分层架构 IM 系统之 Router 架构分析

通过前面文章的分析,我们已经明确,Router 的核心职责是作为中央存储记录在线客户端的连接状态,Router 在本质上是一个内存数据库。

内存是一种易失性的存储,既如此,Router 的可用性如何保障呢?

副本是分布式存储系统容错技术的唯一手段!

所以解决 Router 的可用性问题,为其增加冗余的副本即可。

分布式存储系统的副本,有两类常用模式:主从模式和主主模式。

一、主从模式

对于主从模式来说,服务向 “主节点” 写数据,“从节点” 从 “主节点” 中同步数据;“主节点” 和 “从节点” 都是可以提供 “读数据” 服务的,不过只有主节点才能提供 “写数据” 服务,所以主从模式对于写操作来说,是单点方式,要解决 “写高可用” 是非常麻烦的。

二、主主模式

对于主主模式来说,服务可以向任何一个 “主节点” 写数据,也可以从任何一个 “主节点” 读数据,然后两个主节点之间互相同步数据,所以主主模式同时满足数据 “读高可用” 和 数据 “写高可用”;但是要注意,主主模式不适用的业务场景:对同一条数据从两个 “主节点” 同时进行写操作。

举一个例子: 主主模式集群中有一条数据为 x = 5,两个服务节点分别对两个 “主节点” 同时进行修改,一个 “主节点” 修改为 x = 7,一个 “主节点” 修改为 x = 9,此时两个 “主节点” 在互相同步时就会出现冲突。

所以,在使用主主模式时,一定要避免对相同数据的并发写。

Router 采用了 主主模式,见下图。

Logic 在写 Router 时,通过公式 uid % 2 计算要写入的 Router 节点,避免了相同用户记录在两个主 Router 节点上的并发写操作。另外,对于同一用户的操作,会由相同的 Logic 节点来处理(后面的技术文章中会详细分析),这也会避免相同用户记录的并发写入。

单个 Router 节点保存了所有在线客户端的用户数据,随着在线用户量的增多,Router 会很容易到达存储瓶颈;解决这个问题的常用方案是分片,见下图。

将所有在线用户分配到 N 个分片中,需要部署 N 组Router,每一组 Router 可以主主模式部署也可以主从模式部署; Logic 在写 Router 时,通过公式 uid % N 计算要写入的 Router 分组。这样通过分组的方式,实现了在线用户的横向线性扩容;每一组内部通过主主模式 或 主从模式实现了高可用。

这里有一个实践性很强的问题,大家思考一下: 将最开始的一组 Router 扩容为四组 Router 时,怎样将原来的数据进行迁移呢?

答案是不必迁移。一组 Router 扩容为四组 Router 后,原来这一组 Router 中大概会有四分之三的在线用户数据会被遗弃,不过不必担心,在上一篇文章(分层架构 IM 系统之 Router 能力分析)中,我们分析过,Router 的心跳扫描线程会扫描出心跳失活的用户记录进行清理;另外,其它三组 Router 最开始是空白数据,但随着在线用户客户端的心跳到来,会逐步将这空白的三组 Router 数据进行修复。

心细的同学会提出疑问:即使如此,当从这三组 Router 中读数据时,读不到怎么办呢?这就涉及到 IM 系统的容错性了。将一个在线用户,按离线方式去处理,并不会对用户造成不好的体验。当然,对 Router 进行扩容,选择在凌晨时分处理,肯定是最合适的。

将一个刚启动的 Router 节点作为 “从节点” 部署时,“主节点” 是如何进行数据同步的呢?见下图。

Router 在内存中维护了很多个 Map,当有其他 Router 节点以 “从节点” 的角色连接过来时,“主节点” Router 会将内存数据生成一个 “快照”,然后将 “快照” 数据发送到 “从节点”。

