BirdTalk IM集群中消息流转策略讨论
BirdTalk IM集群中消息流转策略讨论
目前群聊的存储策略是1写多读方案;每个群组一个队列,按时间顺序排列,不区分用户;
私聊的存储是写扩散的,每个人都有自己的消息队列,按时间顺序 保存所有的消息,不区分会话;
1、单机模式
1.1 私聊消息
登录的算法,要求用户按照ID指定的服务器,而不是按照IP,这是因为ip经常发生变动;用ID可以保证各个会话终端都在一个服务器上;
私聊有3类确认:
1)服务器入库的成功回执;
2)对方给的送达回执;
3)阅读回执;
客户端需要一个定时器,对发送的消息监控,如果30秒没有回复成功,认为发送失败;最多尝试3次;
对于没有送达回执的消息,需要向服务区发送查询请求,(回执可能丢失),查询回执会让服务器对在线用户尝试重发;只要客户端实现的正确的,就肯定不会丢消息并应答送达回执;阅读回执可有可无;
1.2 群聊消息
对于单机的群聊,对于内存中没有的用户,就是不在线的,不转发数据;
当群聊用户某个时间点登录,那么先做准备工作,标记自己状态,然后开始同步历史数据,这样能保证数据不丢失。
2、集群模式
不同于TINODE集群直接使用RPC连接,而是使用消息队列同步消息,当一条消息需要从一台服务器路由到另一一台服务器时,可以使用kafka的一个主题来实现,每个服务器一个单独的主题用于接收;这比每对服务器都要建立一个连接好多了,如果集群有1000台服务器,那么就需要1000个TCP连接。
路由可以使用redis辅助实现,为了及时通知对方发现路由变更,也需要使用一个公共的主题来广播消息。
2.1 私聊消息
假如有服务器A和服务器B,小明在服务器A,小美在服务器B;
开始时候小美不在线,消息都写入了小美的消息队列;当某一时刻,小美在服务器B登录,那么:
1)先告知集群当前此用户的此会话在服务器B;
2)执行一次同步历史数据之后,准备接收来自其他服务器用户的数据,当然也包括服务器A;
这里存在一个问题:
服务器A上的小明发现小美上线前,将数据写到了小美的消息队列,但是其实此刻,小美已经上线并且同步完数据了;那么这条消息就会被服务器遗漏,小美客户端也无从得知该条消息;
这个问题的产生主要是路由状态的扩散需要时间,异步的同步历史数据会造成潜在的数据丢失。
但是,与群聊不同,私聊是有回执的;当小明发现小美一直都没有回复接收回执,则会一直查询回执,服务器A会重发消息,此时如果发现了消息路由在服务器B,可以保证消息重发而不丢失;
但是有个缺点也很明显:有可能之前丢失的消息会在客户端出现乱序!!!
2.2 群聊消息
假如有服务器A和服务器B,一个群组G100;小明在服务器A,小美在服务器B;
当小美在服务器登录时间不确定的时候如何保证群聊消息不丢失?
可能会丢失的原因在于:
1)分布式环境下,消息的编号不是连续的流水号,无法通过编号来判断是否发生了丢失;
2)登录后如果只与服务器B同步一次数据,同步数据与其他服务器发现路由有时间差,时间差内的消息会丢失;
那么处理方式也很明显:
**1)传统轮询模式:**每次查询都告知服务器最后一条的ID,然后从数据库表中查询后续的消息,对于scylladb来说肯定是比传统的数据库强,但是效率仍然很低;
**2)暴力的集群同步:**不管服务器B是否有G100群组的用户在线,一直连续不断的转发消息,那么可以服务器B上存在的消息在时间上是连续的,那么登录后,同步一次数据就可以保证与后续转发的数据无缝衔接;
2.3 优化解决方法
那么针对2种方案时候有优化的方案呢?矫正后的算法对私聊和群聊都有效,原理是执行有限次同步以便在时间上覆盖所有范围:
3) 时间戳矫正法:
小美在服务器B登录,就绪后将状态广播到集群,之后开始同步群G100的历史数据,记录下同步到的最后一条消息的ID;假设同步的最新一条数据编号LAST_ID=1000200;(真实环境使用雪花算法)
这个LAST_ID本质上记录的是同步点;同步点仅仅随着同步查询动作而更新;
可能一:服务器A早就发现服务器B有群组G100其他用户,一直在转发数据,那么小美不会丢失数据,因为是流程是先设置状态后同步数据,服务器B可以保证消息没有丢失;对于同步前收到的数据,客户端先写到本地库,同步数据完成后再显示就不会乱序;
可能二:
小美开始是离线状态,等到小美上线服务器B,将状态发布到集群;服务器A收到群组G100到服务器B的路由;此时服务器A针对此路由,应当记录一个发现路由的时间戳(START_TM),并在在此后所有针对此路由的转发的消息都需要带上这个时间戳START_TM,含义是从此时刻起开始转发消息;(加入针对这个路由发送的第一个消息ID为 1000500,这个时间戳可以设置为发现路由后转发的第一条消息ID);
服务器B收到消息后,比对时间戳,如果 LAST_ID >= START_TM 则说明同步的的时间范围与开始转发的时间没有时间差;(在可能一中,也是满足这个不等式)。
如果 LAST_ID < START_TM 则说明存在时间差,有丢失消息风险,应该按照范围再1次执行同步数据,这样就能保证消息不丢失。同步消息后更新LAST_ID,含义是同步点可以标记到当前位置。
后续,假如有服务器C转发过来数据,也是同样大道理: 因为消息ID虽然不连续,但是雪花算法单调递增,而且里面包含了时间戳;
只要同步点晚于路由发现时间,就可以保证消息没有遗漏。

