Redis17 - Sharding

之间我们抛出了单机Redis的几种问题:

  • 单点故障
  • 容量有限
  • IO压力

其中我们使用sentinel解决了单点故障的问题实现了高可用,使用主从复制实现读写分离解决了IO压力的问题,但是如何解决Redis容量的问题呢? - Sharding分片实现扩容

Redis扩容的几种方案

1.数据可以分类,交集不多
在这种情况下,我们可以通过client做业务拆分,不同的业务使用不同的Redis


根据业务拆分

2.数据没办法划分拆解

  • 根据hash取模进行划分
    在客户端通过hash取模算法从不同的Redis中读取数据,其可以实现Redis的扩容,但是取模的数字必须是固定的,影响分布式下的扩展性


    根据hash取模算法拆分
  • 根据Random随机拆分
    在客户端通过random随机从不同的Redis中读取数据,其弊端是完全随机,无法固定取得数据。但是在特定的场景下也是可以使用的,比如做类似消息队列的场景


    随机拆分
  • 根据一致性hash拆分
    可以在客户端根据一致性hash算法(或者一系列映射算法)拆分数据,该算法讲node和data同时进行计算


    一致性hash拆分

一致性hash算法

将0 - 2^32个点散列在hash环上,将node和data使用相同的hash[映射]算法确定在各自的点位,使得读取该key的数据时,都在顺时针最近的node上进行


一致性hash

当加入其node时,也使用同样的算法加入hash环,这样可以很方便的分担其他节点的压力,也不会使数据重新洗牌,但是新增节点会使一小部分数据无法命中,造成缓存击穿,使得请求访问mysql,此时我们可以开启内存管理,淘汰原有的数据,将这些数据加入新的节点,但此时,Redis更倾向作为缓存,而不是数据库

  • 如果因hash算法导致数据倾斜如何处理?

Redis会加入虚拟节点,比如之前是对node的ip进行hash,现在我们可以使用ip+一些随机数进行hash,使得节点和虚拟节点分布在hash环上


一致性hash新加入node

使用Redis分片的架构设计

  • 客户端直连Redis
    Redis的连接成本很高,多个客户端集中访问redis会在服务端造成很大压力


    客户端直连Redis
  • 通过代理连接Redis
    此时需要关注代理性能


    通过代理连接Redis
  • 当代理性能不够时 - LVS + proxy集群
    LVS的相关知识可参阅之前的文章LVS负载均衡:https://www.jianshu.com/p/20b5dc39c564

LVS + proxy集群

关于代理的功能可以参阅twemproxy的功能文档(README):https://github.com/twitter/twemproxy

  • 以上3种分区模式的弊端:Redis无法作为数据库使用

如何解决这个问题。我们可以使用预分区的方式:
redis代理实现预分区:如下图,我们开始只有2台Redis,划分10个hash槽道,0-4的读取在redis01,5-9的读取在redis02,当新加入redis03时,我们可以把对应槽道的数据迁移入redis03中


预分区

那么Redis是如何实现的呢?
Redis自身实现:首先做预分片,然后把对应的槽道数据转移到新的分片,每台redis中保存了所有redis的mapping信息,当用户执行读写操作时,如果数据不在当前节点,则因为有所有redis的mapping,则可以让用户去对应的redis分片读取数据(没有主的概念)


redis实现sharding
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容