今天主要講的是 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