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

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是数据的key,d是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了。

一致性哈希算法解决了普通余数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客户端把请求发送到Twemproxy,Twemproxy根据路由规则发送到正确的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在多核机器上的性能会好于twemproxy;codis的最坏响应时间可能会因为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)

理解并从头搭建redis集群

可以查看其它文章:理解并从头搭建redis集群

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
内容简介: Redis的的是完全开源免费的,遵守BSD协议,是一个性能的键值数据库。是当前最热门的的的NoSql数据库之一,也被人们称为数据结构服务器。本课程从Redis基本数据类型开始,了解不同数据类型的用法和底层实现 。进一步学习Redis的一些级特性与工作原理。了解Redis在分布式环境中的工作方式,和实际项目的使用及问题解决。 为什么学Redis? 原因很简单,快!这个问题在大并发,负载的网站中必须考虑.redis数据库中的所有数据都存储在内存中。由于内存的读写速度远快于硬盘,因此Redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势。项目中使用Redis,主要是从两个角度去考虑:性能状语从句:并发。当然,Redis的的的还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有其他中间件代替,并不是非要使用Redis的的的。因此,这个问题主要从性能和并发两个角度去答。性能:我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存,这样,后面的请求就去缓存中读取,请求使得能够迅速响应。 并发: 在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用的的Redis的做一个缓冲操作,让请求先访问到的Redis的的,而不是直接访问数据库。redis优势:1.运行在内存,速度快官方号称支持并发11瓦特读操作,并发8瓦特写操作,可以说是相当彪悍了。2.数据虽在内存,但是提供了持久化的支持,即可以将内存中的数据异步写入到硬盘中,同时不影响继续提供服务3.支持数据结构丰富(string(字符串),list(链表),set(集合),zset(sorted set - 有序集合))和Hash(哈希类型,md5加密出来的那个串)课程大纲: 为了让大家快速系统了解Redis核心知识全貌,我为你总结了「Redis核心框架图」,帮你梳理学习重点,建议收藏!!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲上云霄的Jayden

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值