自己搞个网站,网站注册免费,化妆品 东莞网站建设,狗贩子怎么做网站卖狗背景 即时通讯(Instant Messaging)#xff0c;也就是我们常说的 IM#xff0c;其实在很多业务场景上都会有或多或少的应用#xff0c;有的会是核心#xff0c;有的会是辅助。既然是聊天#xff0c;那么必然就会产生聊天记录#xff0c;而且聊天记录随着人数的增加和时间的… 背景 即时通讯(Instant Messaging)也就是我们常说的 IM其实在很多业务场景上都会有或多或少的应用有的会是核心有的会是辅助。既然是聊天那么必然就会产生聊天记录而且聊天记录随着人数的增加和时间的推移很容易出现爆炸式的增长这个对存储其实压力是很大的。举个大家都很熟悉的例子一个群聊几分钟不看再打开就是 99 的未读消息。把即时通讯这个技术放到医疗环境下也是同样适用的。患者去线下医院看病肯定离不开和医生的问答这些问答对系统来说其实都是聊天记录。如果把这个场景放到线上进行也就是正常的和我们在微信聊天那样了。说了那么多有的没的也算是把大背景交代了一下那么接下来就看看这个聊天记录存储的选型吧。技术选型 既然要存储那么肯定就会有很多选择关系型数据库非关系型数据库等。当然这个很大程度上是和具体业务场景挂钩的离开了业务场景基本就是在空谈。在医患关系里面的聊天记录是一个十分十分核心的内容并且必须要长期保存不能丢可查询。并且这些聊天记录是和某次问诊强关联的所以单独拿出几条聊天记录出来是没有意义的因为他们没有关联串联不起来。按照以往的经验看一次问诊医生和患者之间的聊天记录在 50 条之内的占据了大部分超过50条的占少数。这个和其他的 IM 情景可能不太一样。MySQL业务开始大概率就是选用 MySQL 去存了这些数据了单库单表但是这种情况下很容易达到单表千万和上亿的级别。后面面临的基本就是分库分表的操作了。分库分表基本就是根据问诊号去进行哈希然后放到不同的库不同的表。这里会有一个不确定因素分多少个库和分多少张表分的多囊中羞涩分的少再一次达到量级的时候又要重新分大动干戈这个时候最怕的就是动到了哈希的规则。所以选 MySQL 的话到了中后期确实还是会有一点力不从心。线性扩展对这一块还是非常重要的。如果想改动小避免分库分表或许可以试试 TiDB但是它要的配置也不是中小企业所能接受的80% 以上的概率会被 Pass 掉。https://docs.pingcap.com/zh/tidb/stable/hardware-and-software-requirementsCassandraCassandra 是一个分布式、无中心、弹性可扩展的 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.GetValuestring(msg_body);var sender_role row.GetValuesbyte(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 对聊天记录这个场景的存储还是有一定优势的可以应对高速的数据增长而不用在业务代码层做过多的适配部署相对简单无特殊依赖运维成本相对较低。