首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

怎样“安全高效”的进行队列消费

队列简介

广义上只要是可以维持先进先出(FIFO)原则的数据存储方式都可以称为队列,小至基本的数据结构:array,list,queue等线性表结构,大至各项软件服务比如带自增键的mysql表,MongoDB的collection,redis的list,又或常见的消息队列,ActiveMQ,RabbitMQ,Kafka等,更有第三方消息服务,AmazonSQS, AliyunMNS等。

在现代互联网高流量的架构中,消息队列一直占据着核心地位,多用在要求系统解耦、流量削峰、高并发缓冲、消息订阅、数据同步等强需求功能上。队列作为上下游的中间件,为下游缓冲数据的同时,也需要下游系统及时消费,以避免队列发生数据堆积,从而影响正常业务流程。

这篇文章,主要就是介绍下消息队列下游消费端要注意的一些事情,欢迎大家探讨。

安全的消费

消费消息队列怎么样才能算是“安全的”呢?其最基本是要保证下面两点:

不丢队列数据

保证FIFO时序

怎么理解这两条,拿即时聊天系统(IM)的消息队列举例,就是既要保证不会漏掉某条的聊天记录,并且也要按时间先后顺序逐条显示。本文主要分享下,下游消费端的安全的消费,至于消息队列本身安全机制,这里就不在探讨。有兴趣的同学,可以去了解各种消息队列的连接池、QoS、去重等机制。

效率的消费

提升队列的消费效率,是每个消费端都要思考的东西。毕竟消息堆积,不仅仅是队列的负载变高,同时意味着下游的接受数据延迟变长,进而导致数据一致性、用户体验等一系列问题。

优化下游消费进程

避免因为不合理的设计或开发导致的消费进程阻塞;比如第三方请求、复杂数据库处理或复杂cpu运算等场景就不适合放到消费进程中。

批量处理

批量拉取消息,批量查询,批量写,提升整体吞吐率。

并发多进程消费

一般情况,消息队列本身的吞吐量不是瓶颈(特大消息量的大佬们请无视^.^),下游消费端的消费速率才是瓶颈,在前两条不能在优化的情况下,并发是最常用的手段。

并发多进程的“安全消费”

大家都知道多进程执行的情况,因为执行环境和时间的不确定性,消息的时序没有办法保证,从而导致乱序。目前主要有两种解决方案:

低粒度的时序

有了这个妥协的时序,就使得多进程消费有了可行性。我们可以将同一个聊天session的所有消息全部映射到同一个队列上,由单进程串行按时序消费该队列,从而保证同一session的时序性。同样在一个电子商务系统,同一个订单的下单-支付-库存-物流等串行逻辑,也可以依赖orderid的低粒度时序,来实现多线程消费。

低粒度时序 示例图

使用消息版本号

上游系统在生成消息时,同时添加该消息的版本号,使得下游多进程消费时,可以通过消息内的含有版本号来决定是否使用该消息。该方案适用于下游系统不关心过程数据,只关心数据结果的场景。

几种非常规的队列

自增mysql表

该队列的时序主要体现在自增键上,键值越小需先消费。多进程消费时,每个进程都会读取表中的每条数据,再通过hash映射来来决定是否在当前进程进行消费,不在当前进程映射的数据跳过。为了消费安全,可以记录每个进程当前消费的自增键,从而在进程异常退出的时候,也可以保证在下次重启时继续消费。至于hash映射,最常用算法就是键值取模,或者依赖低粒度时序字段取模。

MongoDb的collection

mongodb-collection有个自带的主键_id(ObjectID类型),ObjectID本身就是支持分布式时序的,(ObjectId的结构,有兴趣的同学可以看一下),故使用依赖该主键也可以实现队列。_id越小的记录就可以最先消费。至于多进程消费逻辑,可以参照自增mysql表

致力于技术分享,欢迎关注转发

leesenlen_blog

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190114G0RVXP00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券