Gleasy的NOSQL数据库集群Cloudredis

声明
本文为Gleasy原创文章,转载请指明引自Gleasy团队博客

一。问题的提出
redis是目前最快的NO-SQL数据库之一,GLEASY自测的结果也充分证实了这一点。除了性能极强之外,还提供了丰富的数据结构,可以更简洁地解决许多关键性能问题。基于此,GLEASY选用REDIS作为缓存服务器以及存储服务器。并且在此基础上研发了分布式的消息队列cloud-mq,分布式的即时通讯中间件cloud-im,分布式文件系统cloudfs,分布式作业调度中间件cloudjob.这些中间件共同组成了gleasy高性能分布式系统的架构基础。redis做缓存服务器是没有任何问题的,由于缓存本身意识着可丢失。但作为存储服务器,除性能之外,还必须考虑高可用性(High availability)和一致性(Consistency)以及扩展性(Scalability)。而这些能力洽洽是redis所欠缺的。基于这些需求,GLEASY自主研发了分布式的redis集群cloudredis。

二。设计思想
1. 软件架构
a. powered by java
b. 使用mina2作为NIO服务器

2. 主体架构图

图1. 集群内部结构图


图2.客户端连接集群

3. 设计思想
3.1 基本构成
cloudredis集群由若干个cloudredis结点以及1-2个binglog server组成。
cloudredis: 可以称为redis代理服务器。唯一代理某个redis服务器,所有对该redis的访问都必须通过cloudredis进行代理。
binglog server: 独立的redis服务器,用于保存读取binlog和集群状态信息.

3.1 一致性和高可用问题
所有访问redis的操作都经过cloudredis,cloudredis会分析所有访问请求,抽取其中的写命令,并将命令以特定格式写入binlog server。同时,每台cloudredis会启动1个后端线程读取binglog server中其它结点的binlog,另外1个后端线程执行得到的binlog内容。这种机制非常类似于mysql的binglo机制。不同之处在于,这里的binlog不是以文件方式存在,而是直接放在独立的binglog server(redis)里面。为什么这么设计?答案是:性能。文件式的binlog同步已经满足不了redis这种10万TPS的应用场景了。当然,如果由于某种原因(binlog server全部挂掉?),无法连上binlog server,cloudredis会把binlog暂时存在本地文件系统中,等待binglog server恢复之后,会一次过将本地文件系统中的binlog重新写入binlog server从而最大限度上保证binlog不丢失.通过写入和消费binlog,集群内所有结点的数据会做到准实时(延迟在MS级)。

3.2 如何高可用?
通过使用cloud-redis的客户端连接上集群内任意一台结点cloudredis之后,客户端需要定时向cloudredis获取集群内存活结点的信息(ip和端口)。并且全部与它们建立连接,将访问请求使用一致性HASH机制,平均地分配到这些结点上面去。集群内任意一台结点挂掉,客户端会重新进行HASH计算,并且将请求指向存活的结点,由此做到高可用。

3.3 如何实现一致性?
通过使用一致性hash,对某个key的访问会去到唯一的一台服务器,从而避免读写分离方案中的数据延迟带来的不一致性问题。

3.4 如何做到扩展性?
cloudredis并不解决扩展性问题,只解决集群内的高可用和一致性问题。扩展性问题通过客户端的人工shard方式实现。

3.5 Cloudredis与CAP的关系
Cloudredis集群首先是允许分区P的存在,不单止允许,而且从一开始就显式地引入分区P:集群中的每个结点,在某一时刻的状态都可能不一致的;显式引入分区,并且通过一致性HASH算法将某一KEY的访问限制在特定的结点(此处可以理解为一个不变性约束规则),结点内部保证数据一致性,结点之间通过严格遵守顺序的BINLOG日志来同步状态,所有结点BINLOG同步完成,分区消失,结点间数据一致性得以保证。Cloudredis在分区存在情况下,不关心其它结点是否存在,继续提供服务,因此是偏向于PA的设计,甚至可以说属于BASE(可用为主,软状态【非实时同步】,最终一致)。

