Redis核心技术-高可靠-集群方案(客户端分片、代理分片、Redis Cluster)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Redis在3.0版本前只支持单实例模式虽然Redis的开发者Antirez早在博客上就提出在Redis 3.0版本中加入集群的功能但3.0版本等到2015年才发布正式版。

各大企业等不急了在3.0版本还没发布前为了解决Redis的存储瓶颈纷纷推出了各自的Redis集群方案。这些方案的核心思想是把数据分片sharding存储在多个Redis实例中每一片就是一个Redis实例。

包括客户端分片、代理分片、Redis Cluster

客户端分片

客户端分片是把分片的逻辑放在Redis客户端实现比如jedis已支持Redis Sharding功能即ShardedJedis通过Redis客户端预先定义好的路由规则(使用一致性哈希)把对Key的访问转发到不同的Redis实例中查询数据时把返回结果汇集。这种方案的模式如图所示。客户端分片

一致性哈希算法consistent hashing

一致性哈希算法分布式系统中常用的算法。

什么是一致性 hash 算法:
一致性哈希算法也是使用取模的方法普通哈希算法取模算法是对服务器的数量进行取模而一致性哈希算法是对 2^32 取模具体步骤如下
1.一致性哈希算法将整个哈希值空间按照顺时针方向组织成一个虚拟的圆环称为 Hash 环
2.接着将各个服务器使用 Hash 函数进行哈希具体可以选择服务器的IP或主机名作为关键字进行哈希从而确定每台机器在哈希环上的位置
3.最后使用算法定位数据访问到相应服务器将数据key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置从此位置沿环顺时针寻找第一台遇到的服务器就是其应该定位到的服务器

一致性哈希算法问题hash 环的倾斜
一致性哈希算法在服务节点太少的情况下容易因为节点分部不均匀而造成数据倾斜问题也就是被缓存的对象大部分集中缓存在某一台服务器上从而出现数据分布不均匀的情况这种情况就称为 hash 环的倾斜。
hash 环的倾斜在极端情况下仍然有可能引起系统的崩溃为了解决这种数据倾斜问题一致性哈希算法引入了虚拟节点机制即对每一个服务节点计算多个哈希每个计算结果位置都放置一个此服务节点称为虚拟节点一个实际物理节点可以对应多个虚拟节点虚拟节点越多hash环上的节点就越多缓存被均匀分布的概率就越大hash环倾斜所带来的影响就越小同时数据定位算法不变只是多了一步虚拟节点到实际节点的映射。

比如一个分布式的存储系统要将数据存储到具体的节点上如果采用普通的hash方法将数据映射到具体的节点上如mod(key,d)key是数据的keyd是机器节点数如果有一个机器加入或退出这个集群则所有的数据映射都无效了。

一致性哈希算法解决了普通余数Hash算法伸缩性差的问题可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。

如Jedis的Redis Sharding实现采用一致性哈希算法(consistent hashing)将key和节点name同时hashing然后进行映射匹配采用的算法是MURMUR_HASH。

采用一致性哈希而不是采用简单类似哈希求模映射的主要原因是当增加或减少节点时不会产生由于重新匹配造成的rehashing。一致性哈希只影响相邻节点key分配影响量小。

客户端分片的优缺点

优点:

  1. 客户端sharding技术使用hash一致性算法分片的好处是所有的逻辑都是可控的不依赖于第三方分布式中间件。
  2. 服务端的Redis实例彼此独立相互无关联每个Redis实例像单服务器一样运行非常容易线性扩展系统的灵活性很强。
  3. 开发人员清楚怎么实现分片、路由的规则不用担心踩坑。

不足:

  1. 这是一种静态的分片方案需要增加或者减少Redis实例的数量需要手工调整分片的程序。
  2. 运维成本比较高集群的数据出了任何问题都需要运维人员和开发人员一起合作减缓了解决问题的速度增加了跨部门沟通的成本。
  3. 在不同的客户端程序中维护相同的路由分片逻辑成本巨大。比如java项目、PHP项目里共用一套Redis集群路由分片逻辑分别需要写两套一样的逻辑以后维护也是两套。

客户端分片有一个最大的问题就是服务端Redis实例群拓扑结构有变化时每个客户端都需要更新调整。如果能把客户端分片模块单独拎出来形成一个单独的模块(中间件)作为客户端 和 服务端连接的桥梁就能解决这个问题了此时代理分片就出现了。

代理分片

代理基本原理是通过中间件的形式Redis客户端把请求发送到代理代理根据路由规则发送到正确的Redis实例最后代理把结果汇集返回给客户端。

代理分片有Twemproxy、predixy、codis 。

Twemproxy

Twemproxy由Twitter开源的Redis代理其基本原理是通过中间件的形式Redis客户端把请求发送到TwemproxyTwemproxy根据路由规则发送到正确的Redis实例最后Twemproxy把结果汇集返回给客户端。

