Netty+springboot开发即时通讯系统笔记(四)终

实时性

1.线程池多线程,把消息同步给其他端和对方用户,其中数据持久化往往是最浪费时间的操作,可以使用mq异步存储,因为其他业务不需要拿着整条数据,只需要这条数据的id进行操作。

2。消息校验前置,放在tcp层(netty服务中)

可靠性

在这里插入图片描述

tcp协议只能保证数据在传输过程中不丢失,但不能保证到某一端不会丢失,比如传输过程中接收方断网,数据就无法发送到接收方 。

可靠性可以通过消息重发来保证消息一定送到了对方手中。可以通过双重ack确认机制来实现:
在这里插入图片描述

A向im服务端发送数据,服务端收到就返回一个ack,A收到这个ack就停止重发,否则就再次尝试重发。当然重发需要设计上限次数的。

然后服务端接到A的数据,再发送给B,B接到之后告诉服务端,返回一个接受到的ack。服务端把收到的再传回给A,此时A确定了此次传输是成功的。中间任何环节出问题,A就执行重发就ok了。

如果B不在线,服务端是可以感知到的,服务端可以代替B向A回复停止重发指令。

有序性

因为我们使用多线程保证了消息的实时性,那么就会导致消息有乱序的风险。

解决方案:

使用redis的incr命令实现原子性的递增序列号,但是过度依赖redis可能会因为redis的崩溃而造成系统失效

幂等性

再im服务端存储每次发过来的消息id(设置过期时间),重复发送的消息id将不再进行持久化但仍会给另一个客户端发送消息。这样就会导致另一个客户端由于网络问题如果没有及时返回ack确认,那么他确实会收到2条相同的消息,但是在去重是完全可以处理的。

qq发消息失败会有红色感叹号,当再次点击重发时是把它当作一条新的消息id发送的,而不是之前的消息id。

消息已读功能

在写扩散中,每个人对自己的每条消息都可以直接获取,已读只不过是个字段罢了。

在读扩散中,以群聊为例,可以在群成员表中加入一个字段,该字段表示改成员读到的最后一条消息序列(保证有序性的那个递增序列),在这条消息之前的就表示读过了

离线消息存储

IM(即时通讯)系统中的离线消息是指在目标用户不在线或者不可达时,发送方发送的消息无法直接传递给目标用户,而是被服务器暂时存储起来,等到目标用户上线或者可达时再进行投递。

离线消息的存在是为了保证消息的可靠性和完整性。当发送方发送消息时,如果目标用户在线,消息可以直接传递给目标用户;但如果目标用户不在线,服务器会将该消息存储在消息队列或者数据库中,等到目标用户上线后,服务器会将离线消息投递给目标用户。

离线消息通常具有以下特点:

  1. 持久化存储:离线消息通常被存储在服务器的数据库或者消息队列中,确保消息的持久性,即使服务器重启或者断电,消息也不会丢失。
  2. 时效性:离线消息通常会设置一个过期时间,在一定时间范围内等待目标用户上线,过期后会被清理或者丢弃。
  3. 投递策略:服务器会在目标用户上线后,根据一定的投递策略(如先进先出、按时间戳等)将离线消息按顺序投递给目标用户。
  4. 通知机制:当目标用户上线后,服务器可能会发送通知给目标用户,告知其有离线消息待接收。

这里的存储使用redis,每人只存1000条,超过就淘汰最早的,使用zset存储,使用消息的递增序列号作为排序标准,zset支持查询范围内指定数量的元素(SMEMBERS命令)。

即使你错过了离线消息的通知和消息盒子,你仍然可以通过滚动查看聊天记录,找到之前的离线消息。

登录之后的数据同步(历史记录的拉取)

不可能说每次登录都把所有记录都删了重新拉取一遍的,所以这里采用增量拉取。

需要拉取的东西有会话,好友列表,好友申请,为每个需要拉取的数据记录下他的递增序列号,每次只拉取大于记录里最大的序列号。

客户端可以用数据库sqllite

在线状态设计

正常情况下,你的上线和下线等状态应该通知给你的所有好友,和你在的所有群里的所有成员,这将是非常恐怖的数据量。

