分片(partitioning)就是将你的数据拆分到多个 Redis 实例的过程,这样每个实例将只包含所有键的子集.

1 分片何用

Redis 的分片承担着两个主要目标:

  • 允许使用很多电脑的内存总和来支持更大的数据库。没有分片,你就被局限于单机能支持的内存容量。
  • 允许伸缩计算能力到多核或多服务器,伸缩网络带宽到多服务器或多网络适配器。

2 分片基础

有很多不同的分片标准(criteria).
假想我们有 4 个 Redis 实例 R0,R1,R2,R3,还有很多表示用户的键,像 user:1,user:2,… 等等,我们能找到不同的方式来选择一个指定的键存储在哪个实例中。换句话说,有许多不同的办法来映射一个键到一个指定的 Redis 服务器。

最简单的执行分片的方式之一是范围分片(range partitioning),通过映射对象的范围到指定的 Redis 实例来完成分片。例如,我可以假设用户从 ID 0 到 ID 10000 进入实例 R0,用户从 ID 10001 到 ID 20000 进入实例 R1.

这套办法行得通,并且事实上在实践中被采用,然而,这有一个缺点,就是需要一个映射范围到实例的表格.
这张表需要管理,不同类型的对象都需要一个表,所以范围分片在 Redis 中常常并不可取,因为这要比其他分片可选方案低效得多。

一种范围分片的替代方案是哈希分片(hash partitioning).
这种模式适用于任何键,不需要键像 object_name: 这样的饿形式,就像这样简单

  • 使用一个哈希函数(例如,crc32 哈希函数) 将键名转换为一个数字。例如,如果键是 foobar,crc32(foobar)将会输出类似于 93024922 的东西。
  • 对这个数据进行取模运算,以将其转换为一个 0 到 3 之间的数字,这样这个数字就可以映射到我的 4 台 Redis 实例之一。93024922 模 4 等于 2,所以我知道我的键 foobar 应当存储到 R2 实例。注意:取模操作返回除法操作的余数,在许多编程语言总实现为%操作符。

有许多其他的方式可以分片,从这两个例子中你就可以知道了。一种哈希分片的高级形式称为一致性哈希(consistent hashing),被一些 Redis 客户端和代理实现。

3 分片实现(理论)

分片可由软件栈中的不同部分来承担。

  • 客户端分片(Client side partitioning)
    客户端直接选择正确的节点来写入和读取指定键,许多 Redis 客户端实现了客户端分片.
  • 代理协助分片(Proxy assisted partitioning)
    我们的客户端发送请求到一个可以理解 Redis 协议的代理上.而不是直接发送请求到 Redis 实例上.

代理会根据配置好的分片模式,来保证转发我们的请求到正确的 Redis 实例,并返回响应给客户端.
Redis 和 Memcached 的代理 Twemproxy 实现了代理协助的分片.

  • 查询路由(Query routing)
    你可以发送你的查询到一个随机实例,这个实例会保证转发你的查询到正确的节点.

Redis 集群在客户端的帮助下,实现了查询路由的一种混合形式 (请求不是直接从 Redis 实例转发到另一个,而是客户端收到重定向到正确的节点).

4 分片缺点

Redis 的一些特性与分片在一起时玩的不是很好

  • 涉及多个键的操作通常不支持。例如,你不能对映射在两个不同 Redis 实例上的键执行交集(事实上有办法做到,但不是直接这么干).
  • 涉及多个键的事务不能使用
  • 分片的粒度(granularity)是键,所以不能使用一个很大的键来分片数据集,例如一个很大的有序集合
  • 当使用了分片,数据处理变得更复杂,例如,你需要处理多个 RDB/AOF 文件,备份数据时你需要聚合多个实例和主机的持久化文件
  • 添加和删除容量也很复杂。例如,Redis 集群具有运行时动态添加和删除节点的能力来支持透明地再均衡数据,但是其他方式,像客户端分片和代理都不支持这个特性。但是,有一种称为预分片(Presharding)的技术在这一点上能帮上忙。

5 存储 OR 缓存

尽管无论是将 Redis 作为数据存储还是缓存,Redis 的分片概念上都是一样的,但是作为数据存储时有一个重要的局限。当 Redis 作为数据存储时,一个给定的键总是映射到相同的 Redis 实例。当 Redis 作为缓存时,如果一个节点不可用而使用另一个节点,这并不是一个什么大问题,按照我们的愿望来改变键和实例的映射来改进系统的可用性(就是系统回复我们查询的能力)。

