“id串行化”到底是怎么实现的?

简介: 让同一个群gid的所有消息落在同一台服务器上处理。有朋友就要问了,如何保证一个群gid的消息落到同一个服务器处理呢,“id串行化”具体是怎么实现的呢,这个问题在年初的一篇文章中描述过,这里再给有疑问的同学解答一下。

一、需求缘起

在上一篇文章《消息“时序”与“一致性”为何这么难?》中,介绍了一种为了保证“所有群友展示的群消息时序都是一致的”所使用的“id串行化”的方法:让同一个群gid的所有消息落在同一台服务器上处理。

有朋友就要问了,如何保证一个群gid的消息落到同一个服务器处理呢,“id串行化”具体是怎么实现的呢,这个问题在年初的一篇文章中描述过,这里再给有疑问的同学解答一下。

二、互联网高可用常见分层架构

image.png

客户端,反向代理层,接入层(此图是http短链接接入,群聊消息的话是tcp长连接接入),服务层(处理群消息业务逻辑),存储层(缓存cache存储,固化db存储),这是互联网常见的高可用分层架构。

服务层的引入至关重要,群消息的投递不能保证落在同一个接入层,但可以保证落在同一个服务层。

三、服务层上下游细节

服务化的service一般由RPC-server框架实现,上游应用是多线程程序(站点层http接入应用,或者长连接tcp接入应用)一般通过RPC-client访问service,而RPC-client内部又通过连接池connection-pool访问下游的service(为了保证高可用,是一个service集群)。
image.png

如上图:

(1)上游是业务应用(站点层http接入应用,或者长连接tcp接入应用)

(2)下游是service集群

(3)业务应用,它又分为了这么几个部分

(3.1)最上层是任务队列【或许web-server例如tomcat帮你干了这个事情了】

(3.2)中间是工作线程【或许web-server的工作线程或者cgi工作线程帮你干了线程分派这个事情了】,每个工作线程完成实际的业务任务,典型的工作任务是通过服务连接池进行RPC调用

(3.3)最下层是服务连接池,所有的RPC调用都是通过服务连接池往下游服务去发包执行的

工作线程的典型工作流伪代码是这样的:

void work_thread_routine(){

Task t = TaskQueue.pop(); // 获取任务

// 任务逻辑处理,组成一个网络包packet,调用下游RPC接口

ServiceConnection c = CPool.GetServiceConnection();

// 从Service连接池获取一个Service连接

c.Send(packet); // 通过Service连接发送报文执行RPC请求

CPool.PutServiceConnection(c); // 将Service连接放回Service连接池

}

如何保证同一个群gid的消息落在同一个service上呢?

只要对服务连接池进行少量改动:

获取Service连接的CPool.GetServiceConnection()【返回任何一个可用Service连接】改为

CPool.GetServiceConnection(long id)【返回id取模相关联的Service连接】

只要传入群gid,就能够保证同一个群的请求获取到同一个连接,从而使请求落到同一个服务Service上。

需要注意的是,连接池不关心传入的long id是什么业务含义:

(1)传入群gid,同gid的请求落在同一个service上

(2)传入用户uid,同uid的请求落在同一个service上

(3)传入任何业务xid,同业务xid的请求落在同一个service上

四、其他问题

提问:id串行化访问service,同一个id访问同一个service,当service挂掉时,是否会影响service的可用性?

答:不会,当有下游service挂掉的时候,service连接池能够检测到连接的可用性,取模时要把不可用的服务连接排除掉。

提问:取模访问service,是否会影响各连接上请求的负载均衡?

答:不会,只要数据访问id是均衡的,从全局来看,由id取模获取各连接的概率也是均等的,即负载是均衡的。

五、总结

升级RPC-client内部的连接池,在service连接选取上做微小改动,就能够实现“id串行化”,实现不同类型的业务gid/uid等的串行化、序列号需求(这下查找日志就方便了,一个群gid/用户uid的日志只需去一台机器grep啦)。

==【完】==

image.png

目录
相关文章
|
7月前
|
存储 机器学习/深度学习 人工智能
文档切分实战:5种方法详解,打造高效RAG系统的第一步
本文深入解析RAG中至关重要的文档切分技术,系统介绍5种主流策略(句子、定长、重叠、递归、语义切分),结合代码示例与实战调优技巧,涵盖PDF/Markdown/代码等多格式处理,并提供质量评估与避坑指南,助你打造高精度、高效率的私有知识库。
1464 7
|
NoSQL Java Shell
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
541 8
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
|
人工智能 自然语言处理 数据可视化
DeepSeek+Coze:普通人也能轻松搭建AI智能体的完整指南优雅草卓伊凡
DeepSeek+Coze:普通人也能轻松搭建AI智能体的完整指南优雅草卓伊凡
3585 1
DeepSeek+Coze:普通人也能轻松搭建AI智能体的完整指南优雅草卓伊凡
Future原理解析
介绍了Java多线程中Future类的原理
Future原理解析
|
JavaScript API
vue使用hook:声明周期来监听子组件的声明周期
本文介绍了如何在Vue中使用生命周期钩子来监听子组件的生命周期事件,包括在子组件内部监听和在父组件中监听子组件的生命周期钩子。
303 0
|
物联网 编译器 测试技术
【嵌入式 交叉编译器】如何在 ARM 架构下选择和使用高版本交叉编译器
【嵌入式 交叉编译器】如何在 ARM 架构下选择和使用高版本交叉编译器
1842 7
|
Python
SciPy 教程 之 Scipy 显著性检验 7
SciPy 教程之 Scipy 显著性检验第7部分,介绍显著性检验的基本概念及其在 SciPy 中的应用。显著性检验用于评估样本数据与假设之间的差异是否由随机因素引起。SciPy 的 `scipy.stats` 模块提供了执行显著性检验的功能,包括 KS 检验等方法,用于检测数据是否符合特定分布。示例代码展示了如何使用 KS 检验验证一组数据是否符合正态分布。
257 2
|
监控 开发者
深入理解操作系统:内存管理的艺术
【10月更文挑战第2天】在数字世界的幕后,操作系统扮演着至关重要的角色。本文将深入探索操作系统的心脏——内存管理,揭示它是如何协调和管理计算机的宝贵资源。通过浅显易懂的语言和生活化的比喻,我们将一起走进内存管理的奥秘世界,了解它的原理、机制以及为何对整个系统的性能和稳定性有着不可替代的影响。无论你是技术新手还是资深开发者,这篇文章都将为你打开新的视角,让你对日常使用的设备有更深层次的认识和尊重。
|
机器学习/深度学习 存储 算法
特征向量(Eigenvector)
特征向量(Eigenvector)是在线性代数中与矩阵相对应的非零向量,其在矩阵乘法下只发生伸缩变化而不改变方向。特征向量与特征值(Eigenvalue)是成对出现的,特征值表示特征向量的伸缩因子。
1253 1
|
人工智能 自然语言处理 机器人
使用OpenAI的Whisper 模型进行语音识别
本文将解释用于训练的数据集的种类以及模型的训练方法,以及如何使用Whisper
3830 0

热门文章

最新文章