“主节点” Router 生成 “快照” 后,再接收到的所有的 “写操作” 将全部写入到 “增量数据队列” 中;Router “从节点” 消化完 “快照” 后,就会再次发请求到 “主节点”,然后不断从 “主节点” 的 “增量数据队列” 中读数据完成主从同步。

关于 “快照” 如何生成,我们在后面的技术文章中进行分析!

最后,总结文中关键:

1、 分布式存储系统的副本模式有两种实现方式:主从模式和主主模式,在使用主主模式时,需要避免相同数据记录在两个主节点上被并发写入;

2、 Router 采用了主主模式,当在线用户量达到单个 Router 的存储瓶颈时,通过分片方式实现横向扩容;

3、 在对 Router 进行横向扩容时,在 IM 这个业务场景下,不需要进行数据迁移;

4、 Router 进行主从数据同步时,先生成和同步快照,然后同步增量数据。

对 Router 的分析到这里时,会有同学提出疑问: Router 在整个 IM 系统中,特别像 Redis,Redis 是完全可以替代 Router 的 ,为什么要自研 Router 呢? 因为在早期,Redis 还没有那么成熟和普及!随着 IM 系统不断迭代,用 Redis 替换掉 Router 是必然的,因为 Redis 的扩展性和维护成本相对都是最好的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928161.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二分查找常规实现

使用二分查找有一个前提条件:要查找的数必须在一个有序数组里。在这个前提下,取中间位置数作为比较对象: 若要查找的值和中间数相等,则查找成功。 若小于中间数,则在中间位置的左半区继续查找。 若大于中间数&#x…

C++ 之弦上舞:string 类与多样字符串操作的优雅旋律

string 类的重要性及与 C 语言字符串对比 在 C 语言中,字符串是以 \0 结尾的字符集合,操作字符串需借助 C 标准库的 str 系列函数,但这些函数与字符串分离,不符合 OOP 思想,且底层空间管理易出错。而在 C 中&#xff0…

获取联通光猫的管理员密码

缘起:联通给免费更换了一个新的光猫,烽火的光路由,一个WAN口,4个LAN口,带USB接口,欣欣然接受。但是呢,发现以前的管理员密码CUAdmin不能用了。经过一系列查询,借助别人的经验&#x…

数组练习(非最终版)

作业1&#xff1a;使用二维数组输出杨辉三角 //杨辉三角 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char *argv[]) {int i,j,n;scanf("%d",&n);int arr[n][n];for(i0;i<n;i){arr[i][0]1;arr[…

【MySQL 进阶之路】索引概述

第06章_索引 1.什么是索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录中找到对应文章的页码&#xff0c;便可快速定位到需要的文章。MySQL中也是一样的道理&#xff0c;进行数据查找时&#xff0c;首先查…

微积分复习笔记 Calculus Volume 2 - 3.3 Trigonometric Substitution

3.3 Trigonometric Substitution - Calculus Volume 2 | OpenStax

业财一体化新篇章:外贸ERP软件重塑业务流程

业财一体化的定义&#xff08;Definition&#xff09; FMS&#xff0c;即财务管理软件&#xff08;Financial Management Software&#xff09;&#xff0c;涵盖了用于管理公司财务的多种工具和系统&#xff0c;包括预算管理、账务处理、报表生成等功能。 ERP&#xff0c;即企…

Qt 信号与槽:UI设计的基础

Qt 的信号与槽机制是其最强大的功能之一&#xff0c;也是初学者理解 Qt 的第一步。它让对象之间的通信变得直观和高效。信号与槽类似于现实生活中的“呼叫和应答”模式&#xff1a;一个对象发出信号&#xff0c;另一个对象响应并执行动作。 什么是信号与槽&#xff1f; 信号与…

QT 左右 上下,拉伸 分配窗口大小

要的效果是以下&#xff1a; QT C 两个QWideget A B现在有放在一个窗口QWideget Test内&#xff0c;初始比例要2&#xff1a;8 ,现在我要 A B 两个窗口中间 当鼠标移到他中间时&#xff0c;有条线&#xff0c;可以左右移动来控件 A B 窗口所占的大小widgetB &#xff08;有 wi…

