Redis在即时通讯系统中的应用

2017-02-27 03:11李鹏鹏郑扬飞刘玉龙
软件 2017年1期
关键词:即时通讯服务端内存

李鹏鹏,郑扬飞,刘玉龙

(华北计算技术研究所,北京 100083)

Redis在即时通讯系统中的应用

李鹏鹏,郑扬飞,刘玉龙

(华北计算技术研究所,北京 100083)

传统的即时通讯系统的弊端之一是数据库I/O次数频繁,因为在IM中大量短而多的消息持续在磁盘的数据库上进行读写。为了解决数据库造成的系统瓶颈,选取Mysql和内存Key-Value引擎的NoSQL数据库Redis两级存储,从而给出基于XMPP的即时通讯系统高可用的优化方案。

Redis;XMPP;即时通讯系统;数据分片

0 引言

即时通信[1]是以Internet网络及有线、无线网络为基础物理设施,在交互双方之间实时地传送文本、语音和图像等信息的通信方式。新时代的即时通讯系统,用户需要其提供更快、更稳定、更可靠的即时通信服务。伴随着Internet技术的不断发展,影响网络速度的瓶颈主要集中在访问距离和服务器承载负荷能力方面[2]。内存数据库以其明显的优势补足了传统通信技术架构[3]的不足。本文主要介绍NoSQL在即时通讯系统中的设计与实践。

1 Redis技术研究

1.1 Redis技术简介

Redis[4]是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis是一个Key-Value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis是一个远程内存数据库[5],它不仅性能强劲,而且还具有复制特性以及为解决问题而生的独一无二的数据模型。Redis提供了5种不同类型的数据结构,各式各样的问题都可以很自然地映射到这些数据结构上:Redis的数据结构致力于帮助用户解决问题,而不会像其他数据库那样,要求用户扭曲问题来适应数据库。除此之外,通过复制、持久化(persistence)和客户端分片(client-side sharding)等特性,用户可以很方便地将Redis扩展成一个能够包含数百GB数据、每秒处理上百万次请求的系统。

1.2 Redis特性

NoSQL概念在2009年被提了出来。NoSQL最常见的解释是“non-relational”,“Not Only SQL”也被很多人接受。(“NoSQL”一词最早于1998年被用于一个轻量级的关系数据库的名字。)

传统的关系数据库具有不错的性能,高稳定型,久经历史考验,而且使用简单,功能强大,同时也积累了大量的成功案例。在互联网领域,MySQL成为了绝对靠前的王者,毫不夸张的说,MySQL为互联网的发展做出了卓越的贡献。随着时间的推移,线上数据越来越多,悄然进入大数据时代。网站开始快速发展,火爆的论坛、博客、sns、微博逐渐引领web领域的潮流。巨大的流量给公司带来了可观的收入,也带来了数据库存储与查询并优的瓶颈。

Redis是基于C/C++开发的一款K-V数据库,特点是运行异常快,使用协议是类Telnet。除此之外还有以下几个特性:

● Redis持久化

通常,Redis将数据存储于内存中,或被配置为使用虚拟内存。通过两种方式可以实现数据持久化:使用截图的方式,将内存中的数据不断写入磁盘;或使用类似MySQL的日志方式,记录每次更新的日志。前者性能较高,但是可能会引起一定程度的数据丢失;后者相反。

● Redis主从同步

Redis支持将数据同步到多台从库,这种特性对提高读取性能非常有益。

● Redis数据类型

作为Key-value型数据库,Redis也提供了键(Key)和键值(Value)的映射关系。但是,除了常规的数值或字符串,Redis的键值还可以是以下形式之一:

➢ Lists(列表)

➢ Sets(集合)

➢ Sorted sets(有序集合)

➢ Hashes(哈希表)

键值的数据类型决定了该键值支持的操作。Redis支持诸如列表、集合或有序集合的交集、并集、查集等高级原子操作;同时,如果键值的类型是普通数字,Redis则提供自增等原子操作。

● 支持事务

Redis事务可以一次执行多个命令,并且带有以下两个重要的保证。第一,事务是一个单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断;第二,事务是一个原子操作,事务中的命令要么全部被执行,要么全部都不执行。

一个事务从开始到执行会经历以下三个阶段:开始事务,命令入队,执行事务。

● Redis管道技术

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:首先,客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应;然后,服务端处理命令;最后,将结果返回给客户端。Redis管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。

Redis其实开创了一种新的数据存储思路,使用Redis,我们不用再面对功能单调的数据库时,把精力放在如何把大象放进冰箱的问题,而是利用Redis提供的灵活多变的数据结构和数据操作,为不同的大象构建不同的冰箱。根据Redis的特性,总结出其最佳应用场景有:适用于数据变化快且数据库大小可遇见(适合内存容量)的应用程序,例如:股票价格、数据分析、实时数据搜集、实时通讯。

