使用Redis搭建持久化K-V存储

最近在项目中需要在多机之间共享一些集合,Hash等有类型的数据结构,如果基于Mysql来存储的话需要预先定义一系列表结构并维护表结构和数据结构的一致性,后续还需要根据时间对数据库做旧数据清理工作,所以开始调研一些能满足下列需求的存储引擎。
  1. 具有高可用,持久化的特性。
  2. 数据可以设置失效时间,方便自动数据清理。
  3. 支持常用数据结构,如集合,有序集合,Hash map,列表等。
  4. 支持事务操作,方便原子化的对多个key进行操作。
  5. 有Python,Golang语言的客户端。
通过对公司内部的Tair,开源的Redis,Memcache,LevelDB, MongoDB等产品进行比较,感觉Redis最符合需求,现将我对Redis-3.2的理解和使用方法总结一下。

Redis的典型使用方式:


非持久化的独立部署方式:

这种使用方式主要的使用场景是使用Redis做为Cache集群,存储可以丢失的cache数据,首要考虑目标是速度,不考虑持久化。典型的使用方式如下:

使用Redis搭建持久化K-V存储

所有数据都在内存中,不落盘,集群中实例之间相互无感知,每个实例都是对等的,在客户端做基于一致性hash的数据分配。用户只需要告诉客户端所有可用的集群实例列表,由客户端对key做一致性hash来决定key会落到那个redis实例上,从而决定会对哪个实例进行读写。
除了在客户端做hash还有一种方式是使用Proxy代理,由代理来负责对key做hash决定客户端的请求会落到哪个实例,客户端只需要连接到proxy就行了。Twemproxy 就是一个开源的实现了Redis和Memecached协议的Proxy。


持久化方案:

Redis有两种持久化方案: RDB和AOF, 说白了前者就是dump全量数据做snapshot,后者是记录增量操作日志。
两者的优缺点也很明显: RDB适合做数据备份和数据快速恢复,但是做snapshot是一个很费时的过程,不可能做到频率很高,一般是每几分钟进行一次,所以不能保证最近几分钟之内的数据不会丢。
AOF做增量操作日志的代价不是很高,一般是每秒一次,所以能保证最多只丢一秒的数据。
不过需要指出的是这两种方式并不冲突,可以同时开启,我们在部署的时候也是这么做的。
社区也在考虑结合RDB和AOF,达到类似PostgreSQL的数据安全性(有点小期待呢)。


主从复制(Replication):

Redis采用1:N主备结构来实现replication。但是需要注意的是为了提高效率,Master和Slave之间是异步进行数据同步的,这也就意味着主备之间可能存在数据不一致的情况,但是有配置可以指定主备之间的最大数据延时,需要用户自己根据业务场景进行配置。


使用Sentinel哨兵实现HA:

Sentinel是Redis提供的一个哨兵组件,主要实现了两个功能:
1. Master和slave监控,一旦Master不可用,则Sentinel集群会进行投票,进行failover,选举新的master。
2. Master和Slave的配置提供,客户端只需要从sentinel即可读取当前的主从配置即可,不需要主动连接Master和Slave。


Redis Cluster集群部署方式:

Redis Cluster使用多个Redis实例进行容量扩展。这种方式同独立部署方式的区别是集群的实例之间不是相互独立的,是相互感知的,每个实例都知道其他实例的存在,并会进行通信同步全局的sharding和集群配置。

此模式下如何对数据进行切分(sharding):
1. 客户端不会进行一致性hash,而是会对key做CRC16运算,然后将产生的值%16384, 从而产生一个0~16383的值。
2. 集群会将所有key切分成16384个hash slot, 并根据集群中redis实例的个数将hash slot均分到所有的实例中。
3. 将1中产生的值直接对应到相同值的hash slot,而集群中包含此hash slot的机器既是包含此key的机器
4. 当3中客户端计算出的机器因进行过人工resharding而不在包含3中的slot时,此机器会根据自己感知的集群sharding配置返回redirect告知真正包含所需hash slot的机器。

不过有几个需要注意的地方:
1. 当需要对集群进行扩容时,将新机器加到集群中之后其实新机器并没有包含任何hash slot,需要手动重新进行sharding分配hash slot并进行数据迁移。
2. 连接Redis Cluster的客户端和标准客户端是不一样的,不能混用。
3. Transaction支持受限:当transaction中涉及的key不属于同一个redis实例时无法完成transaction。
4. 多key操作受限:如取两个集合的交集操作,若两个集合的key属于不同的机器,则无法完成。


最终选定的部署方式:

由于Redis Cluster部署方式下transaction和多key操作受限,而单台机器的容量能满足我们的业务需求,所以没有选择Redis Cluster部署方式,最终选择的部署方式如下:

使用Redis搭建持久化K-V存储

1. 采用一台Master加两台slave做replication。
2. 采用三台机器搭建sentinel集群,保证高可用性。
3. 将sentinel部署在使用的redis服务的三台Tesla API后端机,使得sentinel能反映API到Master/slave的真实可用性。
在这种部署方式下再加上针对redis server和redis sentinel的配置和运维控制脚本即可完成服务的搭建。

上一篇:LinQ to entities 不能识别方法“system.string.ToString(system.String)”.因此该方法无法转换为存储表达式


下一篇:[发布] QQGame 连连看辅助工具(限制功能版)