今天主要讲的是 Lookupd数据存储方式(DB)。Lookupd主要保存三种信息,一是 NSQD 身份信息,二是 NSQD Topic 信息,三是 NSQD Topic 中 Channel 信息。
主要代码文件:
1.nsqlookupd/registration_db.go
结构体:
type PeerInfo struct { //伙伴信息(nsqd)
lastUpdate int64 //上次心跳检查时间
id string
RemoteAddress string `json:"remote_address"`
Hostname string `json:"hostname"`
BroadcastAddress string `json:"broadcast_address"`
TCPPort int `json:"tcp_port"`
HTTPPort int `json:"http_port"`
Version string `json:"version"`
}
type Producer struct { //nsqd 封装
peerInfo *PeerInfo //nsqd 信息
tombstoned bool //墓碑状态
tombstonedAt time.Time //墓碑状态开始时间
}
type RegistrationDB struct { // 注册表
sync.RWMutex
registrationMap map[Registration]ProducerMap
}
type Registration struct { //注册信息
Category string //现在主要有三种,channel,topic,及 nsqd 的身份信息(client)
Key string //一个确定的值(topic channel 的名称等)或者 *
SubKey string //一个确定的值(topic channel 的名称等)或者 *
}
type Registrations []Registration
type Producers []*Producer
type ProducerMap map[string]*Producer
上面的结构体,总结关系如下:
FindRegistrations 函数 查找符合条件的注册记录
func (r *RegistrationDB) FindRegistrations(category string, key string, subkey string) Registrations {
r.RLock()
defer r.RUnlock()
/*
如果 key 和 subkey 都不是*。则是精确查找
*/
if !r.needFilter(key, subkey) {
k := Registration{category, key, subkey}
if _, ok := r.registrationMap[k]; ok {
return Registrations{k}
}
return Registrations{}
}
results := Registrations{}
for k := range r.registrationMap { //匹配*查找
if !k.IsMatch(category, key, subkey) {
continue
}
results = append(results, k)
}
return results
}
IsMatch 函数 匹配 *
func (k Registration) IsMatch(category string, key string, subkey string) bool {
if category != k.Category {
return false
}
if key != "*" && k.Key != key {
return false
}
if subkey != "*" && k.SubKey != subkey {
return false
}
return true
}
FindProducers 查找符合条件的peerInfo
func (r *RegistrationDB) FindProducers(category string, key string, subkey string) Producers {
r.RLock()
defer r.RUnlock()
if !r.needFilter(key, subkey) { //精确查找
k := Registration{category, key, subkey}
//返回切片数据
return ProducerMap2Slice(r.registrationMap[k])
}
results := make(map[string]struct{})
var retProducers Producers
for k, producers := range r.registrationMap {
if !k.IsMatch(category, key, subkey) { //匹配*
continue
}
//收集producer
for _, producer := range producers {
_, found := results[producer.peerInfo.id]
if found == false {
results[producer.peerInfo.id] = struct{}{}
retProducers = append(retProducers, producer)
}
}
}
return retProducers
}
其他的查询函数,基本 FindProducers 和 FindRegistrations 相似,在这里就不需要赘述.至于其他的函数,都是简单的map操作,也不做详细说明。
其他函数:
AddRegistration:向注册表注册一条信息
AddProducer:添加一条nsqd信息
RemoveProducer:移除一条nsqd信息
RemoveRegistration:移除一条注册表信息
LookupRegistrations :查找指定ID的注册信息
Filter:过滤查找
FilterByActive:查找活跃nsqd
总结:registration_db 定义了一种数据结构,来管理相关信息,可以简单的理解成主表 + 子表的形式。该文件主要实现的就是"数据表”的增删改查。
下一次分享:lookupd 中的协议 lookup_protocal_v1