##1、选择推送还是拉取 在消息系统中,一般有两种消费模式:服务端推送和客户端拉取。若系统主要面向公网的服务器,采用推送模式,有如下优点 :
- 实时性高。从消息的产生到推送,总体平均延时100毫秒,最大不超过200毫秒。
- 服务器压力小。相比于拉取模式,每次推送都有数据,避免空轮询消耗资源。
- 使用简便。使用拉取模式,客户端需要维护消费队列的位置,以及处理多客户端同时消费的并发问题。而在推送模式中,这些事情全部由服务器完成,客户端仅需要启动SDK监听消息即可,几乎没有使用门槛。
当然,系统也支持客户端拉取,推送系统会将客户端的拉取请求转换为推送请求,直接返回。推送服务器会据此请求推送相应数据到客户端。即拉取异步化,如果客户端没有新产生的数据,不会返回任何数据,减少客户端的网络消耗。
##2、消息队列如何实现消息的顺序消费
-
在很多场景下,如何保证队列信息的有序处理是一个棘手的问题。如下图,假定分布式队列保证请求严格有序,请求ri2和ri1都是针对同一数据记录的不同状态,ri2的状态比ri1的状态新。T1、T2、T3和T4代表各个操作发生的时间,并且 T1 < T2 < T3 < T4("<"代表早于)。
采用多消费者架构,这两条记录被两个消费者(Consumer1和Consumer2)处理后更新到数据库里面。Consumer1虽然先读取ri1但是却后写入数据库,这就导致,新的状态被老的状态覆盖,所以多消费者不保证数据的有序性。
-
所以全局顺序是不可能实现的,但是可以实现偏序。
-
如果push模式的消息队列,支持分区,单分区只支持一个消费者消费,并且消费者只有确认一个消息消费后才能push送另外一个消息,还要发送者保证全局顺序唯一,听起来也能做顺序消息,但成本太高了,尤其是必须每个消息消费确认后才能发下一条消息,这对于本身堆积能力和慢消费就是瓶颈的push模式的消息队列,简直是一场灾难。 反观pull模式,如果想做到全局顺序消息,就相对容易很多:
producer对应partition,并且单线程。
consumer对应partition,消费确认(或批量确认),继续消费即可。 所以对于日志push送这种最好全局有序,但允许出现小误差的场景,pull模式非常合适。如果你不想看到通篇乱套的日志~~
Anyway,需要顺序消息的场景还是比较有限的而且成本太高,请慎重考虑。
REF: