持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
前言
说到消息中间件,kafka,rabbitMq等大家肯定都很熟悉,其实redis也可以实现消息中间件的功能,并且还有三种实现方式,各有优势和劣势,下面就让我们一起来分析下吧。
队列模式
实现方式
使用list类型的lpush和rpop实现消息队列
缺点
- 做消费者确认ACK麻烦,不能保证消费者消费消息后是否成功处理的问题(宕机或处理异常等),通常需要维护一个Pending列表,保证消息处理确认。
- 不能做广播模式,如pub/sub,消息发布/订阅模型
- 不能重复消费,一旦消费就会被删除
- 不支持分组消费
注意事项
消息接收方如果不知道队列中是否有消息,会一直发送rpop命令,如果这样的话,会每一次都建立一次连接,这样显然不好。 可以使用brpop命令,它如果从队列中取不出来数据,会一直阻塞,在一定范围内没有取出则返回 null
发布订阅模式
实现方式
SUBSCRIBE,用于订阅信道 PUBLISH,向信道发送消息 UNSUBSCRIBE,取消订阅 此模式允许生产者只生产一次消息,由中间件负责将消息复制到多个消息队列,每个消息队列由对应的消费组消费。
优点
- 典型的广播模式,一个消息可以发布到多个消费者
- 多信道订阅,消费者可以同时订阅多个信道,从而接收多类消息
- 消息即时发送,消息不用等待消费者读取,消费者会自动接收到信道发布的消息
缺点
- 消息一旦发布,不能接收。换句话就是发布时若客户端不在线,则消息丢失,不能寻回
- 不能保证每个消费者接收的时间是一致的
- 若消费者客户端出现消息积压,到一定程度,会被强制断开,导致消息意外丢失。通常发生在消息的生产远大于消费速度时
- 可见,Pub/Sub 模式不适合做消息存储,消息积压类的业务,而是擅长处理广播,即时通讯,即时反馈的业务。
基于Sorted-Set的实现
实现方式
Sortes Set(有序列表),类似于java的SortedSet和HashMap的结合体,一方面它是一个set,保证内部 value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。内部实现是 “跳跃表”。
有序集合的方案是在自己确定消息顺ID时比较常用,使用集合成员的Score来作为消息ID,保证顺序, 还可以保证消息ID的单调递增。通常可以使用时间戳+序号的方案。确保了消息ID的单调递增,利用 SortedSet的依据Score排序的特征,就可以制作一个有序的消息队列了。
优点
就是可以自定义消息ID,在消息ID有意义时,比较重要。
缺点
缺点也明显,不允许重复消息(因为是集合),同时消息ID确定有错误会导致消息的顺序出错。
总结
redis的消息模式优点和缺点都很明显,不太完善,所以建议大家在实际业务中要使用消息中间件的话,还是选择专业的消息中间件比较好,比如kafka等,对于消息的重复,丢失,持久化等都有相应的机制来处理,相对来说比较完善,社区也比较活跃。
结束
需要交流学习可以关注公众号【温故知新之java】,互相学习,一起进步