Twemproxy github地址https://github.com/twitter/twemproxy

Twemproxy通过引入一个代理层将多个Redis实例进行统一管理使Redis客户端只需要在Twemproxy上进行操作而不需要关心后面有多少个Redis实例从而实现了Redis集群。在这里插入图片描述

predixy

Predixy 是一款高性能全特征redis代理支持redis-sentinel和redis-cluster。

Predixy github地址https://github.com/joyieldInc/predixy

predixy完美的实现了对redis单例模式及集群模式的支持几乎完整的实现了redis原生的所有用于客户端的命令。多key命令、列表阻塞操作、发布订阅、脚本、扫描等高级功能全支持在使用redis单例模式下也支持事务。

codis

Codis 是 Wandoujia Infrastructure Team 开发的一个分布式 Redis 服务, 用户可以看成是一个无限内存的 Redis 服务, 有动态扩/缩容的能力. 对偏存储型的业务更实用, 如果你需要 SUBPUB 之类的指令, Codis 是不支持的. 时刻记住 Codis 是一个分布式存储的项目. 对于海量的 key, value不太大( <= 1M ), 随着业务扩展缓存也要随之扩展的业务场景有特效.

Codis是由豌豆荚自主研发支持平滑增加Redis实例的Redis代理软件其基于Go和C语言开发并于2014年11月在GitHub上开源。

codis github地址https://github.com/CodisLabs/codis/

Codis是如何分片的
Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024。
每一个 slot 都会有一个且必须有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供。数据的迁移也是以slot为单位的。

Redis获得动态扩容/缩容的能力增减redis实例对client完全透明、不需要重启服务不需要业务方担心 Redis 内存爆掉的问题. 也不用担心申请太大, 造成浪费. 业务方也不需要自己维护 Redis.

Codis支持水平扩容/缩容扩容可以直接界面的 “Auto Rebalance” 按钮缩容只需要将要下线的实例拥有的slot迁移到其它实例然后在界面上删除下线的group即可。

相对于twemproxy的优劣
codis和twemproxy最大的区别有两个

  • 一个是codis支持动态水平扩展对client完全透明不影响服务的情况下可以完成增减redis实例的操作
  • 一个是codis是用go语言写的并支持多线程而twemproxy用C并只用单线程。 后者又意味着codis在多核机器上的性能会好于twemproxycodis的最坏响应时间可能会因为GC的STW而变大不过go1.5发布后会显著降低STW的时间如果只用一个CPU的话go语言的性能不如C因此在一些短连接而非长连接的场景中整个系统的瓶颈可能变成accept新tcp连接的速度这时codis的性能可能会差于twemproxy。

相对于redis cluster的优劣
redis cluster基于smart client和无中心的设计client必须按key的哈希将请求直接发送到对应的节点。
这意味着使用官方cluster必须要等对应语言的redis driver对cluster支持的开发和不断成熟client不能直接像单机一样使用pipeline来提高效率想同时执行多个请求来提速必须在client端自行实现异步逻辑。 而codis因其有中心节点、基于proxy的设计对client来说可以像对单机redis一样去操作proxy除了一些命令不支持还可以继续使用pipeline并且如果后台redis有多个的话速度会显著快于单redis的pipeline。同时codis使用zookeeper来作为辅助这意味着单纯对于redis集群来说需要额外的机器搭zk不过对于很多已经在其他服务上用了zk的公司来说这不是问题

各个代理对比

特性predixytwemproxycodis
高可用Redis Sentinel或Redis Cluster一致性哈希Redis Sentinel
可扩展Key哈希分布或Redis ClusterKey哈希分布Key哈希分布
开发语言C++CGO
多线程
事务Redis Sentinel模式单Redis组下支持不支持不支持
BLPOP/BRPOP/BLPOPRPUSH支持不支持不支持
Pub/Sub支持不支持不支持
Script支持load不支持不支持
Scan支持不支持不支持
Select DB支持不支持支持
Auth支持定义多个密码给予不同读写及管理权限和Key访问空间不支持同redis
读从节点支持可定义丰富规则读指定的从节点不支持支持简单规则
多机房支持支持可定义丰富规则调度流量不支持有限支持
统计信息丰富丰富丰富

结论
在功能的对比上predixy相比另外两款代理更为全面基本可以完全适用原生redis的使用场景。在性能上predixy在各轮测试中都以较大优势领先。对各代理的总结如下

  1. predixy功能全面既可以使用单个主从redis也可使用Redis Cluster性能优异。
  2. twemproxy高可用依赖一致性哈希仅在缓存场景下适用不适用存储使用性能中等。
  3. codis适用redis集群使用性能一般。

Redis Cluster

可以查看另外一篇文章Redis核心技术-高可靠-集群cluster

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis