Redis7-集群数据容量

主从复制解决HA问题,未解决容量有限问题

容量的问题

AKF 的 y轴 做纵向业务拆分,这样把存储的数据,在客户端层面就决定好每个redis存储一部分的数据。

如果数据可以分类,交集不多,可以考虑按业务拆分

Redis7-集群数据容量

如果数据量很大,光拆分了业务之后,还是每个业务拥有大量数据,数据没有办法划分拆解

采用sharding分片

  1. Hash+取模

分布式系统中,假设有 n 个节点,传统方案使用 mod(key, n) 映射数据和节点。

Redis7-集群数据容量

当扩容或缩容时(哪怕只是增减1个节点),映射关系变为 mod(key, n+1) / mod(key, n-1),绝大多数数据的映射关系都会失效。这种哈希取模的方式,会影响分布式系统的扩展性

  1. random随机分配节点

一端随机往 redis 中不断存储数据,另一端随机从 redis 中取数据,这样就不用太在意数据被存到了哪,只要最终被消费掉即可。

Redis7-集群数据容量

  1. 一致性哈希算法

    一致性哈希算法中,当节点个数变动时,映射关系失效的对象非常少,迁移成本也非常小。

Redis7-集群数据容量

https://baike.baidu.com/item/一致性哈希/2460889?fr=aladdin

https://www.cnblogs.com/lpfuture/p/5796398.html

Redis7-集群数据容量

物理节点:两个redis的物理节点。

虚拟结点:通过多个哈希函数,得到多个结果值,将一个节点,分布在环的多个位置上,两个物理节点可以映射环上多个位置,这样解决了数据倾斜的问题。

成本问题

redis 结点可能只有那么几个,但是连接 redis 的客户端数量非常多。

往往客户端会有一个连接池,一个客户端就建立了很多很多连接导致redis连接对server端的成本很高。

Redis7-集群数据容量

解决方式

增加一个接入层,类似于nginx反向代理,只负责接收来自客户端的请求,把它代理到后端的服务器上。

这样,redis 服务端的连接压力就减轻了,我们就只需要关注代理层的性能。

Redis7-集群数据容量

代理层的性能

可以对代理层再做一次集群,其中的每一部分客户端都只连接一个代理。代理层适应例如modula,random,kemata算法映射redis物理节点。

代理层 Nginx 都扛不住怎么办

可以再统一接入一个负载均衡 LVS。LVS做一个主备,主备之间通过keepalived,除了监控两个LVS的健康状态之外,也监控proxy的健康状态。

Redis7-集群数据容量

这样,无论后端的技术有多么复杂,对于客户端来说都是透明的,因此,客户端的 API 就可以极其简单。

https://github.com/twitter/twemproxy

同时不要因为技术而技术。redis连多线程都没有使用,它并不希望redis被引入那么多的功能。上面3个模式不能做数据库用。

数据预分区

分区时动态扩容或缩容可能非常复杂。Redis集群在运行时增加或者删除Redis节点,能做到最大程度对用户透明地数据再平衡,但其他一些客户端分区或者代理分区方法则不支持这种特性。然而,有一种预分片的技术也可以较好的解决这个问题。

一般情况下随着时间的推移,数据存储需求总会发生变化。今天可能两个Redis节点就够了,但是明天可能就需要增加到10个节点。

开始要取模的话就是 %2,未来很多次扩容到10个,可以一开始一次性取模%10

中间加一层 mapping,当两个节点时,让其中 0-4 这5份数据存到 1 结点,然后让 5-9 这部分数据,存到 2 结点。

Redis7-集群数据容量

扩容到第三个结点的时候,把 1 号的 3、4 槽位以及数据分给它,把 2 号的 8、9 槽位和数据分给它,这样,就可以继续保持每个节点,持有固定槽位的数据,而不会产生数据丢失。

Redis7-集群数据容量

与上面三种分片方式区别

对于之前的哈希取模,或者还是一致性哈希环,它们在新增结点的时候,都需要对数据进行重哈希,重新定位新的数据应存储在哪个结点。

数据迁移会不会有什么问题?

在数据传输的过程中,是先 RDB 把该传的数据全部传过去,由于服务不能停止中断,AOF 传输少量变化的数据。

redis 集群 无主模型

  • 查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的redis节点。

例如,客户端去redis3上找k1,redis2说,你应该去redis3找。于是客户端就去redis3上取k1(每个redis节点知道其他redis持有的分区信息)

分区的缺点

  • 涉及多个key的操作通常不会被支持。例如你不能对两个集合求交集,因为他们可能被存储到不同的Redis实例(实际上这种情况也有办法,但是不能直接使用交集指令)。
  • 同时操作多个key,则不能使用Redis事务.

解决方法

因为数据一但被分开,就很难再被合并处理;如果数据不被分开,那就可以进行事务。

可以由人去实现:hash tag 例如我们将带有相同前缀的key放在一个节点上,对前缀key取模

Twemproxy

Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis或memcached服务器,再原路返回。

https://github.com/twitter/twemproxy

Redis7-集群数据容量

Predixy

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

https://github.com/joyieldInc/predixy/blob/master/README_CN.md

Redis7-集群数据容量

上一篇:Java描述 LeetCode,剑指 Offer 56 - II. 数组中数字出现的次数 II


下一篇:c++类访问权限及友元