聊一聊关于聊天记录的存储

背景

即时通讯(Instant Messaging),也就是我们常说的 IM,其实在很多业务场景上都会有或多或少的应用,有的会是核心,有的会是辅助。

既然是聊天,那么必然就会产生聊天记录,而且聊天记录随着人数的增加和时间的推移,很容易出现爆炸式的增长,这个对存储其实压力是很大的。

举个大家都很熟悉的例子,一个群聊,几分钟不看,再打开就是 99+ 的未读消息。

把即时通讯这个技术,放到医疗环境下,也是同样适用的。

患者去线下医院看病,肯定离不开和医生的问答,这些问答,对系统来说,其实都是聊天记录。

如果把这个场景放到线上进行,也就是正常的和我们在微信聊天那样了。

说了那么多有的没的,也算是把大背景交代了一下,那么接下来就看看这个聊天记录存储的选型吧。

技术选型

既然要存储,那么肯定就会有很多选择,关系型数据库,非关系型数据库等。

当然这个很大程度上是和具体业务场景挂钩的,离开了业务场景,基本就是在空谈。

在医患关系里面的聊天记录,是一个十分十分核心的内容,并且必须要长期保存,不能丢,可查询。

并且这些聊天记录是和某次问诊强关联的,所以单独拿出几条聊天记录出来,是没有意义的,因为他们没有关联,串联不起来。

按照以往的经验看,一次问诊,医生和患者之间的聊天记录在 50 条之内的占据了大部分,超过50条的,占少数。

这个和其他的 IM 情景可能不太一样。

MySQL

业务开始,大概率就是选用 MySQL 去存了这些数据了,单库单表,但是这种情况下很容易达到单表千万和上亿的级别。

后面面临的基本就是分库分表的操作了。

分库分表,基本就是根据问诊号去进行哈希,然后放到不同的库不同的表。

这里会有一个不确定因素,分多少个库和分多少张表?

分的多,囊中羞涩;分的少,再一次达到量级的时候又要重新分,大动干戈,这个时候最怕的就是动到了哈希的规则。

所以选 MySQL 的话,到了中后期确实还是会有一点力不从心。线性扩展对这一块还是非常重要的。

如果想改动小,避免分库分表,或许可以试试 TiDB,但是它要的配置,也不是中小企业所能接受的,80% 以上的概率会被 Pass 掉。

https://docs.pingcap.com/zh/tidb/stable/hardware-and-software-requirements

Cassandra

Cassandra 是一个分布式、无中心、弹性可扩展的 NoSQL 数据库,基于 Amazon Dynamo 的分布式设计和 Google Bigtable 的数据模型。

https://cassandra.apache.org/doc/latest/architecture/overview.html

为什么考虑选型 Cassandra 呢?对上面说的医患场景,严格上是属于写多读少的,查询基本只会基于问诊号去查询,这个是相对比较明确的。

Discord 在 2017 年的时候有一篇博客讲述了他们是怎么存储数十亿消息记录的 ,说的比较详细了。

https://blog.discord.com/how-discord-stores-billions-of-messages-7fa6ec7ee4c7

其实他们选数据库的诉求,也是符合大部分涉及 IM 这一块的。

老黄也是从这里受到了启发,认识了这个数据库。

经常拿来比较的话,应该是 HBase,一个在国内火,一个在国外受欢迎。

可以看看这个对比,了解一下两者的异同:https://www.scnsoft.com/blog/cassandra-vs-hbase

如果选择要用 Cassandra, 那么数据模型的设计,一定是所有环节中最为重要的一步,如果这一步没有做好的话,那后面基本上会是灾难级别,基本不能愉快的玩耍。

那么对医患关系里面的这个聊天模型其实比较简单。

CREATE TABLE IF NOT EXISTS messages(inq_id text,send_time bigint,sender_id text,sender_role tinyint,msg_type tinyint,msg_body text,PRIMARY KEY (inq_id, send_time)
) WITH CLUSTERING ORDER BY (send_time ASC)

对照正常的 IM 群聊, 这个问诊号 (inq_id) 就可以认为是一个群聊,一个频道。

为什么没有消息Id这样的字段呢?多来源,非自研,无实际意义。

下面再来看看如何在 C# 里面进行操作, 这里用的是 DataStax 提供的 CassandraCSharpDriver 客户端。

写入:

var cluster = Cassandra.Cluster.Builder().AddContactPoints("127.0.0.1").WithDefaultKeyspace("messaging").Build();var inqId = "xxxxxx";
var sendTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var senderId = "xxxx";
var senderRole = 1;
var msgType = 1;
var msgBody = "zzzz";string INSERT_SQL = @" INSERT INTO messages(inq_id, send_time, sender_id, sender_role, msg_type, msg_body)
VALUES (?, ?, ?, ?, ?, ?) ";var session = cluster.Connect();var stmt = session.Prepare(INSERT_SQL).Bind(inqId, sendTime, senderId, senderRole, msgType, msgBody));session.Execute(stmt);

