PEL 如何避免消息丢失?
在客户端消费者读取 Stream 消息时,Redis 服务器将消息回复给客户端的过程中,客户端突然断开了连接,消息就丢失了 。但是 PEL 里已经保存了发出去的消息 ID 。待客户端重新连上之后,可以再次收到 PEL 中的消息 ID 列表 。不过此时 xreadgroup 的起始消息 ID 不能为参数>,而必须是任意有效的消息 ID,一般将参数设为 0-0,表示读取所有的 PEL 消息以及自last_delivered_id之后的新消息 。
死信问题
如果某个消息,不能被消费者处理(处理失败),也就是不能被XACK,这是要长时间处于Pending列表中,即使被反复的转移给各个消费者也是如此 。此时该消息的delivery counter(通过XPENDING可以查询到)就会累加,当累加到某个我们预设的临界值时,我们就认为是坏消息(也叫死信,DeadLetter,无法投递的消息),删除即可 。
删除一个消息,使用XDEL语法,注意,这个命令并没有删除Pending中的消息,因此查看Pending,消息还会在,可以在执行执行XDEL之后,XACK这个消息标识其处理完毕 。
Stream 的高可用
Stream 的高可用是建立主从复制基础上的,它和其它数据结构的复制机制没有区别,也就是说在 Sentinel 和 Cluster 集群环境下 Stream 是可以支持高可用的 。不过鉴于 Redis 的指令复制是异步的,在 failover 发生时,Redis 可能会丢失极小部分数据,这点 Redis 的其它数据结构也是一样的 。
分区 Partition
Redis 的服务器没有原生支持分区能力,如果想要使用分区,那就需要分配多个 Stream,然后在客户端使用一定的策略来生产消息到不同的 Stream 。
Stream小结
Stream 的消费模型借鉴了 Kafka 的消费分组的概念,它弥补了 Redis Pub/Sub 不能持久化消息的缺陷 。但是它又不同于 kafka,Kafka 的消息可以分 partition,而 Stream 不行 。如果非要分 parition 的话,得在客户端做,提供不同的 Stream 名称,对消息进行 hash 取模来选择往哪个 Stream 里塞 。
总的来说,如果是中小项目和企业,在工作中已经使用了Redis,在业务量不是很大,而又需要消息中间件功能的情况下,可以考虑使用Redis的Stream功能 。但是如果并发量很高,资源足够支持下,还是以专业的消息中间件,比如RocketMQ、Kafka等来支持业务更好 。
HyperLogLog
HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等 。
如果你负责开发维护一个大型的网站,有一天产品经理要网站每个网页每天的 UV 数据,然后让你来开发这个统计模块,你会如何实现?
如果统计 PV 那非常好办,给每个网页一个独立的 Redis 计数器就可以了,这个计数器的 key 后缀加上当天的日期 。这样来一个请求,incrby 一次,最终就可以统计出所有的 PV 数据 。
但是 UV 不一样,它要去重,一个简单的方案,那就是为每一个页面一个独立的 set 集合来存储所有当天访问过此页面的用户 ID 。当一个请求过来时,我们使用 sadd 将用户 ID 塞进去就可以了 。通过 scard 可以取出这个集合的大小,这个数字就是这个页面的 UV 数据 。
但是,如果你的页面访问量非常大,比如一个爆款页面几千万的 UV,你需要一个很大的 set 集合来统计,这就非常浪费空间 。如果这样的页面很多,那所需要的存储空间是惊人的 。为这样一个去重功能就耗费这样多的存储空间,值得么?其实需要的数据又不需要太精确,1050w 和 1060w 这两个数字对于老板们来说并没有多大区别,So,有没有更好的解决方案呢?
Redis 提供了 HyperLogLog 数据结构就是用来解决这种统计问题的 。HyperLogLog 提供不精确的去重计数方案,虽然不精确但是也不是非常不精确,Redis官方给出标准误差是 0.81%,这样的精确度已经可以满足上面的 UV 统计需求了 。
HyperLogLog提供了3个命令: pfadd、pfcount、pfmerge 。
例如08-15的访问用户是u1、u2、u3、u4,08-16的访问用户是u-4、u-5、u-6、u-7 pfadd 2013-01-02:user:id u1 u2 u3 u4 u5 u6 //添加元素 PFCOUNT 2013-01-02:user:id //返回元素个数 6 PFADD 2013-01-03:user:id u1 u2 u3 u90 u91 PFMERGE 2013-01-02:user:id 2013-01-03:user:id //合并元素到2013-01-02:user:id PFCOUNT 2013-01-02:user:id //求并集,返回8
以使用集合类型和 HperLogLog统计百万级用户访问次数的占用空间对比:
数据类型
1天
1月
1年
集合类型
80M
2.4G
28G
HyperLogLog
15k
450k
推荐阅读
- 这次彻底读透 Redis !
- 娱乐圈|骨瘦如柴、全身涂白、满嘴假牙,娱乐圈的这些“审美”真不高级
- 高级有质感的唯美句子 优美的句子摘抄
- 许嵩|豆瓣唱功组评许嵩高级假唱:预录保留瑕疵,36岁唱功能进步迅速?
- 方媛|方媛分享新年写真:面容精致高级感强,手拿大红花很应景
- 为什么别人穿卫衣高级显贵 卫衣怎么搭配
- 玉米|别再跟风“网红脸”了,现在“大方脸”才最流行,高级还具辨识度
- fun的比较级和最高级 fun的比较级
- 苹果公司高级产品设计师的一个品牌项目 品牌项目
- 慎独,是一个人最高级的修行 慎独精神