2021-01-05

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
大杂草
博客园 首页 新随笔 联系 订阅 管理
随笔 - 120 文章 - 0 评论 - 14
Redis基础篇(八)数据分片

现在有一个场景:要用Redis保存5000万个键值对,每个键值对大约是512B,要怎么部署Redis服务呢?

第一个方案,也是最容易想到的,需要保存5000万个键值对,每个键值对约为512B,一共需要25GB空间,选择一台32GB内存的用品来部署Redis,还剩余7GB空间,可以采用RDB对数据做持续久。

但是Redis服务使用不久后出现Redis的响应有时会非常慢。原因是采用了RDB持久化,在前面介绍RDB原理时,我们知道fork子进程的瞬间会阻塞主线程,而且内存越大,阻塞越长。

第一个方案不太适合,那么有更好的方案吗?Redis提供切片集群机制,多个Redis实例组成一个集群,按照一定的规则,把收到数据划分成多份,每一份用一个实例来保存。这样一来,在生成RDB时,数据量就小了,fork就不会阻塞主线程太长时间。

这里就引出一个问题:该如何保存更多的数据?

如何保存更多数据
通常有两种方案,分别是纵向扩展和横向扩展。

纵向扩展,指通过增加硬件配置来扩展,采用更大的内存,更多的CPU。好处是实施简单,但缺点是受到硬件和成本的限制,不可能无限扩展。

横向扩展,指通过增加机器来组成更大的集群,这也是分布式方案常用的方式。好处是扩展性好,但缺点是管理复杂。

在面向百万、千万级别的用户规模时,横向扩展的Redis切片集群会是一个非常好的选择。

在使用单个实例时,数据保存在哪里,客户端访问哪里,都是非常明确的。但是切片集群不可避免要解决多个实例分布式管理的问题,需要解决两大问题:

数据切片后,在多个实例之间如何分布?
客户端怎么确定想要访问的数据在哪个实例上?
数据切片和实例的对应分布关系
在Redis 3.0之前,官方没有切片集群的方案,从3.0开始,官方提供了一个名为Redis Cluster的方案,用于实现切片集群。

Redis Cluster方案采用哈希槽来处理数据和实例之间的映射关系。这里有两个映射关系:键值对与哈希槽的映射关系和哈希槽与实例的映射关系。下面我们来介绍一下这两个映射关系的映射过程。

键值对与哈希槽的映射过程

根据键值对的key,按照CRC16算法计算一个16bit的值。

再用这个16bit值对16384取模,得到0~16383范围内的模数,每个模数代表一个相应编号的哈希槽。

说明:Redis切片集群最多提供16384个哈希槽。

哈希槽与实例的映射过程

哈希槽与实例的映射关系有两个方案设置,分为自动和手动。

自动映射:使用cluster create命令创建集群,Redis会自动把这些槽平均分布在集群实例上。

手动映射:使用cluster meet命令搬运建立实例间的连接,形成集群,再使用cluster addslots命令,指定每个实例上的哈希槽个数。

说明:在手动分配哈希槽时,需要把16384个槽都分配完,否则Redis集群无法正常工作。

客户端如何定位数据
客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端。

集群刚创建时,实例如何互相知道哈希槽信息?Redis实例会扩展哈希槽信息,每个Redis实例都拥有完整的哈希槽信息。

另外,客户端收到哈希槽信息后,会缓存在本地,以便在客户端后续请求直接访问实例。

但在集群中,实例和哈希槽的对应关系不是一成不变的。最常见的变化:

在集群中,实例有新增或删除,Redis需要重新分配哈希槽;
为了负载均衡,Redis需要把哈希槽在所有实例上重新分布一遍。
Redis Cluster提供一种重定向机制,类似于HTTP协议的重定向。

客户端把一个键值对操作请求发给一个实例,如果这个实例没有这个键值对映射的哈希槽,这个实例就会给客户端返回MOVED命令的响应结果,包含新实例的访问地址。

GET hello:key (error)
MOVED 13320 172.16.19.5:6379

其中,MOVED命令表示,客户端请求的键值对所在的哈希槽13320,实际是在172.16.19.5这个实例上。

如果哈希槽没有完成迁移,客户端请求的数据并不在哈希槽时,客户端就会收到一条ASK报错信息,如下所示:

GET hello:key (error)
ASK 13320 172.16.19.5:6379

这个结果中的ASK命令就表示,客户端请求的键值对所在的哈希槽13320,在172.16.19.5这个实例上,但是这个哈希槽正在迁移。

和MOVED命令不同,ASK命令并不会更新客户端缓存的哈希槽分配信息。

Redis Cluster为什么不采用把key直接映射到实例的方式
整个集群存储key的数量是无法预估的,key的数量非常多时,直接记录每个key对应的实例映射关系,这个映射表会非常庞大,这个映射表无论是存储在服务端还是客户端都占用了非常大的内存空间。

Redis Cluster采用无中心化的模式(无proxy,客户端与服务端直连),客户端在某个节点访问一个key,如果这个key不在这个节点上,这个节点需要有纠正客户端路由到正确节点的能力(MOVED响应),这就需要节点之间互相交换路由表,每个节点拥有整个集群完整的路由关系。如果存储的都是key与实例的对应关系,节点之间交换信息也会变得非常庞大,消耗过多的网络资源,而且就算交换完成,相当于每个节点都需要额外存储其他节点的路由表,内存占用过大造成资源浪费。

