Redis系列之分片存储

Redis,一个完全免费开源的缓存软件,它是使用C语言编写,基于内存的高性能key-value数据库。Redis在互联网存储技术中得到非常广泛的应用,它作为缓存中间件,能够解决互联网应用中的一些技术瓶颈,且具有使用简单,性能强悍,功能应用场景丰富的特点。

 

本文讲述Redis的分片存储的架构。

什么是分片存储?

分片存储就是在Redis集群中,采用分布式存储数据的方案,让集群能够得到水平拓展。Redis中使用16384个虚拟哈希槽对集群进行分区,好比如在多个Redis集群中,把16384个槽的位置全部分到Redis集群的master中,每个Redis负责一些槽位,每个槽位都可以用来存储数据,这样就实现了分布式存储。每个Redis实例可以根据机器的性能分配到自定义数量的槽位用来存储数据,数据全部存在16384个槽中,但又分配在不同的Redis实例中,每个Redis实例至少有1个槽位。官网推荐最大Redis集群实例是1000个。

 

为什么要分片存储?

为了解决单机redis内存存储不足的瓶颈。

 

Redis是如何实现的?

Redis采用的是虚拟哈希槽分区,把所有的数据key值根据哈希函数映射到0~16384个槽中,每个key通过CRC16校验后对16384取模得到将数据分配到哪个槽中,每个Redis实例负责维护一部分槽。

计算公式:slot = CRC16(key)%16384

这样设计的好处:可以很方便的添加和删除redis集群中的节点。

Redis系列之分片存储

为什么要这样设计?

想想,在通常的使用到哈希时,需要计算某个key对应的哈希位置时,都是hash(key)%容量来计算哈希的位置,但是这样的做法在集群中特别不适合。假如在集群中使用这种方式计算数据存储的位置,当向集群中加入或删除一个节点的时候,根据公式,原来存储的数据的位置也要相应的变化,或是下次来取数据的时候再计算一次,发现数据找不到了,就乱套了。

 

在客户端信息中是没有记录集群的16384个槽分配信息的,那么客户端计算出槽后又是如何知道发送给哪个节点的?

1、客户端在不知道向哪个节点发送时,会先发送到任何一台redis实例,让redis实例去计算槽,当redis实例发现这个槽不在当前实例时会向客户端发回数据,并告诉客户端这个数据是发向哪个节点的,客户端再重定向发到正确的redis实例上。

2、客户端在进行一次重定向后,会在本地缓存一份redis分布槽的信息,下次就会根据缓存信息发送到正确的槽位置。当槽的位置变化时,客户端也会进行定时的刷新。

3、重定向分为两个情况:ask和moved。当redis实例确定槽不在当前实例时,会发送moved命令告知客户端发送到哪个正确的redis实例;当redis实例发现当前槽不在当前实例,且集群的节点在发生迁移时,会发送ask命令来告知客户端重新发送给我(因为我还不确定槽在哪个实例上,重试几次或许就迁移完了)。

ps:频繁的重定向会导致redis性能下降。

 

Redis集群为什么要设计16384个槽呢?

作者官网也做出了回答https://github.com/antirez/redis/issues/2576

1、如果槽位是65536个,那么发送心跳信息的信息头达8k,发送的心跳包过于庞大。我们都知道在集群中各个节点之间都有通信的,可以通过发送心跳看看对方是否还存活着,如果槽数量太大的话,会ping心跳的时候消息头太大了,带来一定的压力,浪费带宽。

2、redis集群实例主节点数量基本不会超过1000个。如果redis实例超过1000个,会给集群带来网络阻塞,很明显不是不会这样做的,对于16384个槽位也是够的,没必要搞到65536个。

3、槽位越小,节点少的情况下,压缩率高。Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

而16384÷8÷1024=2kb,怎么样,神奇不!

综上所述,作者决定取16384个槽,不多不少,刚刚好!

参考资料:https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650125660&idx=4&sn=e7f35b1a0b96e3927f554500a70b6d5d&chksm=f36ba87dc41c216b8f40a3f3106195579ace2e4b1e95af84c6ed09a2e3cd5e50675abd6609bc&mpshare=1&scene=24&srcid=&sharer_sharetime=1577150423515&sharer_shareid=a48016b3d542cd713a5def09940b925d#rd

 

--注意的要点--

数据倾斜和访问倾斜问题

前期尽量对业务数据进行预测,避免造成部分节点的槽压力过大,数据分布不均匀。

后期可以对槽进行数据迁移,尽量把数据压力分摊开来。

集群节点之间是有通信的,尽量避免带宽的消耗

避免使用一个大的集群,可以分多个集群。

redis集群仍然存在数据不一致问题

 

笔者相关文章回顾:

为什么需要缓存?—— 互联网架构中缓存介绍

Redis雪崩、击穿、穿透——Redis系列之雪崩、击穿、穿透

Redis分片存储 —— Redis系列之分片存储

Redis高可用——Redis系列之高可用集群

(文章内容不定期补充,若有不恰当的地方,恳请指正。)

相关文章:

  • 2021-06-29
  • 2022-12-23
  • 2021-05-28
  • 2021-12-27
  • 2022-01-05
  • 2021-05-09
  • 2021-06-29
  • 2022-12-23
猜你喜欢
  • 2021-07-04
  • 2021-10-15
  • 2021-11-05
  • 2022-12-23
  • 2021-09-08
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案