1.3 Redis优势分析

Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis特点突出,正是因为这些特点所以才凸显其以下几个优点:

✧ 性能极高-Redis能读的速度是110000次/s,写的速度是81000次/s。

✧ 丰富的数据类型-Redis支持二进制案例的Strings,Lists,Hashes,Sets及Ordered Sets数据类型操作。

✧ 原子-Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

✧ 丰富的特性-Redis还支持publish/subscribe,通知,key过期等等特性。

2 Redis存储设计

即时通讯系统一般分为客户端与服务端,客户端较轻,关键逻辑在服务端,一般分为三到四层,采用B/S和C/S混合架构。即时通讯系统,主要包含的业务场景有,注册登录、即时会话[6]、组织机构、文件传输。对于所有的用户,有在线和离线的状态。并且,对于在线状态用户的长连接需要有专用服务器来维护,表现在架构中的连接服务。系统逻辑架构示意图如图1。

2.1 数据库详细设计

数据库设计图,见图2:

如图2所示,根据业务逻辑层,将数据库进行分库设计[7],并且每一个分片是主从设计。

初始设计使用4台MySQL分库。分库的策略是:

图1 系统逻辑架构示意图

图2 数据库设计图

如公式(1),proxyNo代表选择Redis数据库编号0-3。具体计算公式解释为,使用SID(发送方用户ID)+RID(接收方用户ID) mod 64,0-15落在第0个库rdb0上,16-31落在第1个库rdb1上,32-47落在第2个库rdb2上,48-63落在第3个库rdb3上。这样的优势在于,A用户发送B用户和B用户发送A用户的消息,都会落在同一个底层数据库。基于此设计,对于查询用户A和B的聊天记录,只需要使用一个SQL查询即可,而不需要写脚本跨库查询,减少IO的开销,以达到性能提升的效果。

分库设计和主从备份实现了高并发和高可用的设计。但是,当Mysql单表的数据量达到1000W的时候,使用索引等对表进行优化已经到达瓶颈,所以需要从DDL、DML、DQL对数据库进行设计。根据业务需求,在Redis上设计了消息表、用户状态表及其索引,并且实现两个用户之间消息记录的查询。

(a)针对聊天消息表

按照时间进行分区。基于此设计的原因在于:用户使用场景一般为按照时间逆序查询聊天记录,越新的数据越热。创建聊天表的SQL如图3。

图3 消息表创建sql

(b)用户状态表

该表主要用于维护用户连接信息,当长链接被意外打断,用此表信息恢复用户之前状态,起到“保留现场”的作用。创建表sql如图4。

图4 用户状态表创建sql

其中,sessionId是聊天双方,(较小的ID在前,较大的ID在后)的会话状态信息,pcMid是用户pc端已读的最大消息ID;mobileMid是用户手机端已读的最大消息ID;hashvalue是(发送方用户ID+接收方用户ID)mod 64计算后的值,为了记录该条数据在具体的某一个数据库中。

(c)未读消息索引

对于未读消息的查询,为了实现大数据量更加高效的查询,在数据库中为消息表和用户状态表添加索引。创建索引SQL如图5。

图5 获取未读消息索引

(d)DQL未读消息查询

根据以上设计,查询用户id为1,2之间的聊天内容,优化[8]后的SQL语句如图6。

2.2 业务场景应用

在3.1章节中介绍了数据库的设计,并且给出了优化设计方案。针对设计的方案,我们利用具体的业务场景来完成对设计方案的试验。首先,图7给出的是id为1的用户与id为2的用户之间的文本通讯过程以及步骤。

图6 未读消息SQL

图7 业务结构图

如图7所示,首先,定义:发送方用户ID为srcid,接收方用户ID为destid,每个会话的当前消息ID为msgid(针对每个发送方和接收方,自增)。

针对离线消息的场景流程如下:

1. 发送方用户通过电脑将消息发送至Web服务器.消息主要内容(srcid,destid,msgid)

2. Web服务器根据srcid,destid获取会话的mid(会话状态的自增ID)

每个会话都按照较小ID在前,较大ID在后作为Redis的key,并且,每个会话的状态信息都设置过期时间。如果Redis里没有会话的状态,则用时间戳填充。数据格式如表1。

3. 将消息放入持久化队列,并且更新Redis未读消息列表

首先将(srcid,destid,mid,msg)放入持久化队列,然后更新Redis的用户未读消息列表,未读消息列表在Redis的存储结构如表2。

表1 公共数据区数据结构

表2 PC端未读消息存储结构

如表2所示,Mobile端未读消息存储结构和PC端设计原理一致。其中,在接收方ID的前面增加一个前缀,表明是手机未读消息还是PC未读消息。这个作为表结构的key。而value是一个HashMap,这个HashMap的key是发送方ID,value是未读消息数量。

