首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TimeLine模型下确保消息有序不丢

TimeLine模型下确保消息有序不丢

作者头像
普通程序员
发布2019-10-23 11:54:09
1.1K0
发布2019-10-23 11:54:09
举报
文章被收录于专栏:普通程序员普通程序员

通过《基于TimeLine模型的消息同步机制》一文,我们了解到Timeline模型有非常多的优点,也是钉钉采用的消息同步机制。实际工作中,我们也将该模型应用在了C端用户的消息场景中。实施过程中也遇到了一些问题,积累了一些经验。本文将介绍极端情况丢失消息的问题及解决办法。

一、Timeline概念

Timeline可以简单理解为是一个消息队列,某个用户所有的消息都存储在这个Timeline中,用户的各个端可以从这个队列中同步各自消息。

图中的例子中,消息发送方是A,消息接收方是B,同时B存在多个接收端,分别是B1、B2和B3。A向B发送消息,消息需要同步到B的多个端,待同步的消息通过一个Timeline来进行交换。A向B发送的所有消息,都会保存在这个Timeline中,B的每个接收端都是独立的从这个Timeline中拉取消息。每个接收端同步完毕后,都会在本地记录下最新同步到的消息的msgid,即最新的一个位点,作为下次消息同步的起始位点。

二、丢失消息的原因

理论上讲,Timeline模型能够确保消息不重不漏。实际实施中,根据系统架构特点以及选用中间件的不同,极端情况下,可能出现丢消息。最主要的原因是某一时刻,Timeline中的数据不连续或不完整。

举个例子,如果用户有两条时间间隔非常近的消息msg1、msg2,对应的msgId分别为10,11。由于时间很相近,(分布式系统)某些情况下可能出现msg2先写入TimeLine,如果此时用户某个端正好执行Sync同步消息,将同步到最大msgId为11的msg2消息,造成msg1丢失(msg1此时还没有写入TimeLine)。

下图是IM系统的结构。Dispatcher负责生成msgId,通过Kafka传递给具体业务逻辑处理单元Processor(名称与图不完全一致),Processor将消息写入Redis/MongoDb。

这个过程中有三个环节会造成顺序不一致

1、消息msgid在Dispatcher节点生成(采用类snowflake算法),由于不同节点时间可能存在误差,有可能造成msgid和时序不一致

2、Kafka有多个patition,不同patition不能保证消息顺序

3、Processor是多实例部署,多线程处理,也不能保证顺序

三、解决办法

1、服务端严格有序

应用神奇的hash算法,把属于同一用户的消息路由到相同的Dispatcher节点,相同的Kafka分区,相同的Processor线程即可保证消息循序性。但是对于群消息,极端情况下还是可能出现时序问题(当然要丢消息还需要客户端正好执行Sync同步,这个概率极低)

2、客户端补偿

服务端为Timeline中的每条消息都进行严格递增编号,叫做sequenceid。从1开始,2、3、4……加一递增。这样,客户端拉取到消息,能够通过sequenceid感知是否丢失消息。如果丢失消息,可以再次尝试拉取。

这里有个问题,这个严格编号服务我们利用了redis,万一redis数据丢失怎么办呢?个人收件箱Timeline中最新一条消息就是已有的最大编号,redis数据万一丢失了可以从这条消息中取得之前的最大编号。

通过这两个方法,能够确保消息可靠性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 普通程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档