Redis高级数据结构Stream和HyperLogLog( 四 )


5M
可以看到,HyperLogLog内存占用量小得惊人,但是用如此小空间来估算如此巨大的数据,必然不是100%的正确,其中一定存在误差率 。前面说过,Redis官方给出的数字是0.81%的失误率 。
Redis事务
简单地说,事务表示一组动作,要么全部执行,要么全部不执行 。例如在社交网站上用户A关注了用户B,那么需要在用户A的关注表中加入用户B,并且在用户B的粉丝表中添加用户A,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况 。
multi //开启事务 exec //事务结束,开始执行 discard //停止执行,代替exec,它们之间的命令是原子顺序执行的
可以看到sadd命令此时的返回结果是QUEUED,代表命令并没有真正执行,而是暂时保存在Redis中的一个缓存队列(所以discard也只是丢弃这个缓存队列中的未执行命令,并不会回滚已经操作过的数据,这一点要和关系型数据库的Rollback操作区分开) 。如果此时另一个客户端执行sismember u:a:follow ub返回结果应该为0 。

Redis高级数据结构Stream和HyperLogLog

文章插图
 
事务中出现错误
  1. 命令错误,属于语法错误,会造成整个事务无法执行
  2. 运行时错误,例如用户B在添加粉丝列表时,误把sadd命令(针对集合)写成了zadd命令(针对有序集合),这种就是运行时命令,因为语法是正确的,那第一条执行成功,第二条执行失败,
 
可以看到Redis并不支持回滚功能,开发人员需要自己修复这类问题 。
watch
有些应用场景需要在事务之前,确保事务中的key没有被其他客户端修改过,才执行事务,否则不执行(类似乐观锁) 。Redis 提供了watch命令来解决这类问题 。
Redis高级数据结构Stream和HyperLogLog

文章插图
 
可以看到“客户端-1”在执行multi之前执行了watch命令,“客户端-2”在“客户端-1”执行exec之前修改了key值,造成客户端-1事务没有执行(exec结果为nil) 。
Pipeline和事务的区别
1、pipeline是客户端的行为,对于服务器来说是透明的,可以认为服务器无法区分客户端发送来的查询命令是以普通命令的形式还是以pipeline的形式发送到服务器的;
2、而事务则是实现在服务器端的行为,用户执行MULTI命令时,服务器会将对应这个用户的客户端对象设置为一个特殊的状态,在这个状态下后续用户执行的查询命令不会被真的执行,而是被服务器缓存起来,直到用户执行EXEC命令为止,服务器会将这个用户对应的客户端对象中缓存的命令按照提交的顺序依次执行 。
3、应用pipeline可以提服务器的吞吐能力,并提高Redis处理查询请求的能力 。
存在问题,当通过pipeline提交的查询命令数据较少时(可以被内核缓冲区所容纳),Redis可以保证这些命令执行的原子性 。然而一旦数据量过大,超过了内核缓冲区的接收大小,那么命令的执行将会被打断,原子性也就无法得到保证 。
因此pipeline只是一种提升服务器吞吐能力的机制,如果想要命令以事务的方式原子性的被执行,还是需要事务机制,或者使用更高级的脚本功能以及模块功能 。
4、可以将事务和pipeline结合起来使用,减少事务的命令在网络上的传输时间,将多次网络IO缩减为一次网络IO 。
Redis提供了简单的事务,之所以说它简单,主要是因为它不支持事务中的回滚特性,同时无法实现命令之间的逻辑关系计算,当然也体现了Redis 的“keep it simple”的特性 。
 
作者:咖啡冲不冲 链接:https://juejin.cn/post/7184007074945171513 来源:稀土掘金

【Redis高级数据结构Stream和HyperLogLog】


推荐阅读