
# GeminiDB Redis 在IM场景中的应用
#### 背景
即时通讯（Instant Messaging，简称IM）是一个实时通信系统，允许两人或多人使用网络实时地传递文字消息、文件、语音与视频。微信、QQ等IM类产品在这个高度信息化的互联网时代已成为生活必备品，IM系统中最核心的部分是消息系统，消息系统中最核心的功能是消息的同步、存储和检索。
- 消息同步：将消息完整地、快速地从发送方发送至接收方。消息同步系统最重要的衡量指标是消息传递的实时性、完整性、顺序性以及支撑的消息规模。
- 消息存储：即消息的持久化，传统消息系统通常支持消息在接收端的本地存储，数据基本不具备可靠性。现代消息系统支持消息在云端存储，从而实现消息漫游：账号可在任意客户端登录查看所有历史消息。
- 消息检索：消息一般是文本，所以支持全文检索也是必备的能力之一。传统消息系统通常来说基于本地存储的消息数据来构建索引，支持消息的本地检索。而现代消息系统支持消息的在线存储以及存储过程中构建索引，提供全面的消息检索功能。
 
#### 使用场景
IM系统可用于聊天，游戏、智能客服等诸多行业。不同行业对IM系统的成本、性能、可靠性、时延等指标的需求是不同的，架构设计需要进行平衡。
图1IM应用场景   
![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002080860520.png "点击放大")
#### IM系统架构
首先介绍IM系统架构设计所涉及到的一些基本概念。
- **传统架构和现代架构对比**
  图2传统架构和现代架构对比   
  ![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002084276465.png "点击放大")
  传统架构：
  - 先同步后存储。
  
  - 在线消息同步和离线消息缓存。
  
  - 服务端不会对消息进行持久化，无法支持消息漫游。
  
  
  现代架构：
  - 先存储后同步。
  
  - 划分消息存储库与消息同步库。消息存储库用于全量保存所有会话消息，主要用于支持消息漫游。消息同步库，主要用于接收方的多端同步。
  
  - 提供消息全文检索能力。
   
- **读扩散和写扩散** **对比**
  针对用户消息较多的场景，如何保证消息传递的可靠性、一致性并且有效地降低服务器或者客户端的压力。其中，采用何种读写模型对IM系统至关重要，这里介绍两种模型：读扩散和写扩散。
  图3读扩散   
  ![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002048325988.png "点击放大")
  如上图所示，用户B与每个聊天的人(A1,A2,A3)都有一个信箱（一种数据结构的抽象，用于存储消息），B在查看聊天信息时需读取所有有新消息的信箱。IM系统里的读扩散通常是每两个相关联的人就有一个信箱。
  读扩散优点：
  - 写操作(发消息)轻量，不管是单聊还是群聊，只需要往相应的信箱写一次即可。
  
  - 每一个信箱天然就是两个人的聊天记录，可以方便查看和搜索聊天记录。
   
  读扩散缺点：
  - 读操作(读消息)很重，存在读放大效应。
  
  
  图4写扩散   
  ![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002048326612.png "点击放大")
  如上图，在写扩散中，用户(B1,B2,B3)都只从自己的信箱里读取消息，但写(发消息)的时候，对于单聊跟群聊处理如下：
  - 单聊：往自己的信箱跟对方的信箱都写一份消息；同时，如果需要查看两个人的聊天历史记录的话还需要再写一份。
  
  - 群聊：发信息时需要针对所有群成员的信箱都写一份消息。群聊使用的是写扩散模型，而写扩散很消耗资源，因此群聊有人数上限(目前是500)。
  
  
  写扩散优点：
  - 读操作很轻量，只需要读取自己的邮箱。
  
  - 可以很方便实现消息的多终端同步。
  
  
  写扩散缺点：
  - 写操作很重，尤其是对于群聊来说。
   
 
