为什么使用消息队列?
这是一个很严肃的问题。
- 系统之间解除耦合,可以让不同语言编写的系统通信交互
- 保证服务器负载不会飙升。高大上一点就是流量削峰。
- 让程序变成异步,提高响应速度。把费时任务放到另一个进程或线程去执行。
消息队列用什么?
- redis实现
刚开始学习redis时,一看这个链表不就是给队列准备的吗?
所以,一心扎进去,要写个队列出来。结果就看到redis作者说redis不是拿来搞这个的。
哈哈,所以就作罢。 - RabbitMQ
- Kafka
关于消息队列,我本身也是刚开始琢磨和入门,就不乱做对比。
一般来说kafka用于日志。
RabbitMQ
看了官方的案例后,很是心动。就想着直接用到项目里。
幸亏,我喜欢把文档看完。
结尾有这样一句话:以上案例不能直接用于生产环境。额啊呀喔哦,一库。
注意事项:
- 连接管理
- 错误处理
- 连接恢复
- 并发
- 度量收集
如何保证消息不丢失?
如果消费者使用消息的时候,消息未处理成功,进程死掉。
那么消息队列,在消费者取信息时直接删除就会有丢失消息的风险。
所以RabbitMQ引入了消费者ACK。即不发ACK,消息就不会删除。
setting the fourth parameter to basic_consume to false (true means no ack)
设置basic_consume的第四个参数为false(true意味着不发ACK)
使用命令查看没有得到ACK的消息
sudo rabbitmqctl list_queues name messages_ready messages_unacknowledged
如何保证ACK丢失,代码不出错?
我的想法是把每个任务做标记,已经处理过的任务,再次遇到,直接返回ack。
如何保证RabbitMQ挂掉,队列消息不丢失?
这就用到了持久化的思想,将队列和消息都标记为持久。
说到这里就想到了redis的RDB和AOF。哈哈
设置queue_declare的第三个参数为true
保证新发布的队列持久。不能对已经发布的队列更改
设置消息持久,PHP版本代码
$ msg = new AMQPMessage(
$ data,array('delivery_mode' => AMQPMessage :: DELIVERY_MODE_PERSISTENT)
);
未完待续。。。