一致性哈希实现常常能够在指定键的首选节点不可用时切换到其他节点。类似的,如果你添加一个新节点,部分数据就会开始被存储到这个新节点上。

这里的主要概念如下:

  • 如果 Redis 用作缓存,使用一致性哈希来来实现伸缩扩展(scaling up and down)是很容易的。
  • 如果 Redis 用作存储,使用固定的键到节点的映射,所以节点的数量必须固定不能改变。否则,当增删节点时,就需要一个支持再平衡节点间键的系统,当前只有 Redis 集群可以做到这一点.

6 预分片

我们已经知道分片存在的一个问题,除非我们使用 Redis 作为缓存,增加和删除节点是一件很棘手的事情,使用固定的键和实例映射要简单得多。

然而,数据存储的需求可能一直在变化。今天我可以接受 10 个 Redis 节点(实例),但是明天我可能就需要 50 个节点。

因为 Redis 只有相当少的内存占用且轻量级(一个空闲的实例只是用 1MB 内存),一个简单的解决办法是一开始就开启很多的实例。即使你一开始只有一台服务器,你也可以在第一天就决定生活在分布式的世界里,使用分片来运行多个 Redis 实例在一台服务器上。

你一开始就可以选择很多数量的实例。例如,32 或者 64 个实例能满足大多数的用户,并且为未来的增长提供足够的空间。

这样,当你的数据存储需要增长,你需要更多的 Redis 服务器,你要做的就是简单地将实例从一台服务器移动到另外一台。当你新添加了第一台服务器,你就需要把一半的 Redis 实例从第一台服务器搬到第二台,如此等等。

使用 Redis 复制,你就可以在很小或者根本不需要停机时间内完成移动数据:

  • 在你的新服务器上启动一个空实例。
  • 移动数据,配置新实例为源实例的从服务。
  • 停止你的客户端。
  • 更新被移动实例的服务器 IP 地址配置。
  • 向新服务器上的从节点发送 SLAVEOF NO ONE 命令。
  • 以新的更新配置启动你的客户端。
  • 最后关闭掉旧服务器上不再使用的实例。

7 分片实现(实践)

到目前为止,我们从理论上讨论了 Redis 分片,但是实践情况如何呢?你应该使用什么系统呢?

7.1 Redis 集群

Redis 集群是自动分片和高可用的首选方式.

一旦 Redis 集群可用,以及支持 Redis 集群的客户端可用,Redis 集群将会成为 Redis 分片的事实标准。

Redis 集群是查询路由和客户端分片的混合模式。

7.2 Twemproxy

Twemproxy 是 Twitter 开发的一个支持 Memcached ASCII 和 Redis 协议的代理。它是单线程的,由 C 语言编写,运行非常的快。基于 Apache 2.0 许可的开源项目。

Twemproxy 支持自动在多个 Redis 实例间分片,如果节点不可用时,还有可选的节点排除支持(这会改变键和实例的映射,所以你应该只在将 Redis 作为缓存是才使用这个特性)。

这并不是单点故障(single point of failure),因为你可以启动多个代理,并且让你的客户端连接到第一个接受连接的代理。

从根本上说,Twemproxy 是介于客户端和 Redis 实例之间的中间层,这就可以在最下的额外复杂性下可靠地处理我们的分片。这是当前建议的处理 Redis 分片的方式.

7.3 支持一致性哈希的客户端

Twemproxy 之外的可选方案,是使用实现了客户端分片的客户端,通过一致性哈希或者别的类似算法。有多个支持一致性哈希的 Redis 客户端,例如 Redis-rb 和 Predis。

请查看完整的 Redis 客户端列表,看看是不是有支持你的编程语言的,并实现了一致性哈希的成熟客户端。

联系我

gayhub