当集群在扩容、缩容、数据均衡时,节点之间会发生数据迁移,迁移时需要修改每个key的映射关系,维护成本高。

而在中间增加一层哈希槽,可以把数据和节点解耦,key通过Hash计算,只需要关心映射到了哪个哈希槽,然后再通过哈希槽和节点的映射表找到节点,相当于消耗了很少的CPU资源,不但让数据分布更均匀,还可以让这个映射表变得很小,利于客户端和服务端保存,节点之间交换信息时也变得轻量。

当集群在扩容、缩容、数据均衡时,节点之间的操作例如数据迁移,都以哈希槽为基本单位进行操作,简化了节点扩容、缩容的难度,便于集群的维护和管理。

小结
数据扩容有两种方式:纵向扩展和横向扩展。Redis切片集群提供了横向扩展的模式。
集群的实例增减或者数据重新分布,会导致哈希槽和实例的映射关系发生变化。当客户端发送请求时,会收到命令执行报错信息。
在Redis3.0之前,Redis官方并没有提供切片集群方案。业界提供了一些成熟的方案,例如基于客户端分区的ShardedJedis,基于代理的Codis、Twemproxy等。
参考资料
09 | 切片集群:数据增多了,是该加内存还是加实例?
标签: redis, redis基础篇
好文要顶 关注我 收藏该文
大杂草
关注 - 29
粉丝 - 22
+加关注
0 0
« 上一篇: Redis基础篇(七)哨兵机制
posted @ 2021-01-05 08:24 大杂草 阅读(13) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】AWS携手博客园为开发者送福利,注册立享12个月免费套餐
【推荐】七牛云新老用户同享 1 分钱抢 CDN 1TB流量大礼包!
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· 【Python之路】特别篇–Redis
· php操作redis–列表篇
· php操作redis–集合(set)篇
· php操作redis–字典(hash)篇
· php操作redis–生存时间篇
» 更多推荐…

最新 IT 新闻:
· 蛋壳之后,房企们能否成为长租公寓的“解药”?
· 高通骁龙480发布:采用8nm工艺 处理器性能相比上一代翻倍
· 第九城市股价涨逾50%触发熔断,公告称将开展数字货币业务
· 不造整车造部件 华为驾车向何方?
· NASA回顾2020年在国际空间站上进行的关键实验
» 更多新闻…
公告
昵称: 大杂草
园龄: 9年5个月
粉丝: 22
关注: 29
+加关注
< 2021年1月 >
日 一 二 三 四 五 六
27 28 29 30 31 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 1 2 3 4 5 6
搜索

找找看

谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签
redis(25) leetcode(22) mysql(18) 算法(18) 链表(16) 数据结构(15) StackExchange.Redis(14) ASP.NET Core(11) 递归(6) 快慢指针(6) 更多
随笔档案
2021年1月(2)
2020年12月(24)
2020年11月(20)
2020年10月(21)
2020年9月(7)
2020年8月(6)
2020年7月(24)
2020年6月(13)
2020年1月(1)
2019年3月(1)
2019年2月(1)
最新评论

  1. Re:Redis基础篇(四)持久化:内存快照(RDB)
    写的很好
    –菜鸟无名
  2. Re:MySQL高可用(三)搭建主备同步实战
    嘿嘿
    –缺陷测试
  3. Re:MySQL高可用(二)主备延时如何解决?
    mark
    –BirdZ
  4. Re:MySQL锁(四)行锁的加锁规则和案例
    0x11
    –KMSFan
  5. Re:MySQL锁(四)行锁的加锁规则和案例
    看来是学了阿里mysql大神的教程
    –Itdotaer
    阅读排行榜
  6. 滑动窗口(Sliding Window)技巧总结(673)
  7. Cookie:SameSite,防止CSRF攻击(673)
  8. ASP.NET Core Authentication系列(一)理解Claim, ClaimsIdentity, ClaimsPrincipal(653)
  9. ASP.NET Core Authentication系列(二)实现认证、登录和注销(638)
  10. MySQL锁(二)表锁:为什么给小表加字段会导致整个库挂掉?(507)
    评论排行榜
  11. MySQL锁(四)行锁的加锁规则和案例(2)
  12. MySQL锁(二)表锁:为什么给小表加字段会导致整个库挂掉?(2)
  13. MySQL存储引擎:MyISAM和InnoDB的区别(2)
  14. 并查集(UnionFind)技巧总结(2)
  15. 《数据结构与算法之美》20——二叉树(二)二叉查找树(2)
    推荐排行榜
  16. ASP.NET Core Authentication系列(一)理解Claim, ClaimsIdentity, ClaimsPrincipal(7)
  17. ASP.NET Core Authentication系列(四)基于Cookie实现多应用间单点登录(SSO)(4)
  18. ASP.NET Core Authentication系列(二)实现认证、登录和注销(4)
  19. 滑动窗口(Sliding Window)技巧总结(4)
  20. ASP.NET Core Authentication系列(三)Cookie选项(3)
    Copyright © 2021 大杂草
    Powered by .NET 5.0 on Kubernetes
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值