三。 性能怎么样?
我们在相同环境下跟原生redis对比,来判断cloudredis的性能如何。测试工具使用redis自带的压力测试工具 redis-benchmark.
1. 原生redis的性能测试

C语言版本benchmark 200连接
[root@gleasy redis]# bin/redis-benchmark -h 192.168.0.11 -p 6677 -t set -n 1000000 -c 200
====== SET ======
1000000 requests completed in 13.60 seconds
200 parallel clients
3 bytes payload
keep alive: 1
2.42% <= 1 milliseconds
19.71% <= 2 milliseconds
86.69% <= 3 milliseconds
97.18% <= 4 milliseconds
99.36% <= 5 milliseconds
73518.60 requests per second

[root@gleasy redis]# bin/redis-benchmark -h 192.168.0.11 -p 6677 -t get -n 1000000 -c 200
====== GET ======
1000000 requests completed in 13.12 seconds
200 parallel clients
3 bytes payload
keep alive: 1

1.96% <= 1 milliseconds
17.60% <= 2 milliseconds
90.74% <= 3 milliseconds
97.44% <= 4 milliseconds
99.60% <= 5 milliseconds
99.94% <= 6 milliseconds
99.99% <= 7 milliseconds
100.00% <= 7 milliseconds
76190.48 requests per second

总结: 读操作76K,写操作73K.

2. 单结点的cloudredis性能测试(不开binlog)

[root@gleasy redis]# bin/redis-benchmark -h 192.168.0.11 -p 16677 -t set -n 1000000 -c 200
====== SET ======
1000000 requests completed in 12.99 seconds
200 parallel clients
3 bytes payload
keep alive: 1
9.57% <= 1 milliseconds
72.71% <= 2 milliseconds
84.95% <= 3 milliseconds
97.21% <= 9 milliseconds
97.93% <= 10 milliseconds
76952.67 requests per second

[root@gleasy redis]# bin/redis-benchmark -h 192.168.0.11 -p 16677 -t get -n 1000000 -c 200
====== GET ======
1000000 requests completed in 12.03 seconds
200 parallel clients
3 bytes payload
keep alive: 1
11.86% <= 1 milliseconds
77.96% <= 2 milliseconds
86.32% <= 3 milliseconds
89.91% <= 4 milliseconds
83153.17 requests per second
小结: 读操作 83K, 写操作 76K。 (性能比原生的redis有10%的提升,很惊奇?后面讲解原理。。。)

3. 集群双结点,开binlog,cloudredis性能测试(使用cloud-redis客户端)

[root@gleasy cloudredis]# bin/redis-benchmark -t get -h 192.168.0.11 -p 6679 -d 15 -l 60 -c 800 online casino -b shard -m 10 -n 50
成功:5139656
失败:0
命中缓存:0
总时间:48002194
最长用时:117
最短用时:0
平均用时:9.339573309964713
min tps:0
max tps:195370
avg tps:84256

[root@gleasy cloudredis]# bin/redis-benchmark -t set -h 192.168.0.11 -p 6679 -d 15 -l 30 -c 800 -b shard -m 10 -n 50
成功:2282561
失败:0
命中缓存:0
总时间:24004343
最长用时:121
最短用时:0
平均用时:10.516408104756017
min tps:0
max tps:140498
avg tps:73631
小结: 读操作84K,写操作73K

通过以上对比,我们可以清晰地看到,cloudredis无论在单结点还是多结点情况下,都至少能够做到和原生redis相同的性能要求。甚至会有更好的性能表现。

四。 运维工具
除了作为redis的代理之外,cloudredis还提供了一系列的集群管理工具,方便管理集群
1. info

说明:会在原来redis info命令基础之上,额外返回本集群的信息
示例:
#集群信息
结点标识:11-6673
IP:192.168.0.11
端口: 6673
代理的redis:192.168.0.11:16673
当前连接数:34
内存(最大/己分配/己分配中剩余/最大可用):2048/512/170/1706(M)
CPU核数:4
集群开启:true
是否只读:false
日志开启:true
日志故障:false