改进1:只推给在线用户

改进2:

  1. 按需拉取:在按需拉取的策略下,IM 系统不会主动向所有好友和群成员发送上线和下线等状态通知。相反,当其他用户需要获取某个用户的状态时,他们可以向服务器发送请求,然后服务器根据请求返回相应的状态信息。这种方式可以避免将状态通知广播给所有人,只有真正需要获取状态信息的用户才会发起请求,减少了不必要的数据传输和处理。
  2. 临时订阅:临时订阅是指用户可以临时订阅某个好友或群组的状态更新通知。当用户订阅了某个用户或群组后,只有在被订阅对象的状态发生变化时,系统才会向订阅者发送通知。这样可以避免向所有好友和群成员广播状态更新,只有被订阅的对象状态发生变化时,才会发送通知给订阅者。这种方式可以根据用户的实际需求,选择性地接收特定用户或群组的状态更新通知,减少了不必要的通知量。

陌生人发消息限制

  1. 计数限制:为每个用户设置一个计数器,记录他们发送给陌生人的消息数量。当陌生人发送消息时,系统会检查计数器的值。如果计数器小于等于三,允许发送消息并将计数器加一;如果计数器大于三,拒绝发送消息。

  2. 时间限制:除了计数限制,可以设置一个时间限制,例如每小时或每天只允许陌生人发送三条消息。系统会记录陌生人发送消息的时间,并在规定的时间段内检查发送数量。如果超过限制,拒绝发送消息。

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

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

相关文章

谷歌推出首款量子弹性 FIDO2 安全密钥

谷歌在本周二宣布推出首个量子弹性 FIDO2 安全密钥,作为其 OpenSK 安全密钥计划的一部分。 Elie Bursztein和Fabian Kaczmarczyck表示:这一开源硬件优化的实现采用了一种新颖的ECC/Dilithium混合签名模式,它结合了ECC抵御标准攻击的安全性和…

机器学习与模式识别3(线性回归与逻辑回归)

一、线性回归与逻辑回归简介 线性回归主要功能是拟合数据,常用平方误差函数。 逻辑回归主要功能是区分数据,找到决策边界,常用交叉熵。 二、线性回归与逻辑回归的实现 1.线性回归 利用回归方程对一个或多个特征值和目标值之间的关系进行建模…

java版本spring cloud 企业工程系统管理 工程项目管理系统源码em

工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…

消息中间件的选择:RabbitMQ是一个明智的选择

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! MQ(Message Queue) MQ(消息队列)是一种用于在应用程序之间进行异步通信的技术;允许应用程序通过发送和接收…

Vue3 用父子组件通信实现页面页签功能

一、大概流程 二、用到的Vue3知识 1、组件通信 (1)父给子 在vue3中父组件给子组件传值用到绑定和props 因为页签的数组要放在父页面中, data(){return {tabs: []}}, 所以顶部栏需要向父页面获取页签数组 先在页签页面中定义props用来接…

CloudCompare——统计滤波

目录 1.统计滤波2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创,CloudCompare——统计滤波,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 1.统计滤波 算法原理见:PCL 统计滤波器…

Cpp学习——类与对象3

目录 一,初始化列表 1.初始化列表的使用 2.初始化列表的特点 3.必须要使用初始化列表的场景 二,单参数构造函数的隐式类型转换 1.内置类型的隐式类型转换 2. 自定义类型的隐式类型转换 3.多参数构造函数的隐式类型转换 4.当你不想要发生隐式类型转换…

CPU缓存一致性原理

CPU缓存一致性原理 在本站的文章CPU缓存那些事儿中, 介绍了cpu的多级缓存的架构和cpu缓存行cache line的结构。CPU对于缓存的操作包含读和写,读操作在cache line中有所涉及,在本文中,将重点讨论CPU对于缓存进行写时的行为。 单核…

美国大模型风向速报(一)为何重视提示工程?LangChain+向量数据库+开源大模型真香...

多家,且独家来自美国的信源同时向“亲爱的数据”表示, 提示工程(Prompt Engineering)在美国大模型领域备受重视。 读者都要聊, 那就干活。 (一)开源真香 现阶段,AI开源极客大展身手&…