一旦用户登录,直接拉取该用户的HashMap内容展示,这部分内容是有过期时间的,假如用户长时间未使用,这个PC-destid和Mobile-destid的条目将被删除。如果程序发现这个条目不存在.则去数据库中查询未读消息列表。

假如A的ID是1000,B的ID是1001,B给A发送了三条消息,但是A一直没有在线。程序将做如下操作:

如果此时A登录手机客户端,点击未读消息.则对Redis操作如下,删除对应条目。

在此情况下,并且回写数据库一个状态标识(已读的最大mid)。这个回写数据库的过程,也是异步的,每隔30 s回写一次数据库状态。这样的设计,虽然在数据库上对不同类型设备进行了状态冗余,但是保证了未读消息在不同端多次提醒。

4. 如果发送方的其他设备在线,或者接收方的设备在线,则转发消息。

5. JAVA从队列中异步获取消息,然后批量Insert到数据库。

2.3 实验验证

对于系统设计的方案,编写脚本进行性能测试[9]。测试结果,如。

图8 测试结果图

Redis插入效率,在不使用持久化的情况下,可以达到7.3 W;在持久化情况下,保证数据最终一致性的前提下,也可以达到2.3 W。针对本文的设计,此套系统可以胜任日均超1 KW量的即时通讯任务。

3 结论

在即时通讯系统中使用Redis进行优化,为传统IM的升级革新提供了新的思路。由于使用了无事务的NoSQL数据库Redis,所以在本文中对所有消息有编号进行确认,类似于网络中的ACK,解决了在故障情况下批量消息未成功发送到指定用户端所带来的数据丢失的问题。最后,基于Redis的即时通讯系统,相比于传统的即时通讯系统无论在性能还是用户体验度都有很大的提升,达到了预期的效果。

[1] 郭鑫杰. 即时通讯系统的设计与实现[D]. 南京大学2012.

[2] 林源晟. 基于XMPP协议的即时通信服务器的设计与实现[D]. 电子科技大学 2013.

[3] 董恒竞. 一种企业移动应用平台架构设计[J]. 软件, 2016, 37(01)∶ 136-138.

[4] 马豫星. Redis数据库特性分析[J]. 物联网技术. 2015(03).

[5] 邱祝文. 基于redis的分布式缓存系统架构研究[J]. 网络安全技术与应用. 2014(10).

[6] 张勇, 裴东良, 张会兵. 消息传输系统研究[J]. 软件, 2016, 37(3)∶ 51-54.

[7] 朱思征, 王山山, 敖丽娜, 等. 大数据环境下刀具仓储与采购智能协同研究[J]. 软件, 2016, 37(02)∶ 29-32.

[8] 杨淙钧, 艾中良, 刘忠麟, 等. 基于多级列式索引的海量数据高效查询设计[J]. 软件, 2016, 37(3)∶ 79-83.

[9] 凌高源, 朱琳. 上网流量监测管理软件设计与实现[J]. 软件, 2016, 37(01)∶ 48-52文献内容.

[10] Wang S, Liu Z, Sun Q, Zou H, Yang F. Towards an accurate evaluation of quality of cloud service in service-oriented cloud computing. Journal of Intelligent Manufacturing, 2014, 25(2)∶ 283-291.

The Application of Instant Messaging System Based on Redis

LI Peng-peng, ZHENG Yang-fei, LIU Yu-long
(North China Institute of Computing Technology, Beijing 100083)

One of the drawbacks of the traditional instant messaging system is the frequent number of database I / O, because a large number of short messages in IM continue to read and write on the disk database. In order to solve the system bottleneck caused by the database, the NoSQL database Redis two-level storage of Mysql and Key-Value engine of memory is selected, and the optimization scheme of XMPP-based instant communication system is presented.

Redis; XMPP protocol; Instant Messaging system; Database sharding

TP311

A

10.3969/j.issn.1003-6970.2017.01.024

李鹏鹏(1991-),男,研究生,计算机应用技术;郑扬飞(1976-),男,高级工程师,主要研究方向为企业信息化,分布式系统;刘玉龙,男,高级工程师,信息系统顶层设计,信息集成

本文著录格式:李鹏鹏,郑扬飞,刘玉龙. Redis在即时通讯系统中的应用[J]. 软件,2017,38(1):115-119

猜你喜欢
即时通讯服务端内存
外部高速缓存与非易失内存结合的混合内存体系结构特性评测
“春夏秋冬”的内存
云存储中基于相似性的客户-服务端双端数据去重方法
新时期《移动Web服务端开发》课程教学改革的研究
民事诉讼中即时通讯记录的证据采用进路
在Windows Server 2008上创建应用
即时通讯软件发展模型的实证研究
科学技术哲学视域下的即时通讯
基于内存的地理信息访问技术
摸清黑客套路防范木马侵入