redis pubsub
备注:
每个redis client(服务端保存的表示客户端状态的结构体)都有一个dict(pubsub_channels),保存该client监听的所有channel;key是channel,value为空
每个redis client都有一个list(pubsub_patterns),保存该client使用模式订阅的所有channel;
每个redisServer内有一个dict(pubsub_channels),保存该redis server上的所有channel以及监听该channel的所有client(channel为key,client list为value)
每个redisServer内有一个list(pubsub_patterns),保存该server使用模式订阅的所有channel及其client
(1)int pubsubSubscribeChannel(client *c, robj *channel)
1. 调用dictAdd向client的pubsub_channels加入该channel,如果加入成功,说明该client之前没有监听过该channel
1> dictFind查找server.pubsub_channels中是否有该channel,如果有,则直接取出该channel的所有client链表;如果没有,则新创建一个空链表。将client指针加入到该client链表中。
2.通过network发送回应(network代码待学习),通知客户端
(2)int pubsubUnsubscribeChannel(client *c, robj *channel, int notify)
1.调用dictDelete在client的pubsub_channels字典中删除key为channel的元素,如果删除成功,说明client曾监听过该channel
1> dictFind查找server.pubsub_channels查找key为channel的dictEntry,并通过dictGetVal获取该key对应的value,该value是一个client的list—>clients
2> 并在1>中的clients中删除当前client
3> 如果clients为空,则直接在server中删除值为channel的key
2.如果notify为true,则通知client
3.返回1
(3)int pubsubSubscribePattern(client *c, robj *pattern)
1.查找c->pubsub_patterns中有没有pattern,如果有,说明该client已经订阅了该模式;如果没有:
1> 向c->pubsub_patterns中加入pattern,并增加该pattern的引用计数
2> 利用pattern以及c生成一个pubsubPattern类型的对象,挂到server.pubsub_patterns上
2.通知客户端
(4)int pubsubUnsubscribeAllChannels(client *c, int notify): 退订该client所订阅的所有channel
1.获取c的pubsub_channels的字典,依次遍历该字典的所有key(key即channel),调用pubsubUnsubscribeChannel退订,并统计退订的channel的总数量—>count
2.通知客户端
3.返回count
(5)int pubsubUnsubscribeAllPatterns(client *c, int notify)
1.获取c的pubsub_patterns—>li,依次遍历li的所有元素,每一个元素的value是pattern,对于pattern,调pubsubUnsubscribePattern退订,并统计退订数量—>count
2.如果notify && count == 0,通知客户端
3.返回count
(6)int pubsubPublishMessage(robj *channel, robj *message)
1.查找server.pubsub_channels中一channel为key的dictEntry,如果不存在,则跳过;如果存在,获取该dictEntry的value(订阅该channel的client列表),依次向该列表的所有client发送message消息
2.查找server.pubsub_patterns中的所有节点,对于每个节点,获取pubsubPattern类型对象的指针—>pat,使用Glob-style pattern匹配来比较channel与pat->pattern是否匹配,如果匹配,则向pat->client发送message