#其它结点
结点:10-6673
IP:192.168.0.10
端口:6673
己同步binlog位置:1420434 1432391
最大binlog位置:1420434 1432391

2. cluster start|stop

说明: 开启/关闭本结点的集群功能
讲解:
cluster start: 将本结点挂上集群,可以被客户端访问到
cluster stop:将本结点从集群拿下,客户端将不再继续访问得到

3. cluster syn ip port

说明: 非常好用的同步工具
讲解:
cluster syn 192.168.0.11 6673 :与目标服务器完全同步数据(清除自己的原有数据,将将目标服务器数据全部拿过来),并且会将目标服务器的binlog位置等信息同步过来。是集群管理必用的工具。

4. cluster binlog start|stop|restart

说明: 开启,关闭,重新开启binlog
讲解:
cluster binlog start: 开启binlog
cluster binlog stop: 关闭binlog(不再写日志啦,这个很危险)
cluster binlog restart: 用于将本地文件系统中暂存的binlog一次性刷新进binlog server。用于binlog server故障恢复后使用。

5. cluster visible on|off

说明:对客户端可见,不可见
讲解:
cluster visible on :客户端可以访问得到
cluster visible off:客户端不可访问,等于集群中没有这个结点

6. cluster lockwrite|unlockwrite

说明:设置只读和可读写
讲解:
cluster lockwrite:只读(挂起所有写操作)
cluster unlockwrite:结束只读(执行所有被挂起的写操作)

五。 其它
1. 与redis官方研发中的cluster方案有何异同?为何要自己开发?
答: 通常来说,我们认为cluster主要的能力包括:扩展(Scalability),高可用,性能分担。附加要求为一致性,安全性等。从这层意思上说,我们的cloudredis应该只算是准集群方案,它并不解决扩展性问题。扩展性问题我们通过redis-shard使用人工shard方式来解决。我们使用binlog方式进行数据同步,一致性hash进行请求分发,而且把大量的功能放在客户端。之所以这么做,最根本的原因是我们要保持本方案的高性能。采用真正意义上的cluster,其性能从理论上必定有非常严重的损耗。这个可以从淘宝的tair系统得到证实。而我们的集群方案,可以保持甚至可以超越原生的单台redis。

2. 为什么代理的性能可以超越原生redis?
答: redis有一套机制叫做pipeline. 比如A,B,C命令同时到达cloudredis,如果不使用pipeline,我们可能要逐条命令送过去执行,假如每个需要1MS,我们共要3MS。但我们可以将A,B,C打包发送给redis执行,需时1.5MS。这样我们就节省了1.5MS。如果更多的命令同时到达,节省的辐度会更大。当到大一定程度便足可以抵销代理与REDIS之间的网络等开销。

六。 缺点和限制
1. cloudredis并不能完全支持全部的redis命令,不被支持命令包括: blpop,blpush,blpoprpush,subscribe,unsubscribe,zinterstore,zunionstore.
2. cloudredis使用多线程,会有更高的CPU占用,这也是压力测试中表现优秀的关键因素之一。

七。关于开放源码的说明
Gleasy现阶段暂无开放源码的打算,但为学习目的可提供源码供大家参考。如有需要可以在留下联系方式。

此条目发表在 Java技术, 分布式技术, 数据库技术 分类目录。将固定链接加入收藏夹。

Gleasy的NOSQL数据库集群Cloudredis》有 3 条评论

  1. 说:

    本人在互联网公司搞分布式系统开发,能否把贵公司代码发我一份作为学习和参考,谢谢。可以的话请发我126邮箱:zhangnian88123@126.com,谢谢。

  2. Pingback 引用通告: Gleasy分布式架构体系介绍 | Gleasy团队博客

  3. Pingback 引用通告: 一种redis主-主解决方案及其实现 | Gleasy团队博客

发表评论