redis学习笔记(20)---发布与订阅
来源:互联网 发布:什么是网络超市? 编辑:程序博客网 时间:2024/06/06 01:10
发布与订阅
redis的发布与订阅功能由以下几个命令实现:
订阅给定的一个或多个频道的信息2PUBLISH
将信息 message 发送到指定的频道 channel3PUBSUB
查看订阅与发布系统状态4PSUBSCRIBE
订阅一个或多个符合给定模式的频道
使用示例
客户端A通过subscribe命令订阅频道“news”,客户端B通过命令publish发布“news”频道的信息,可以发现客户端A会收到这条信息
实现
redis将所有的订阅关系都保存在字典pubsub_channels中,这个字典的键key为被订阅的频道,对应的value是一个链表,指向所有订阅了这个channel的客户端
struct redisServer { ...... dict *pubsub_channels; ......};
每个client也维护了一个这样的字典pubsub_channels,用来记录每个client所订阅的频道。这个字典的key为订阅的频道,value为NULL
typedef struct redisClient { ...... dict *pubsub_channels; ......} redisClient;
假设有三个客户端:client A、client B、client C
其中A订阅了频道news和it,B订阅了频道news,C订阅了频道it
则一个基本的示意图如下:
server的字典中保存了两对key-value对,key为news时,对应的链表中有A和B两个client
key为it时,对应的链表中有A和C两个client。
client A的字典中保存着两个key-value对,key为news和it两个频道,value为NULL
订阅subscribe
void subscribeCommand(redisClient *c) { for (j = 1; j < c->argc; j++) //依次处理每个订阅的频道 pubsubSubscribeChannel(c,c->argv[j]); c->flags |= REDIS_PUBSUB;}int pubsubSubscribeChannel(redisClient *c, robj *channel) { //将订阅的channel加入到对应client的字典中 if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) { //在server的字典中查找channel de = dictFind(server.pubsub_channels,channel); //若server中不存在这个channel if (de == NULL) { //则创建一个链表,将channel-client加入到server中 clients = listCreate(); dictAdd(server.pubsub_channels,channel,clients); } else { //获取channel对应的client链表 clients = dictGetVal(de); } //将这个client加入到链表尾部 listAddNodeTail(clients,c); } //将信息返回给客户端 addReply(c,shared.mbulkhdr[3]); addReply(c,shared.subscribebulk); addReplyBulk(c,channel); addReplyLongLong(c,clientSubscriptionsCount(c)); return retval;}
发布publish
void publishCommand(redisClient *c) { int receivers = pubsubPublishMessage(c->argv[1],c->argv[2]); addReplyLongLong(c,receivers);}int pubsubPublishMessage(robj *channel, robj *message) { //在server的字典中,找到channel de = dictFind(server.pubsub_channels,channel); if (de) { //获取channel对应的client列表,遍历列表 list *list = dictGetVal(de); while ((ln = listNext(&li)) != NULL) { //依次向订阅了这个频道的所有client发送信息 redisClient *c = ln->value; addReply(c,shared.mbulkhdr[3]); addReply(c,shared.messagebulk); addReplyBulk(c,channel); addReplyBulk(c,message); receivers++; } } //向所有匹配模式的用户发送信息 if (listLength(server.pubsub_patterns)) { listRewind(server.pubsub_patterns,&li); channel = getDecodedObject(channel); while ((ln = listNext(&li)) != NULL) { pubsubPattern *pat = ln->value; ...... } } return receivers;}
本文所引用的源码全部来自Redis3.0.7版本
redis学习参考资料:
https://github.com/huangz1990/redis-3.0-annotated
Redis 设计与实现(第二版)
0 0
- redis学习笔记(20)---发布与订阅
- redis学习笔记 发布与订阅
- 【学习笔记】Redis(3)-发布与订阅
- Redis学习笔记(6)消息的订阅与发布
- 《Redis设计与实现》学习笔记-发布订阅与事务
- [Redis学习笔记]-Redis 发布订阅(充当消息组件)
- Redis学习笔记8--Redis发布/订阅
- Redis学习笔记8--Redis发布/订阅
- 发布与订阅消息--Redis学习笔记八
- Redis系列学习笔记10 发布与订阅
- 发布与订阅消息--Redis学习笔记八
- Redis 学习笔记(一):安装配置、发布订阅与事务
- 六 redis学习笔记之发布订阅
- redis学习笔记六之发布订阅
- redis学习笔记六之发布订阅
- 六 redis学习笔记之发布订阅
- 《Redis源码学习笔记》发布/订阅
- redis学习笔记:发布和订阅
- Android实训案例(八)——单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局
- ubuntu14.10安装五笔\拼音中文输入法--不适用于16.04
- Strategy Design Pattern
- .gradle的学习总结(一)
- 在Linux下搭建dubbo管理控制台
- redis学习笔记(20)---发布与订阅
- Tomcat安装和使用
- POJ 3180 The Cow Prom
- 通过eclipse创建maven项目
- ACM编程比赛入门题目之蛇形矩阵 CodeVS/wikioi 1160
- CSS ToolTip 实现方法1
- 【结论】【位运算】求1~n异或的结果(NKOJ 2466)
- Invert Binary Tree 递归
- 如何把sqlserver中的列转换成行,行转换成列,显示