读取:

var cluster = Cassandra.Cluster.Builder().AddContactPoints("127.0.0.1").WithDefaultKeyspace("messaging").Build();var inqId = "xxxxxx";string GET_MSG_SQL = @" SELECT * FROM messages WHERE inq_id = ? ";var session = cluster.Connect();var stmt = session.Prepare(GET_MSG_SQL).Bind(inqId);var rowset = session.Execute(stmt);Console.WriteLine("患者\t\t\t\t\t医生");foreach (var row in rowset)
{// 解析从 cassandra 中返回的行var msg_body = row.GetValue<string>("msg_body");var sender_role = row.GetValue<sbyte>("sender_role");if (sender_role == 0){Console.WriteLine($"{msg_body}\t\t\t\t\t");}else{Console.WriteLine($"\t\t\t\t\t{msg_body}");}
}

写在最后

存储的选择其实还是有点门道的,根据不同的应用场景,找出比较适合当前场景的几个方案,再选择一个成本没这么高的。

Cassandra 对聊天记录这个场景的存储还是有一定优势的,可以应对高速的数据增长,而不用在业务代码层做过多的适配;部署相对简单,无特殊依赖,运维成本相对较低。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

考勤机信息同步不到服务器,考勤机实时同步功能上线啦

一、考勤机管理重磅上线&#xff0c;告别手动处理打卡数据考勤机打卡仍然是当前企业主流的考勤方式&#xff0c;而考勤机打卡数据的核算也是HR最头痛的一点。HR每个月都要去电脑打开复杂难用的考勤机配套软件&#xff0c;导出并整理打卡数据&#xff0c;逐个统计员工的迟到、早…

对那些刷抖音外放音乐的人,就这么治他!| 今日最佳

世界只有3.14 % 的人关注了青少年数学之旅&#xff08;视频源B站春风里、&#xff09;我最讨厌抖音方外了&#xff01;↓ ↓ ↓

Asp.net 2.0 发送电子邮件

在网上收集的资料&#xff0c;和一点自己的心得 资料1 最基本的小例子&#xff0c;帮助上的例子看着可真够乱的&#xff1a; privatevoidSendMail() { MailMessage message new MailMessage("发件人电子邮件地址", "收件人电子邮件地址"); …

python目前版本强势英雄_王者荣耀目前版本什么英雄强势?

谢邀。在我之前写天梯排行时&#xff0c;总有不少人质疑我的段位和实力&#xff0c;可能是我的排行跟他们理解有所出入&#xff0c;欢迎各位在评论区理性讨论。在写这篇天梯排行前&#xff0c;我先放一下我的段位&#xff0c;证明一下我并不是瞎写乱写的。以下是我2018.5.5打的…

windows 服务实现定时任务调度

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;它可以与c#应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个&#xff0c;百个&#xff0c;甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的c#组件。Quartz的最新版本为Qu…

ios gb2312转utf-8

2019独角兽企业重金招聘Python工程师标准>>> 靠&#xff0c;想写个爬虫功能&#xff0c;结果一直是乱码&#xff0c;终于找到了转码的方法了 (NSString *) gb2312toutf8:(NSData *) data{ NSStringEncoding enc CFStringConvertEncodingToNSStringEncoding(kCFStr…

数学特级教师:数学除了做题目,我还必须让他们看这些!

▲ 点击查看很多时候&#xff0c;我们把数学简单的归为算数&#xff0c;归为计算能力&#xff0c;但数学更多的是一种培养逻辑思维能力的方式。包括一元二次方程、或者向量&#xff0c;或者几何证明。而在我们传统的数学课上&#xff0c;更多的是通过做题来理解数学知识&…

烟袋斜街-后海,印象已模糊

上个周末和猪头&#xff0c;廖廖一起去的。大家都神往已久&#xff0c;但是从未去过&#xff0c;这次一并去了&#xff0c;了却心愿。我不在北京&#xff0c;神往但是不能前去自然可以理解&#xff0c;但是他们两个已经在北京生活了六年&#xff0c;向往了六年&#xff0c;路程…

laya 怎么生成签名_PHP开发API接口签名生成及验证

开发过程中&#xff0c;我们经常会与接口打交道&#xff0c;有的时候是调取别人网站的接口&#xff0c;有的时候是为他人提供自己网站的接口&#xff0c;但是在这调取的过程中都离不开签名验证。我们在设计签名验证的时候&#xff0c;请注意要满足以下几点&#xff1a;可变性&a…

