redis怎么做消息队列?
程序员文章站
2022-05-16 20:45:15
...
有个想法,用两个服务器,node处理请求,把数据全部push到 redis缓存队列中,另一个php服务器不断的pop这个队列里的数据然后与mysql交互做持久化。。。大家觉得这么做怎么样 ?
1. Redis自带的PUB/SUB机制,即发布-订阅模式。这种模式生产者(producer)和消费者(consumer)是1-M的关系,即一条消息会被多个消费者消费,当只有一个消费者时即可以看做一个1-1的消息队列,但这种方式并不适合题主的场景。首先,数据可靠性的无法保障,题主的数据最终需要落库,如果消息丢失、Redis宕机部分数据没有持久化甚至突然的网络抖动都可能带来数据的丢失,应该是无法忍受的。其次,扩展不灵活,没法通过多加consumer来加快消费的进度,如果前端写入数据太多,同步会比较慢,数据不同步的状态越久,风险越大,当然可以通过channel拆分的方式来解决,虽然不灵活,但可以规避。这种方案更适合于对数据可靠性要求不高,比如一些统计日志打点。
2. Redis的PUSH/POP机制,利用的Redis的列表(lists)数据结构。比较好的使用模式是,生产者lpush消息,消费者brpop消息,并设定超时时间,可以减少redis的压力。这种方案相对于第一种方案是数据可靠性提高了,只有在Redis宕机且数据没有持久化的情况下丢失数据,可以根据业务通过AOF和缩短持久化间隔来保证很高的可靠性,而且也可以通过多个client来提高消费速度。但相对于专业的消息队列来说,该方案消息的状态过于简单(没有状态),且没有ack机制,消息取出后消费失败依赖于client记录日志或者重新push到队列里面。
最后再来看题主的需求,是希望先写Redis,再异步同步到mysql里面,期望数据的最终一致性。这样带来的好处是前端写的请求飞速啊(不用落盘当然快),问题是很复杂,而且不太合理。假设是合理的话,就应该选择一个更可靠的消息中间件,比如Redis作者开源的Disque,或者阿里开源RocketMQ,以及基于Golang的nsq等,Redis更适合用来存数据。
为什么说题主的需求不合理?
类似于这种先写缓存再同步到DB的,目的是为了减少DB压力,提升前端API性能。题主的方案虽然能做到这两点,但忽略了根本的一点:数据不管存到哪里,都是用来访问(使用)的。但在题主的方案里,写入Redis的数据除了同步到DB里,不接任何访问量,并没有什么卵用,最后DB读的压力上来了,还得把数据重新LOAD回Redis里面,得不偿失。
什么样的架构更合理?
只简单说一下。
异步写入,在百度、58同城使用很多,基本的架构是先抽象出对象访问层(或者只是缓存层),对外屏蔽数据来源(Redis、mysql、others)。对象访问层对于某类数据的格式是定义好的,写的请求来了直接写入缓存(Redis),这样前端的读请求就直接读缓存了,这样存入的数据就有意义(当然了,接了大大的读的量啊)。然后是数据落地(最终一致性问题),简单的可以读RDB文件(实时性不高),复杂一点的可以实现Redis的主从同步协议(实时性高于前一种)。第一种简单,效率低,第二种复杂,效率高。
从Redis谈起(三)—— Redis和消息中间件 这边文章比较详细得讲解了Redis和消息中间件
按题主的场景,需要配置redis的持久化保存,否则可能会出现数据没有保存到mysql中的情形。 pubsub解决的是广播问题,poppush才是解决队列问题。 lpush rpop lpush和lpop适合楼主 Reference [2.3]
什么类的数据?
要求不是很高的话可以用logstash
目前官方没有mysql的output plugins
输入源 redis支持lpush和lpop和、pub/sub模式,改改配置文件就行了,不用redis,用nsq、 kafka之类也有对应的插件
输出插件看官方文档,支持mongodb和elasticsearch lpush/rpop模拟堆栈去存取。 和我毕业设计做的爬虫一样,一个进程持续往redis里rpush数据,另一个进程lpop
回复内容:
如其它答案,基本有两种解决方案1. Redis自带的PUB/SUB机制,即发布-订阅模式。这种模式生产者(producer)和消费者(consumer)是1-M的关系,即一条消息会被多个消费者消费,当只有一个消费者时即可以看做一个1-1的消息队列,但这种方式并不适合题主的场景。首先,数据可靠性的无法保障,题主的数据最终需要落库,如果消息丢失、Redis宕机部分数据没有持久化甚至突然的网络抖动都可能带来数据的丢失,应该是无法忍受的。其次,扩展不灵活,没法通过多加consumer来加快消费的进度,如果前端写入数据太多,同步会比较慢,数据不同步的状态越久,风险越大,当然可以通过channel拆分的方式来解决,虽然不灵活,但可以规避。这种方案更适合于对数据可靠性要求不高,比如一些统计日志打点。
2. Redis的PUSH/POP机制,利用的Redis的列表(lists)数据结构。比较好的使用模式是,生产者lpush消息,消费者brpop消息,并设定超时时间,可以减少redis的压力。这种方案相对于第一种方案是数据可靠性提高了,只有在Redis宕机且数据没有持久化的情况下丢失数据,可以根据业务通过AOF和缩短持久化间隔来保证很高的可靠性,而且也可以通过多个client来提高消费速度。但相对于专业的消息队列来说,该方案消息的状态过于简单(没有状态),且没有ack机制,消息取出后消费失败依赖于client记录日志或者重新push到队列里面。
最后再来看题主的需求,是希望先写Redis,再异步同步到mysql里面,期望数据的最终一致性。这样带来的好处是前端写的请求飞速啊(不用落盘当然快),问题是很复杂,而且不太合理。假设是合理的话,就应该选择一个更可靠的消息中间件,比如Redis作者开源的Disque,或者阿里开源RocketMQ,以及基于Golang的nsq等,Redis更适合用来存数据。
为什么说题主的需求不合理?
类似于这种先写缓存再同步到DB的,目的是为了减少DB压力,提升前端API性能。题主的方案虽然能做到这两点,但忽略了根本的一点:数据不管存到哪里,都是用来访问(使用)的。但在题主的方案里,写入Redis的数据除了同步到DB里,不接任何访问量,并没有什么卵用,最后DB读的压力上来了,还得把数据重新LOAD回Redis里面,得不偿失。
什么样的架构更合理?
只简单说一下。
异步写入,在百度、58同城使用很多,基本的架构是先抽象出对象访问层(或者只是缓存层),对外屏蔽数据来源(Redis、mysql、others)。对象访问层对于某类数据的格式是定义好的,写的请求来了直接写入缓存(Redis),这样前端的读请求就直接读缓存了,这样存入的数据就有意义(当然了,接了大大的读的量啊)。然后是数据落地(最终一致性问题),简单的可以读RDB文件(实时性不高),复杂一点的可以实现Redis的主从同步协议(实时性高于前一种)。第一种简单,效率低,第二种复杂,效率高。
从Redis谈起(三)—— Redis和消息中间件 这边文章比较详细得讲解了Redis和消息中间件
谢谢,希望对大家有帮助。
===============================================================
欢迎各位关注我运营的wx公众号 “中间件架构”,微信号:middlewarearch,最近有在更新Redis相关的文章,会持续更新mysql proxy、Redis、nginx、消息中间件、RPC框架相关的文章,谢谢。
用redis的list, 先lpush, 然后一个线程去rpop数据处理。 如果系统量不大,redis的list push,pop足够了, 如果量大尽量用成熟一些的MQ,不过会重一些,具体要看场景。 redis本身就支持pub/sub模式,可以作为消息队列处理,参见 Command reference按题主的场景,需要配置redis的持久化保存,否则可能会出现数据没有保存到mysql中的情形。 pubsub解决的是广播问题,poppush才是解决队列问题。 lpush rpop lpush和lpop适合楼主 Reference [2.3]
什么类的数据?
要求不是很高的话可以用logstash
目前官方没有mysql的output plugins
输入源 redis支持lpush和lpop和、pub/sub模式,改改配置文件就行了,不用redis,用nsq、 kafka之类也有对应的插件
输出插件看官方文档,支持mongodb和elasticsearch lpush/rpop模拟堆栈去存取。 和我毕业设计做的爬虫一样,一个进程持续往redis里rpush数据,另一个进程lpop
上一篇: PHP取得HTML表单数据无法写入MySQL数据库
下一篇: php 实现进制相互转换_PHP