Redis Partitioning
这是Redis官方文档Partitioning的翻译和摘录
分区:如何在多个Redis实例上拆分数据
分区是将数据拆分到多个Redis实例的过程,目的是让每一个实例只包含用户的键的子集。
本文档第一部分讲述分区的概念,第二部分介绍Redis分区的不同方式。
为什么分区有用
Redis分区又两个目标:
- 利用分区可以使用多台机器的内存,这样就可以支持较大的数据库。
如果没有分区,数据库大小将受限于单台机器内存。 - 分区可以利用多核、多台机器实现计算能力、网络带宽扩展
分区基础
根据方式不同,键可能按照下面的方式来选择对应的实例来存储
- 范围分区
例如[0, 1000]到一个实例,[1001,2000]到另一个实例
缺点:- 需要维护一张范围到实例的映射表
- 每一种对象都需要一个表
(这个没明白什么意思)
- 散列分区
对于任意键都有效,不要求键是 object_name:形式
具体形式:- 用散列函数将键名处理为一个数
- 对上一步得到的数求余(模为实例总数)
- 其他方法
一致性哈希:散列分区的一种高级形式
分区的不同实现
- 客户端分区
客户端直接根据键选择对应的节点进行读写 - 代理辅助分区
在客户端和Reids之间加入了一个中间层,负责转发客户端请求和反馈响应给客户端 - 请求路由(Query Routing)
客户但可以给任意实例发请求,收到请求的实例确保请求将被转发到正确的节点上。
Redis Cluster借助客户端实现了一个混合型是的请求路由:- 请求不是直接由一个实例转发到另一个实例,而是将客户端重定向到正确的节点
- 形式上类似于HTTP的3xx重定向
分区的缺点
Redis的某些特性不能很好地配合分区
- 无法进行设计多个键的操作
- 不能使用设计多个键的事务
- 因为分区的粒度是键,故而不能对一个巨型键的数据集进行分片,比如一个大的有序集
(没太明白)
- 数据处理会更复杂,比如需要处理多个RDB/AOF文件,备份数据时需要从多个实例或机器上收集合并持久化文件
- 扩容与减少容量会更复杂。Redis Cluster可以在运行时添加和删除节点,从而可以支持大多数情况下的透明数据均衡。然而客户端分区和代理方式不支持这种特性,预分片技术可以用于解决这个问题
数据存储还是缓存?
虽然不管Redis是用作数据存储或用作缓存,Redis分区的在概念上都是一样的,但在用作数据存储的情况还是有一个重要限制,即每一个键必须永远对应同一个实例。
如果一个键对应的节点不可用,通常情况下一致性哈希实现可以切换到到其他节点上。类似地,如果添加了新节点,一部分新添加的键会开始被新节点存储。
有两个主要概念:
- 如果Redis被用作缓存,使用一致性哈希来扩容和缩小是很容易的
- 如果Redis被用作存储,那就需要一个固定的键-节点映射表,节点的数目必须固定且不可能变化。否则,就需要一个额外的系统,这个系统负责在节点添加或删除时对键进行重新均衡,目前只有Redis Cluster可以做到(从2015.04.01开始,Redis Cluster production-ready)
预分片
这一节是描述对于Redis用作存储情况下,怎样进行手动扩容
Reids作为存储时,添加和删除节点会不那么容易,但如果使用固定键-实例映射,则相对容易。
Redis开销极小,一个实例只会用到1MB内存,一个解决扩容问题的简单方法是在一开始就启动大量实例。即使开始只有一台服务器,我们也可以从第一天就构建分布式系统,在一台机器上运行多个Redis实例,并且使用分区。
可以一开始就选择使用32个或者64个实例。
通过这种方式,只需要简单地迁移实例到其他机器上就可以实现扩容。例如增加一台机器后,可以将一半的实例迁移到新机器上,以此类推。
使用Redis复制,可使上文提到的迁移过程只涉及极小的停机时间,甚至没有。过程如下:
- 在新机器上启动新的空实例集
- 将新实例集配置为原实例集的slave,迁移数据
- 停止客户端
- 将迁移后的实例配置为新机器的IP
- 在新机器上发送SLAVEOF NO ONE命令给所有slaves
- 使用新配置重启所有客户端
- 关闭旧机器上不再使用的实例
Reids分区实现
Redis Cluster
推荐的实现自动分片与高可用途径
Twemproxy
- 在Twitter开发的一个代理
- 可用于Memcached ASCII和Redis协议
- 单线程
- C语言写的
- 极快
- 开源 Apache2.0
它不会造成单点故障,因为可以开启多个代理,客户端可以由第一个接受连接的代理提供服务
简单地说,Twemproxy为客户端和Redis实例之间添加了一个中间层,它可以为我们提供可靠的分片,但同时增加一些微小的额外复杂性。
支持一致性哈希的客户端
可以通过实现客户端分区来替代Twemproxy,这需要在客户端使用一致性哈希或类似算法。有很多客户端实现已经支持了一致性哈希,比如Redis-rb和Predis