当服务器B上所有的关于群组G100的用户都离线后,则不需要服务器A转发数据了,则删除该路由。
相关代码:
// 发送方
type RouteData struct{MemCount int64 // 当前服务器上群组活动人员数量StartTm int64 // 发现路由的时间戳,
}// 在群组中添加2个映射记录数据
type Group struct{GroupId int64...RouteMap map[string]*RouteData // 发方:发现到某路由时候设置时间戳}
// 收方:
// 由于用户支持多终端同时在线,所以路由其实记录的用户的会话,而不是用户本身,有可能出现同一个用户登录到不同的主机上;
type Session struct{Sid int64...GroupSynId map[int64]int64 // 收方:每个组同步操作得到的位置:groupId -> LAST_ID
}
当服务器B有群组G100的用户时,会记录如下
//lock
group.RouteMap["serverB"] = &RouteData{MemCount: 1,StartTm: 1000500,
}
当路由消失后,则删除此路由;
针对私聊采用类似的策略:
其中,有可能出现同一个用户登录到不同的主机上;
type SessionOnserverData struct{ // 每个会话在哪个服务器上,记录首次发现路由的时间SessionList []int64StartTm int64
}// 有可能该好友的会话分布在多种终端,但是按照算法大多在同一个服务器
type UserRouteData struct{SessionOnServerMap map[string]*SessionOnserverData // 服务器——>会话列表}type User struct{UserId int64...FriendRoute map[int64]*UserRouteData // 针对好友的路由,UID-> 路由信息
}
// 接收方,在会话中记录好友发来的最后的消息的LAST_ID,
type Session struct{Sid int64..LastSynPoint int64 //会话已经完成同步最新的ID,因为所有消息都存在在一起,不用区分好友
}
从上面可以总结:
收方记录的同步点是基于队列的;
群聊的路由发现是以服务器为单位执行转发;(减少处理的复杂度)
私聊的路由发现是基于服务器为单位执行转发;
2.4 收方消息处理
收方如果从消息队列拿到数据后,直接在线程池中处理,会造成用户数据的并发冲突,我们这里针对每个用户需要线性处理;
合适的方式是将消息分发到各个会话的消息缓存队列中,由会话的读协程来处理这个内容;
完。
相关文章:
BirdTalk IM集群中消息流转策略讨论
BirdTalk IM集群中消息流转策略讨论 目前群聊的存储策略是1写多读方案;每个群组一个队列,按时间顺序排列,不区分用户; 私聊的存储是写扩散的,每个人都有自己的消息队列,按时间顺序 保存所有的消息&#x…...
重磅!2024年最新影响因子正式发布,附Excel下载
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 激动人心的时刻终于来了,2024年影响因子已全面发布!废话不多说,大家一起来看看最新的发布的结果吧! 神刊:CA-A CANCER JOURNA…...
【会议征稿】2024年应用计算智能、信息学与大数据国际会议(ACIIBD 2024,7月26-28)
2024年应用计算智能、信息学与大数据国际学术会议(ACIIBD 2024)将于2024年7月26-28日在中国广州举办。会议将聚焦于计算智能及其应用、信息、大数据等相关的研究领域, 广泛邀请国内外知名专家学者,共同探讨相关学科领域的最新发展…...
【代码发布】Quantlab4.3:lightGBM应用于全球大类资产的多因子智能策略(代码+数据)
原创文章第566篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 昨天,Quantlab整合Alpha158因子集,为机器学习大类资产配置策略做准备(代码数据),我们完成了因子集构建,并尝试…...
【毕业设计】Django 校园二手交易平台(有源码+mysql数据)
此项目有完整实现源码,有需要请联系博主 Django 校园二手交易平台开发项目 项目选择动机 本项目旨在开发一个基于Django的校园二手交易平台,为大学生提供一个安全便捷的二手物品买卖平台。该平台将提供用户注册和认证、物品发布和搜索、交易信息管理等…...
文章自动生成器,在线AI写作工具
随着人工智能AI技术的发展,AI技术被应用到越来越多的场景。对于需要创作内容的同学来说,AI写作-文章内容自动生成器是一个非常好的辅助工具。AI写作工具可以提升我们的创作效率,快速的生成文章,然后在根据需求进行调整修改即可。下…...
Matlab初识:什么是Matlab?它的历史、发展和应用领域
目录 一、什么是Matlab? 二、Matlab的历史与发展 三、Matlab的应用领域 四、安装和启动Matlab 五、界面介绍 六、第一个Matlab程序 七、总结 一、什么是Matlab? Matlab 是由 MathWorks 公司开发的一款用于数值计算、可视化以及编程的高级技术计算…...
大模型之-Seq2Seq介绍
大模型之-Seq2Seq介绍 1. Seq2Seq 模型概述 Seq2Seq(Sequence to Sequence)模型是一种用于处理序列数据的深度学习模型,常用于机器翻译、文本摘要和对话系统等任务。它的核心思想是将一个输入序列转换成一个输出序列。 Seq2Seq模型由两个主…...
NSSCTF-Web题目12
目录 [SWPUCTF 2021 新生赛]finalrce 1、题目 2、知识点 3、思路 [UUCTF 2022 新生赛]ez_rce 1、题目 2、知识点 3、思路 [羊城杯 2020]easycon 1、题目 2、知识点 3、思路 [SWPUCTF 2021 新生赛]finalrce 1、题目 2、知识点 命令执行,tee命令 3、思路…...
22、架构-资源与调度
1、资源与调度 调度是容器编排系统最核心的功能之一,“编排”一词本身便包 含“调度”的含义。调度是指为新创建的Pod找到一个最恰当的宿主机 节点来运行它,这个过程成功与否、结果恰当与否,关键取决于容器 编排系统是如何管理与分配集群节点…...
mac 常用工具命令集合
Iterm2 Command T:新建标签 Command W:关闭当前标签 Command ← →:在标签之间切换 Control U:清除当前行 Control A:跳转到行首 Control E:跳转到行尾 Command F:查找 Command …...
服务器雪崩的应对策略之----限流
限流是一种控制流量的技术,旨在防止系统在高并发请求下被压垮。通过限流,可以确保系统在负载高峰期依然能保持稳定运行。常见的限流策略包括令牌桶算法、漏桶算法、计数器算法和滑动窗口算法。 常见的限流方法 1. 令牌桶算法 (Token Bucket Algorithm)2…...
Python12 列表推导式
1.什么是列表推导式 Python的列表推导式(list comprehension)是一种简洁的构建列表(list)的方法,它可以从一个现有的列表中根据某种指定的规则快速创建一个新列表。这种方法不仅代码更加简洁,执行效率也很…...
threejs 光影投射-与场景进行交互(六)
效果 场景中有三个立方体,三种颜色.点击变成红色,再点恢复自身原有颜色 代码 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { log } from three/examples/jsm/nodes/Nodes.js//…...
Ubuntu 20.04安装显卡驱动、CUDA和cuDNN(2024.06最新)
一、安装显卡驱动 1.1 查看显卡型号 lspci | grep -i nvidia我们发现输出的信息中有Device 2230,可以根据这个信息查询显卡型号 查询网址:https://admin.pci-ids.ucw.cz/mods/PC/10de?actionhelp?helppci 输入后点击Jump查询 我们发现显卡型号为RTX …...
二叉树的这五种遍历方法你们都会了吗?
说在前面 🎈二叉树大家应该都很熟了吧,那二叉树的这五种遍历方式你们都会了吗? 以这一二叉树为例子,我们来看看不同遍历方式返回的结果都是怎样的。 前序遍历 前序遍历的顺序是:首先访问根节点,然后递归地…...
使用模数转换器的比例电阻测量基础知识
A/D 转换器是比率式的,也就是说,它们的结果与输入电压与参考电压的比值成正比。这可用于简化电阻测量。 测量电阻的标准方法是让电流通过电阻并测量其压降 (见图 1)。然后,欧姆定律(V I x R) 可用于计算电压和电流的…...
(C++语言的设计和演化) C++的设计理念
文章目录 前言📖C 语言设计规则📐规则和原理📐一般性规则📐设计支持规则📐语言的技术性规则📐低级程序设计支持规则 📖标准化(扩充评判准则)📐它精确吗&#…...
AI音乐:创新引擎还是创意终结者?
✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点赞、关注、收藏、评论,是对我最大…...
20240621每日后端---------如何优化项目中的10000个if-else 语句?
如何优化 10000 个 if-else 语句?有没有好的解决方案? 额,本身问题就很奇怪,怎么可能有这种代码。。。世界你让我陌生,但是我们还是假象着看看能不能解决一下。 解决方案1:策略模式 使用策略模式确实可以…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
