第九章 切片集群:数据增多了,是该加内存还是加实例 ?
如何保存更多数据 ?
redis应对数据量增多的两种方案:纵向扩展 和 横向扩展,那什么是纵向扩展,什么是横向扩展呢 ?
- 纵向扩展:扩展硬件配置的深度,能容纳更多数据
- 横向扩展:扩展redis的广度,能分摊更多数据
纵向扩展 和 横向扩展 的优缺点是什么呢 ?
- 纵向 优点:扩展使用简单
- 缺点:受硬件和成本限制,大小受限。持久化时会比较长阻塞主线程,影响性能
- 横向 优点:不受硬件限制,大小几乎无限。不影响性能
- 缺点:复杂度增加
数据切片和实例的对应分布关系
数据切片后,在多个实例之间如何分布 ?
切片集群是一种通用机制,而 Redis Cluster 是切片集群的落地实现。
什么是 哈希槽(Hash Slot) ?
- Redis Cluster 方案采用哈希槽来处理数据和实例之间的映射关系。
- 在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。
- 数据分片和实例的对应关系建立:按照 CRC16 算法计算一个key的16bit的值,在将这值对 16384 取模
哈希槽 和 哈希表 有什么区别呢 ?
- 哈希槽 是用于映射key与不同实例的关系。然后应该是在每一个实例中,有自己的全局哈希表。
- 即:先通过key映射到对应的slot,然后在对应的实例中通过全局哈希表查找key对应的value。
16384个哈希槽怎么分布到多个实例中呢 ?
- 使用
cluster create
创建集群可以平均把哈希槽平均分到各个集群实例上,每个实例的哈希槽个数是 16384/N 个 - 也可以使用
cluster addslots
根据不同实例的性能自定义不同实例哈希槽的个数- 在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作。
数据、哈希槽、实例三者的映射关系图
客户端如何定位数据 ?
客户端怎么确定想要访问的数据在哪个实例上 ?
- Redis 会把自己的哈希槽信息发给和它相连接的其它实例,这样每一个实例就都能知道所有哈希槽的映射关系了。
- 客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端。
- 客户端知道哈希槽的分布之后,会缓存一份到本地。
- 当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。
集群的实例增减,或者是为了实现负载均衡而进行的数据重新分布,会导致哈希槽和实例的映射关系发生变化,客户端发送请求时,会收到命令执行报错信息。
- Redis Cluster 方案提供了一种重定向机制。
- 重定向机制:客户端访问的实例没有数据,被访问实例响应move命令,告诉客户端指向新的实例地址
MOVED 命令 和 ASK 命令 的区别 ?
- move命令是在数据迁移完毕后被响应,客户端会更新本地缓存。
- ASK命令是在数据迁移中被响应,不会让客户端更新缓存。
- 表明数据正在迁移
- 告知客户端数据所在的实例
- 客户端MOVED重定向命令
- 客户端ASK重定向命令
Redis Cluster 不采用直接将key映射到实例,而采用哈希槽的方式原因是什么 ?
不使用哈希槽的劣势:
- 集群中的key无法预估,直接存key对应实例的映射关系,需占用的内存空间不可控
- Cluster是去中心化设计,所有实例都需保存完整的映射关系,采用直接的映射,会导致节点间信息交换成本高昂
- key与实例直接映射,在集群扩缩容时,需要数据迁移,所有的key都需要重新映射
使用哈希槽的好处:
- 在中间增加一层哈希槽,可以将数据与节点解耦,使数据分配均匀。
- key通过hsah计算再取模,可以把数据打的更散,只需要关心映射到了哪个哈希槽,通过哈希槽映射表找到对应的实例
- 增加哈希槽可以使得映射表比较小,有利于客户端和服务端保存,节点间信息交换
- 集群扩缩容,数据均衡时,操作单位是哈希槽,可以简化操作难度