【视觉SLAM入门】5.2. 2D-3D PNP 3D-3D ICP BA非线性优化方法 数学方法SVD DLT

"养气之学,戒之躁急" 1. 3D-2D PNP1.1 代数法1.1.1 DLT(直接线性变换法)1.1.2. P3P 1.2 优化法BA (Bundle Adjustment)法 2. 3D-3D ICP2.1 代数法2.1.1 SVD方法 2.2 优化(BA)法2.2.2 非线性优化方法 前置事项: 1. 3D-2D PNP 该问题描述为&am…

线性代数的学习和整理7:各种特殊矩阵(草稿-----未完成)

目录 1 单位矩阵 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 2 旋转矩阵 3 伸缩矩阵 放大缩小倍数矩阵 4 镜像矩阵 5 剪切矩阵 矩阵 行向量 列向量 方阵 1 单位矩阵 [ 1 0 0 1] 为什么单位矩阵I是 [1,0;0,1]T 而不是[1,1;1,1]T 因为 矩阵 [1,0;0,1] 代表…

websocket + stomp + sockjs学习

文章目录 学习链接后台代码引入依赖application.ymlWebSocketConfigPrivateControllerWebSocketService WebSocketEventListenerCorsFilter 前端代码Room.vue 学习链接 WebSocket入门教程示例代码,代码地址已fork至本地gitee,原github代码地址&#xff…

马哈鱼数据血缘工具背后的项目: gsp_demo_java 项目简单介绍与使用

0.背景 马哈鱼数据血缘工具(https://www.sqlflow.cn/)是SQLflow工具的中文译名,实际就是sqlflow. 对于SQL flow来说,底层调用的是General SQL Parser(GSP https://sqlparser.com) 的库. 这个gsp有开源的java demo项目:https://github.com/sqlparser/gsp_demo_java 1.快速使用…

【C# 基础精讲】LINQ 基础

LINQ(Language Integrated Query)是一项强大的C#语言特性,它使数据查询和操作变得更加简洁、灵活和可读性强。通过使用LINQ,您可以使用类似SQL的语法来查询各种数据源,如集合、数组、数据库等。本文将介绍LINQ的基础概…

(排序) 剑指 Offer 45. 把数组排成最小的数 ——【Leetcode每日一题】

❓ 剑指 Offer 45. 把数组排成最小的数 难度:中等 输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 示例 1: 输入: [10,2] 输出: “102” 示例 2: 输入: [3,30,34,5,9] 输出: “3033459”…

PV3D: A 3D GENERATIVE MODEL FOR PORTRAITVIDEO GENERATION 【2023 ICLR】

ICLR:International Conference on Learning Representations CCF-A 国际表征学习大会:深度学习的顶级会议 生成对抗网络(GANs)的最新进展已经证明了生成令人惊叹的逼真肖像图像的能力。虽然之前的一些工作已经将这种图像gan应用于无条件的2D人像视频生…

[K8s]问题描述:k8s拉起来的容器少了cuda的so文件

问题解决:需要设置Runtimes:nvidia的同时设置Default Runtimenvidia

Java请求Http接口-OkHttp(超详细-附带工具类)

简介:OkHttp是一个默认有效的HTTP客户端,有效地执行HTTP可以加快您的负载并节省带宽,如果您的服务有多个IP地址,如果第一次连接失败,OkHttp将尝试备用地址。这对于IPv4 IPv6和冗余数据中心中托管的服务是必需的。OkHt…

Win11游戏高性能模式怎么开

1、点击桌面任务栏上的“开始”图标,在打开的应用中,点击“设置”; 2、“设置”窗口,左侧找到“游戏”选项,在右侧的选项中,找到并点击打开“游戏模式”; 3、打开的“游戏模式”中,找…

搭载KaihongOS的工业平板、机器人、无人机等产品通过3.2版本兼容性测评,持续繁荣OpenHarmony生态

近日,搭载深圳开鸿数字产业发展有限公司(简称“深开鸿”)KaihongOS软件发行版的工业平板、机器人、无人机等商用产品均通过OpenAtom OpenHarmony(以下简称“OpenHarmony”)3.2 Release版本兼容性测评,获颁O…