Linux 各个目录作用

刚毕业的时候学习Linux基础知识&#xff0c;发现了一份特别好的文档快乐的 Linux 命令行&#xff0c;翻译者是happypeter&#xff0c;作者当年也在慕课录制了react等前端相关的视频&#xff0c;通俗易懂&#xff0c;十分推荐 关于Linux的目录&#xff0c;多数博客已有详细介绍…

基于PyTorch框架的线性回归实现指南

目录 ​编辑 1. 线性回归基础 2. PyTorch环境搭建 3. 数据准备 4. 定义线性回归模型 5. 损失函数和优化器 6. 训练模型 7. 评估模型 8. 结论 线性回归是统计学和机器学习中最基本的预测模型之一&#xff0c;它试图找到输入特征和输出结果之间的线性关系。在深度学习框…

HYSPLIT下载及使用

准备工作 官网基础教程&#xff1a;https://www.ready.noaa.gov/documents/Tutorial/html/index.html 使用 参考&#xff1a;https://blog.csdn.net/liaohaibing/article/details/112788701 下载之前还需要Graphical Utilities&#xff1a;https://www.ready.noaa.gov/HYSPLI…

基于Java Springboot环境保护生活App且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

骨架行为识别-论文复现

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【PyTorch】torch.distributed.elastic.multiprocessing.errors.ChildFailedError:

报错说明 torch.distributed.elastic.multiprocessing.errors.ChildFailedError: 报错如图所示 报错分析 该报错是 torch 和 CUDA 版本不兼容导致。 &#xff08;一般N卡自带的CUDA版本与最新的torch版本相差较大&#xff09; 解决方案 1.查看自己的CUDA版本 # 查看自己的…

Kylin Server V10 下基于Kraft模式搭建Kafka集群

一、Kraft 模式与 ZooKeeper 模式简介 在Kafka 2.8 之前,Kafka 重度依赖 ZooKeeper 集群做元数据管理、Controller 的选举等(统称为共识服务);当ZooKeeper 集群性能发生抖动时,Kafka 的性能也会受到很大的影响。如下图所示: 在 Kafka 2.8 之后,引入了基于 Raft …

ceph手动部署

ceph手动部署 一、 节点规划 主机名IP地址角色ceph01.example.com172.18.0.10/24mon、mgr、osd、mds、rgwceph02.example.com172.18.0.20/24mon、mgr、osd、mds、rgwceph03.example.com172.18.0.30/24mon、mgr、osd、mds、rgw 操作系统版本&#xff1a; Rocky Linux release …

记录vite关于tailwindcss4.0-bate4出现margin[m-*]、padding[p-*]无法生效的问题。

环境如下&#xff1a; vite:5.4.10 tailwindcss: 4.0.0-beta.4 tailwindcss/vite: 4.0.0-beta.4 4.0默认的样式优先级比较低 如果使用了一些reset的css文件 那么很多样式会失效 例如&#xff1a;reset.css中 html, body, ul, li, h1, h2, h3, h4, h5, h6, dl, dt, dd, ol, i…

AcWing 841. 字符串哈希

字符串哈希 一种将任意长度的字符串转换为固定长度数值&#xff08;通常是整数&#xff09;的过程。全称字符串前缀哈希法&#xff0c;把字符串变成一个p进制数字&#xff08;哈希值&#xff09;&#xff0c;实现不同的字符串映射到不同的数字。 对形如 X1X2X3⋯Xn−1Xn 的字…

物联网接入网关的数据安全和高效传输详解

物联网接入网关&#xff0c;作为连接物联网终端设备与云端或本地服务器的关键环节&#xff0c;不仅负责数据的汇聚与转发&#xff0c;更需确保数据在传输过程中的安全无虞与高效流畅。 一、数据安全&#xff1a;构筑坚实防线 1. 加密技术的应用 天拓四方物联网接入网关内置了…