NSQ 源碼分析之Lookupd--DB

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章