《Redis 设计与实现》读书笔记(四)
独立功能的实现
十八、发布和订阅
发布和订阅由下面几条命令组成
- PUBLISH,发布消息,例如PUBLISH <频道名> <消息内容>
- SUBSCRIBE,订阅某个频道 SUBSCRIBE <频道名>
- UNSUBSCRIBE 退订某个频道
- PSUBSCRIBE,订阅某个模式频道,例如news.* PSUBSCRIBE <模式频道名>
- PUNSUBSCRIBE,退订某个模式频道
数据结构
- redisServer
- dict *pubsub_channels key是频道名,value是一个链表,保存所有订阅这个频道的客户端
- list *pubsub_patterns 链表,值是pubsub_pattern对象,保存客户端和模式频道
操作
- 订阅频道。例如命令 SUBSCRIBE news.it
- 查看pubsub_channels 字典是否有news.it这个key,如果有,把客户端添加到链表后面,如果没有,新建一个链表,设置news.it这个key指向这个链表
- 退订频道。例如命令 UNSUBSCRIBE news.it
- 找到news.it对应的链表,遍历链表,找出当前客户端,然后删除
- 订阅模式频道。例如命令 PSUBSCRIBE news.*
- 在pubsub_patterns 链表后面添加一个pubsub_pattern对象,保存这个客户端的信息和news.*
- 退订模式频道。例如命令 PUNSUBSCRIBE news.*
- 遍历pubsub_patterns 链表,删除客户端等于当前客户端,模式等于news.*的对象
- 发布消息,例如 PUBLISH news.it news11
- 遍历pubsub_channels[news11]链表,把消息发送给链表中的所有客户端
- 遍历pubsub_patterns链表,如果模式和news11匹配,就发送消息给对应的客户端
其他命令
这些命令是2.8后新增的
- PUBSUB CHANNELS [pattern] 模式是可选的
- 如果没有pattern 返回服务端所有被订阅的频道
- 如果有,返回匹配上pattern的所有频道
- PUBSUB NUMSUB [channel-1 channel-2 。。。] 可以输入多个频道
- 返回每个频道的订阅者数量,也就是pubsub_channels[channel-1]链表的长度
- PUBSUB NUMPAT
- 返回服务端当前被订阅的模式频道数量,也就是pubsub_patterns 链表的长度。
十九、事务
Redis通过MULTI EXEC WATCH命令来实现事务
事务例子
MULTI
get test
set test 111
EXEC
数据结构
- redisClient 客户端对象
- multiState mstate 事务状态
- multiState 事务状态对象
- multiCMD *commands 保存改事务下面的所有命令FIFO原则
- int count 已入队的命令数量
- multiCmd 命令对象
- robj **argv 命令参数
- int argc 参数数量
- struct redisCommand * cmd 命令对象
流程
- 当执行MULTI命令,改客户端进入事务模式。会打开客户端对象的flags属性的REDIS_MULTI标识
- 当执行get和set命令,会把这些命令的信息加入到commands队列。但是不会立刻执行
- 当执行EXEC命令。服务端把客户端的commands命令拿出来,逐条执行,然后返回每条的结果
- 在MULTI和EXEC命令之间的所有命令,都不会立刻执行。
- 执行完EXEC命令后,清空客户端对象的事务状态,包括flags标识,multiState对象等
WATCH命令
WATCH命令是一个乐观锁,可以在EXEC命令开始前监视任意数量的数据库键。
例如事务
WATCH name
MULTI
set name kevinlu
EXEC
如果在WATCH后,EXEC前,name这个键被修改了,执行EXEC后,会返回空给客户端。
实现:
- redisDb的对象的dict *watched_keys变量用于保存当前watch命令的所有key和客户端对象。key是数据库的键,value是链表,值是客户端对象
- 当执行WATCH命令,Redis会在watched_keys加上数据
- 当Redis执行修改命令时,会执行touchWatchKey操作。具体就是在watched_keys找出修改的key的链表,对链表中的所有客户端对象,打开客户端的REDIS_DIRTY_CAS标识,表示这些客户端WATCH的key中至少有一个被修改了
- 当客户端执行EXEC命令时,检查REDIS_DIRTY_CAS标识是否被打开,如果是,返回空。否则才执行事务。
事务性质(ACID)
- A 原子性。因为Redis把事务打包在一起执行,所以是具有原子性的。要不成功,要不失败。但是Redis不会有事务回滚,也就是例如第2条命令失败了,第1条命令不会回滚,第3条命令也会继续执行。作者是命令回滚太复杂,不适合Redis的简单原则。
- C 一致性。事务执行前和执行后都能保证一致性。一致性是指不会破坏数据库的设计(这个好笼统,不知道具体的边界)。Redis的命令执行错误主要有两种:
- 入队错误。例如命令不存在。这个在EXEC前就会被发现并被Redis拒绝。所以这个不会破坏一致性。
- 执行错误。命令执行的时候错误了,例如key是string类型,却用rpush操作。对于这种错误,Redis不会终止事务的执行,也不会回滚。所以这些命令不会执行,所以也不会破坏一致性(不太明白这个,都有一个条命令执行失败了,怎么会不破坏一致性?)
- 数据库停机。如果不保存数据,那一致性就不用考虑了,因为重启后都是空白数据库。如果保存数据,事务会落地,所以也能保证一致性
- I 隔离性。由于Redis是单线程执行,所以不会有事务并发问题。所以可以保证隔离性。
- D 耐久性。事务执行成功后保证可以持久化到数据库。由于Redis在执行指定命令,例如BGSAVE的时候,才会进行持久化,所以不能保证耐久性。
- 可以使用AOF 设置appendfsync来保证耐久性
《Redis 设计与实现》读书笔记(四)的更多相关文章
- JAVA编程思想读书笔记(四)--对象的克隆
接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...
- JAVA编程思想读书笔记(五)--多线程
接上篇JAVA编程思想读书笔记(四)--对象的克隆 No1: daemon Thread(守护线程) 参考http://blog.csdn.net/pony_maggie/article/detail ...
- JAVA编程思想读书笔记(二)--容器
接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
- Java编程思想读书笔记之内部类
现在是够懒得了,放假的时候就想把这篇笔记写出来,一直拖到现在,最近在读<Java编程思想>,我想会做不止这一篇笔记,因为之前面试的时候总会问道一些内部类的问题,那这本书的笔记就从内部类开始 ...
- Java编程思想读书笔记(一)【对象导论】
2018年1月7日15:45:58 前言 作为学习Java语言的经典之作<Java编程思想>,常常被人提起.虽然这本书出版十年有余,但是内容还是很给力的.很多人说这本书不是很适合初学者,我 ...
- <Java编程思想>读书笔记(1)-对象导论、一切都是对象
1.面向对象编程:OOP (Object-oriented Programming) 2.Alan Kay 总结的面向对象语言5个基本特性: 1) 万物皆为对象 2) 程序是对象的集合,他们通过发送消 ...
- Java编程思想读书笔记(二)【一切都是对象】
begin 2018年1月9日17:06:47 第二章 一切都是对象 Java语言假设我们只进行面向对象的程序设计. 2.1 用引用操纵对象 每种编程语言都有自己的操纵内存元素的方式 操纵内存元素的方 ...
- Java编程思想读书笔记
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- java编程思想读书笔记三(11-21)
十一:持有对象 >持有对象实例 ●数组将数字与对象联系起来.它保存类型明确的对象,查询对象时,不需要对结果做类型转换.他可以是多维的. 可以保存基本的数据类型.但是,数组一旦生成,容量就不会在变 ...
随机推荐
- poj2826(细节,计算几何)
题目链接:https://vjudge.net/problem/POJ-2826 题意:平面中摆两根木棍,雨水从上垂直下落,问木棍中能乘多少水. 思路: 细节很多,坑QAQ.. 首先不相交时肯定为0. ...
- [转帖]什么是WAL?
什么是WAL? https://www.cnblogs.com/hzmark/p/wal.html 原来数据库与消息中间件 用的是相同的模式 都是基于 顺序写的性能优于 离散写 series 强于sc ...
- SpringBoot以WAR包部署遇到的坑---集合贴
⒈忽略tomcat的context-path 方式一: 停止tomcat服务,删除tomcat安装目录的webapps目录下的ROOT目录,将打成的WAR包重命名为ROOT.war,重启tomcat服 ...
- k-近邻(KNN) 算法预测签到位置
分类算法-k近邻算法(KNN): 定义: 如果一个样本在特征空间中的k个最相似 (即特征空间中最邻近) 的样本中的大多数属于某一个类别,则该样本也属于这个类别 来源: KNN算法最早是由Cover和H ...
- 以太坊再爆高危漏洞!黑客增发ATN 1100万枚token事件始末
事情发生在5月中旬,ATN技术人员发现Token合约由于存在漏洞受到攻击.不过ATN基金会随后透露,将销毁1100万个ATN,并恢复ATN总量,同时将在主链上线映射时对黑客地址内的资产予以剔除,确保原 ...
- nginx运行基本指令
测试配置文件: 安装路径下的/nginx/sbin/nginx -t启动: 安装路径下的/nginx/sbin/nginx停止 安装路径下的/nginx/sbin/nginx -s stop 或者是: ...
- C#基础知识 (转)
https://www.cnblogs.com/zhouzhou-aspnet/articles/2591596.html(原文地址) 本文是一个菜鸟所写,本文面向的人群就是像我这样的小菜鸟,工作一年 ...
- [NOIP2018模拟赛10.19]只会暴力报告
闲扯 今天又是暴力满满(并不)的一天呢 昨天老师说了分数要正态分布,今天看起来...不过暴力分很多,虽然我人太傻逼又没打满 T1 woc?不是说送分的吗,看起来又是个树形DP神题,暴力告辞,链上的搞一 ...
- 查找最大和次大元素(JAVA版)(分治法)
问题描述:对于给定的含有n个元素的无序序列,求这个序列中最大和次大的两个不同元素. 问题求解分析(分治法):先给出无序序列数组a[low...high].第一种情况为当数组中只有一个元素时,此时只存在 ...
- C#中DateTime.Ticks
DateTime.Ticks:表示0001 年 1 月 1 日午夜 12:00:00 以来所经历的 100 纳秒数,即Ticks的属性为100纳秒(1Ticks = 0.0001毫秒). Unix时间 ...