关于redis:高并发场景下的会话服务数据读写设计思路附具体实施方案

7次阅读

共计 1648 个字符,预计需要花费 5 分钟才能阅读完成。

关上聊天软件,跟重要的人说个早安,扫一眼敞开了揭示的群音讯。置信这是很多人开始一天的“固定动作”。

随着挪动互联网和通信技术的高速倒退,线上交换已成为人们工作、生存的最重要形式。没带手机出门就像失去了全世界,电量低于 50% 就开始焦虑,因为好友列表里保留着咱们跟这个世界的联结。而通过会话列表关上一个会话,是咱们每天最频繁的动作之一。

IM 会话列表里会话的准确性、实时性会间接影响用户的应用体验与感触。本文分享融云 IM 即时通讯的会话服务数据读写设计思路。(关注 融云寰球互联网通信云 ,理解更多 IM & RTC 技术、场景话题 )

海量音讯会话的技术挑战

以单聊为例,用户 A 给用户 B 发送音讯,会产生两条会话记录:一条发送者的会话,一条接受者的会话。服务端会把这两条会话记录保留到数据库中,便于后续服务重启、更新、查问应用。

为了缩小服务端与客户端的交互,通常状况下,咱们会在会话记录中保留最初一条音讯。之后每次 A 给 B 发消息,或 B 给 A 发消息都会相应地更新这两条会话的音讯记录以及会话的最初工夫等。

如果某一时刻有 10 万个单聊用户发送音讯,便会产生 20 万条会话的增加(第一次聊天)或更新(后续聊天)操作。

在高频次读写的场景下,要提供精确疾速的查问,以及牢靠的存储就很考验服务在高并发场景下的解决能力了。

高并发下会话的查问操作

为了提供疾速的查问能力,咱们个别会把被频繁拜访的热点数据存储在缓存中,比方 Redis 等,以不便零碎疾速做出响应,而不是每次查问到数据库造成数据库压力。

为了缩小网络交互,升高服务器压力和晋升用户体验,咱们能够将热点数据放到服务内存中。当下次用户查问时,先去内存中查找是否存在。若存在则间接返回给用户;若不存在则去数据库中查问进去再放到内存中缓存起来,便于下次查问间接从内存中获取而后返回给用户。

(图 1 会话查问流程)

在分布式系统架构中,为了进步内存中缓存数据的命中率,咱们个别会采纳一致性 Hash 的形式,将一个用户的所有会话的操作都落到同一个服务实例上。这样做,不仅利于性能晋升,还有助于升高解决分布式读写带来的数据一致性问题的难度。

(图 2 一致性 Hash 算法计算服务落点)

高并发下会话的插入更新操作

解决完查问操作,咱们再来看看如何优化写操作,蕴含插入、更新以及删除等。

当有大量数据要增加到数据库中时,势必进步数据库查问的延时。该如何解决呢?

首先,内存大小是无限的,把所有的会话都放在内存中是不事实的。咱们会把新增加的会话放到 LRU 缓存中供查问应用,而后把要增加的会话写入到队列中,通过异步形式增加到数据库。此时你可能会想:这也并没有缩小插入数据库的次数呀,只是放到前面异步解决了而已。是的,到这一步的确达不到缩小操作数据库次数的成果,且往下看。

(图 3 异步化数据落地解决)

如果要增加会话 A,首先会更新到 LRU 中,而后把会话退出到队列中期待增加到数据库中。此时队列中若没有积压,则会间接更新到数据库中;若有积压,更新到此条会话时先比照 LRU 中的会话,把最新的会话更新到数据库中,并记录最新的会话工夫。

(图 4 会话数据存取策略)

如图 4,从队列中取出会话 1 进行存储,此刻队列中的会话 1 的音讯工夫是 1,LRU 中的会话 1 的音讯工夫是 4。相比拟 LRU 中的会话是最新的,则把 LRU 中的会话入库,并记录这条会话的更新工夫。当队列中更新到 time 为 3 这条旧的会话 1 时,因为这条会话的工夫比记录的工夫小,则抛弃不入库。这样,就能够无效缩小高并发积压的状况下,雷同会话频繁更新导致频繁入库的状况,从而达到减小数据库压力的目标。

总而言之,融云的会话服务数据读写的设计思路如下:

充分利用内存对热点数据进行缓存,缩小对后端数据存储服务的读取压力;
通过服务落点计算,晋升缓存命中率;
通过合并业务数据,尽量减少有效业务操作,缩小对存储服务的写入操作;
通过异步解耦业务与数据写入流程。

随着通信能力成为越来越多场景的根底需要,高并发场景越来越多,咱们也将一直对服务架构进行迭代,进步并发反对能力,为宽广开发者提供稳固、牢靠、低延时的通信能力反对。

正文完
 0