为啥 .NET 自带的 JsonSerializer 无法序列化 Field ?

咨询区 Theyouthis&#xff1a;最近我将项目升级到 .NET Core 3 之后&#xff0c;我发现自带的 System.Text.Json.JsonSerializer 序列化器有一个奇葩的问题&#xff0c;它不支持对 类字段 的序列化。。。参考如下代码&#xff1a;namespace ConsoleApp6 {class Program{static…

Windows下MinGW编译vim7.4

学习了一段时间Vim&#xff0c;感觉有些功能真的很方便。因学习原因&#xff0c;工作平台更换到一台老式Xp电脑上&#xff0c;重新安装了Vim7.4。官网默认版本不支持等宽字体和GDI渲染&#xff0c;需要手工编译一个修改过的版本。 1、下载MinGW 直接从MinGW官网下载的是在线安装…

告别 ROR windows 部署的噩梦-在 windows 上面 使用 Apache 部署 Ruby On Rails

今天去赛博把给朋友做的网站部署一下&#xff0c;服务器是一台windows2003的服务器。本身没想到在windows2003上面配置 ROR 是一场噩梦&#xff0c;因为网上看到了很多的 IIS 和 ROR 文档。不做不知道&#xff0c;一做才知道那简直是噩梦。忙到下午5点多还是没有配置好&#xf…

除了中国,原来还有这么多国家采用十二生肖的啊~| 今日最佳

世界只有3.14 % 的人关注了青少年数学之旅一、肥宅快乐水&#xff08;qiu&#xff1f;&#xff09;A岛-匿名版二、永远不轻言放弃知识冷知识青年 图片五目马丁饭三、终于知道怎么倒立问了冷知识日报社四、千万不能浪费文医疗音乐手绘君五、世界上所有采用十二生肖的国家冷知识日…

命中率_数据说话!詹姆斯的“皇家射手团”命中率为近十年最低

北京时间10月13日&#xff0c;湖人球员丹尼格林更新个人社交媒体&#xff0c;发布自己与奥布莱恩杯的合影等&#xff0c;并配文“随你怎么说&#xff0c;我又多了一样你拿不走的东西”。格林晒出自己与杜德利、詹姆斯的合影。此前&#xff0c;格林因为在NBA总决赛G5中未能命中极…

.net core 微服务下的手工签名实现,以及消除中文乱码

最近在实现一款业主签字的需求&#xff0c;签字前端由vue下的某个共享组件实现&#xff0c;其采用Canvas绘图方式实现签名图片的生成&#xff0c;后台主要提供签名前文档的呈现&#xff0c;以及签名后文件合成过的签名文档保存。FastReport报表生成器FastReport .NET是适用于.N…

高性能通道

高性能通道 http://detail.1688.com/offer/896868540.html https://www.datastoragecables.com/qsfp/qsfp-qsfp/qsfp-qsfp-ib/C9494-M-IB.html【infiniband】 http://pkg-ofed.alioth.debian.org/howto/infiniband-howto.html#toc6【infiniband-ib】posted on 2013-10-28 21:26…

清华学霸直博简历火了!CPU、操作系统、编译器全自主写,刘知远点赞

全世界只有3.14 % 的人关注了青少年数学之旅清华大学直博面试的一则简历上了知乎热榜&#xff1a;“实现了在自己写的CPU上运行自己写的操作系统&#xff0c;以及自己实现的编译器生成的程序”。简历主人是清华计算机系本科生周聿浩同学&#xff0c;他顺利拿到直博名额&#xf…

mysql索引有几种使用索引的好处_mysql索引的类型和优缺点

mysql索引的类型和优缺点索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)&#xff0c;它们包含着对数据表里所有记录的引用指针。注&#xff1a;[1]索引不是万能的&#xff01;索引可以加快数据检索操作&#xff0c;但会使数据修改操作变慢。每修改数据记录…

使用Blazor开发内部后台(一):认识Blazor

转载技术社区中一位朋友最新的文章&#xff0c;介绍自己为公司的 WebForm 遗留系统使用 Blazor 重写前端 UI 的经历。前言啊&#xff0c;又好久没写文章了&#xff0c;这一年一直在接触新的领域&#xff0c;扩展了一下技术面&#xff0c;学了很多新东西。前阵子发现公司内部有个…

[新手学go]关于go语言中的变量重复声明

代码一&#xff1a; package mainimport ("fmt" )func main() {a,b :1,2 a,b : 3,4fmt.Println(a, b) } 代码二&#xff1a; package mainimport ("fmt" )func main() {a, b : 1, 2k, b : 3, 4fmt.Println(a, b, k) //1&#xff0c;4&#xff0c;2 } 代码…