Zookeeper 分布式应用的分布式协调服务
Zookeeper简介
ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,
一些基本应用场景:分布式锁服务、配置维护、组服务、分布式消息队列、分布式通知/协调等。
Zookeeper客户端
客户端连接一个单独的ZooKeeper服务端。客户端维护了一个TCP 的连接,
通过它来发送请求、获取响应、获取watch事件以及发送心跳。
如果与服务端的连接断了,客户端将会连到其他的服务端。
以golang客户端go-zookeeper为例
1
2
3
4
5
6
7
8
9
10
|
func Connect(servers []string, sessionTimeout time.Duration, options ...connOption) (*Conn, <-chan Event, error) {
/*...*/
go func() {
conn.loop(ctx) //循环获取服务器地址建立连接,并发送心跳和接收消息
conn.flushRequests(ErrClosing)
conn.invalidateWatches(ErrClosing)
close(conn.eventChan)
}()
return conn, ec, nil
}
|
Zookeeper数据结构
ZooKeeper命名空间中的Znode,兼具文件和目录两种特点。既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,
又像目录一样可以作为路径标识的一部分。图中的每个节点称为一个Znode。
ZooKeeper数据结构特点:
- znode标识:每个子目录项都是一个znode,znode被它所在的路径唯一标识,如 Server1 这个 znode 的标识为 /NameService/Server1
- znode可以有子节点目录: 每个 znode 可以存储数据,
EPHEMERAL
类型的目录节点不能有子节点目录
- znode有版本:每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据
- znode 可以是临时节点: 一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除
- znode 的目录名可以自动编号: 如 App1 已经存在,再创建的话,将会自动命名为 App2
- znode 可以被监控: 这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端
每个Znode由3部分组成:
- stat:状态信息, 描述该Znode的版本, 权限等信息
- data:Znode关联的数据
- children:Znode下的子节点
watch事件类型
1
2
3
4
5
6
7
8
9
|
const (
EventNodeCreated EventType = 1 // 创建节点成功通知
EventNodeDeleted EventType = 2 // 节点移除通知
EventNodeDataChanged EventType = 3 // 当前节点数据变化通知
EventNodeChildrenChanged EventType = 4 // 子节点列表变化通知
EventSession EventType = -1
EventNotWatching EventType = -2
)
|
watch事件状态
1
2
3
4
5
6
7
8
9
10
11
12
|
const (
StateUnknown State = -1 // 未知状态
StateDisconnected State = 0 // 断开连接
StateConnecting State = 1 // 连接中
StateAuthFailed State = 4 // 权限异常
StateConnectedReadOnly State = 5 // 当前连接仅支持读操作
StateSaslAuthenticated State = 6
StateExpired State = -112 // 会话超时
StateConnected = State(100) // 已经连接
StateHasSession = State(101)
)
|
创建节点时flags参数类型:
1
2
3
4
5
6
|
const (
// 0 持久节点
FlagEphemeral = 1 // 临时节点
FlagSequence = 2 // 顺序节点
FlagTTL = 4 //
)
|
创建节点时控制权限参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// Constants for ACL permissions
const (
PermRead = 1 << iota // 可以读取节点数据及显示子节点列表
PermWrite // 可以设置节点数据
PermCreate // 可以创建子节点
PermDelete // 可以删除子节点(仅下一级节点)
PermAdmin // 可以设置节点访问控制列表权限
PermAll = 0x1f // 所有权限
)
// world模式,anyone是唯一值,表示所有人
func WorldACL(perms int32) []ACL {
return []ACL{{perms, "world", "anyone"}}
}
// auth模式,表示所有通过身份验证的用户
func AuthACL(perms int32) []ACL {
return []ACL{{perms, "auth", ""}}
}
|
Znode状态信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
type Stat struct {
Czxid int64 // 创建节点的事物ID
Mzxid int64 // 修改节点的事务ID
Ctime int64 // 创建时间(milliseconds)
Mtime int64 // 最后修改时间(milliseconds)
Version int32 // 数据版本变更次数
Cversion int32 // 子节点进行的更改次数(不包括子节点)
Aversion int32 // 权限版本变更次数
EphemeralOwner int64 // 临时节点会话属性ID
DataLength int32 // 数据长度
NumChildren int32 // 子节点数(不包括子子节点)
Pzxid int64 // 子节点变更的事务ID
}
|
参考