Redis分片(分布式缓存)相关推荐

  1. Redis 实现分布式缓存

    缓存 1. 什么是缓存? 缓存就是数据交换的缓冲区,用于临时存储数据(使用频繁的数据).当用户请求数据时,首先在缓存中寻找,如果找到了则直接返回.如果找不到,则去数据库中查找 缓存的本质就是用空间换时 ...

  2. Redis实现分布式缓存

    分布式缓存 在分布式缓存中常常使用redis的技术实现方案. 单节点redis存在的问题及解决方案 数据丢失问题 解决方案:实现redis持久化 并发能力问题 解决方案:搭建主从集群,实现读写分离 故 ...

  3. 用REDIS实现分布式缓存

    2019独角兽企业重金招聘Python工程师标准>>> 第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的 ...

  4. 使用Ehcache+Redis实现分布式缓存

    Redis和Ehcache缓存的区别 如果是单个应用或者对缓存访问要求很高的应用,用ehcache. 如果是大型系统,存在缓存共享.分布式部署.缓存内容很大的,建议用redis. 实际工作中使用Ehc ...

  5. mybatis+redis实现分布式缓存+缓存面试题

    一,mybatis缓存机制 mybatis提供了一级.二级缓存. 一级缓存:线程级别的缓存,也称为本地缓存或sqlSession级别的缓存,一级缓存是默认存在的,同一个会话中,查询两次相同的操作就会从 ...

  6. Redis实现 分布式缓存、分布式锁

    缓存逻辑 代码实例 堆外内存溢出 springboot2.0以后默认使用lettuce作为操作rendis的客户端,在高并发下回产生"堆外内存溢出",可以通过切换使用jedis. ...

  7. 高性能分布式缓存Redis(缓存分类 安装 数据类型选择和应用场景 发布订阅 事务 Lua脚本 慢查询日志)

    高性能分布式缓存Redis 高性能分布式缓存Redis 1. 缓存发展史&缓存分类 1.1 大型网站中缓存的使用 1.2 常见缓存的分类 1.3 分布式缓存选型方案对比 2. Redis概述& ...

  8. redis 分布式缓存 详解

    1.Redis概述 1.1.NoSQL NoSQL(Not Only SQL),意即不仅仅是SQL, 泛指非关系型的数据库. 1.2.Redis安装 首先需要从Redis官网上下载Redis的源码包, ...

  9. Redis应用场景以及分布式缓存的实现

    1. Redis应用场景 利用 redis 中字符串类型完成 项目中手机验证码存储的实现 验证码一般都具有时效性,我们在redis中可以设置一个key的超时时间, 当用户在超时时间之内响应时,会与re ...

最新文章

  1. java制表位是什么意思_java制表位如何应用?大神进来。
  2. 87.VGA 88.FPGA
  3. ABAP 实现新会话新窗口方法
  4. PL/SQL在win7/win8 x64位下使用客户端连接oracle
  5. poj 1149 PIGS【最大流】
  6. Office远程代码执行漏洞补丁(905413)
  7. 微软自带iscsi客户端对iqn的要求
  8. 十一、网络编程。TCP\UDP\socket
  9. matlab实现2dpsk调制与解调,(完整版)matlab设计2DPSK信号调制与解调
  10. 记账系统推荐金蝶精斗云_金蝶精斗云好用的免费的财务做账软件有哪些?
  11. OOK电路在电调天线远端控制器(RCU)中的应用
  12. 电路设计软件系列教程(五),Protel DXP电路设计软件之设计规则(上)
  13. 潇洒郎: 解决EDAS论文上传文字没有嵌入问题:Upload failed: The font Arial,Italic is not embedded in the file.
  14. 阿里云视频点播服务的开通和使用
  15. wps-excel的自动分页符(虚线)怎么去掉
  16. 渗透中常用的在线工具和网站总结
  17. 第四天--外边距塌陷
  18. 玩qq游戏提示计算机内存不足,为什么电脑运行游戏后提示内存不足
  19. matlab中s_cplot,matlab系统模型建立和动态特性研究分析实验.docx
  20. Qt - QRegExp 正则表达式

热门文章

  1. Modbus TCP报文结构
  2. 韩顺平QQ多用户聊天系统-离线消息发送
  3. 开发者工具F12指南
  4. mysql索引innodb和myisam的区别
  5. mysql myisam 行锁_MySQL MYISAM引擎表锁和行锁详解
  6. The Sound Of Silence
  7. 解决remote: [session-e84096af] xmonster: Incorrect username or password (access token) fatal
  8. I^2RNet: Intra- and Inter-Human Relation Network for Multi-Person Pose Estimation 笔记
  9. Kubernetes网络原理
  10. 你想学的都在这里!大佬手把手教你如何仿写出大厂的APP,Android面试题及解析