- **推模式、 拉模式 和推拉结合模式** **对比**
  图5推模式、 拉模式与 推拉结合模式的对比   
  ![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002084286561.png "点击放大")
  在IM系统中，消息的获取通常有三种模式：
  - 推模式(Push)：新消息到达时由服务器主动推送给所有客户端；需要客户端和服务器建立长连接，实时性很高，对客户端来说只需要接收处理消息即可；缺点是服务端不知道客户端处理消息的能力，可能会导致数据积压。
  
  - 拉模式(Pull)：由前端主动发起拉取消息的请求，为了保证消息的实时性，一般采用推模式，拉模式一般用于获取历史消息；因客户端拉取新消息的时间间隔不好预设，太短可能会导致大量的连接拉取不到数据，太长导致数据接收不及时。
  
  - 推拉结合模式：兼顾Push和Pull两种模式的优点。新消息来临时服务器会先推送一个有新消息到达的通知给前端，前端接收到通知后就向服务器拉取消息。
   
#### IM技术挑战
图6IM系统总体架构图   
![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002086960484.png "点击放大")
Client双方通信会经过Server转发来完成消息传递。其核心为消息存储库和消息同步库。这两种库对存储层的性能有极高的要求。
- 支撑海量数据存储：对于消息存储库来说，如果需要消息永久存储，则随着时间的积累，数据规模会越来越大，需存储库支持容量无限扩展以应对日益增长的消息数据。
- 低存储成本：消息数据具有明显的冷热特征，大部分查询集中在热数据，冷数据需要一个低成本的存储方式，否则随着时间的积累，数据量不断膨胀，存储成本会不断上升。
- 数据生命周期管理：不管是对于消息数据的存储还是同步，数据都需要定义生命周期。存储库是用于在线存储消息数据本身，通常需要设定一个较长周期的保存时间。而同步库是用于写扩散模式的在线或离线推送，通常设定一个较短的保存时间。
- 极高的写入吞吐：绝大部分IM类场景，通常是采用写扩散模型，写扩散要求底层存储具备极高的写入吞吐能力，从而应对消息洪峰。
- 低延迟的读：消息系统通常应用于在线场景，具备较高的实时性，读取延迟应尽可能低。
#### GeminiDB Redis在IM场景中的优势
IM系统的核心是存储层，其性能差异将直接影响IM系统的用户体验。目前存储层可选择的数据库产品有很多，如HBase、开源Redis等等。选择何种数据库，需根据业务规模、成本、性能等指标来进行综合选择。这里介绍一种NoSQL数据库：GeminiDB Redis，在性能和规模上，可以满足IM系统对存储层的严格要求：海量数据存储、低存储成本、生命周期管理、写入吞吐大、读取时延低。
GeminiDB Redis是华为云数据库团队自主研发且兼容Redis5.0协议的云原生数据库，采用计算存储分离架构。存储侧使用自研的存储系统，容量无限扩展、强一致、高可靠。计算侧基于 LSM 存储引擎实现，通过将大量的随机写转换为顺序写，从而极大地提升了数据写入性能，同时也通过读缓存、bloom filter 等极大优化了读取性能。下图是GeminiDB Redis在IM场景的优势介绍。
图7GeminiDB Redis优势   
![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002048322916.png "点击放大")
基于GeminiDB Redis的IM应用案例
下图是基于GeminiDB Redis的IM系统模型图，使用stream作为基本数据结构。redis stream不仅可以作为消息存储容器，还实现了生产者、消费者等基本模型，具有IM系统的基本功能，如消息订阅，分发、增加消费者等，用户可基于GeminiDB Redis快速构建一套IM系统。创建一个群聊时，在redis中对应地为该群聊创建一个stream队列。在发送消息时，每个用户都将消息按照时间顺序添加到stream队列中，保证了消息的有序性。stream是一个持久化的队列，可保证信息不丢失。
图8基于Redis Stream及时通讯系统   
![](https://support.huaweicloud.com/redisug-nosql/zh-cn_image_0000002048165520.png "点击放大")
GeminiDB Redis通过一系列技术创新实现了读写性能水平扩展，秒级扩容，低成本以及自动备份等功能, 可作为IM系统的存储层，其优异的读写性能和高级特性将会极大助力IM应用.同时，GeminiDB Redis 在开源Redis的基础之上，较好平衡了性能和成本，能够广泛应用在智慧医疗、流量削峰、计数器等领域。
