26.分区技术

  • Redis 分区技术(又称 Redis Partition)指的是将 Redis 中的数据进行拆分,然后把拆分后的数据分散到多个不同的 Redis 实例(即服务器)中,每个实例仅存储数据集的某一部分(一个子集),我们把这个过程称之为 Redis 分区操作。

Redis 实例指的是一台安装了 Redis 服务器的计算机。

  • 分区(Partition)不仅是 Redis 中的概念,几乎所有数据库管理系统都会涉及到“分区”的应用。
26.1 分区的优点
  • Redis 分区技术有两个方面的优势,一是提升服务器的性能,二是提高了服务器的数据存储能力。
  • 一方面,单台机器的 Redis 服务器,其网络 IO 能力和计算资源都是非常有限的,但是如果我们将请求分散到多台机器上,那么就能充分利用多台计算机的算力和网络带宽,从而整体上提升 Redis 服务器的性能。另一方面,随着存储数据的不断增加,单台机器的存储容量会达到极限,若将数据分散存储到多台 Redis 服务器上,其存储能力也将得到大幅度提升。

注意,Redis 分区技术可以利用多台计算机的内存总和,从而创建出大型的 Redis 数据库。

26.2 分区常用方法
  • 分区技术有两种常用方法,分别是“范围分区”和“哈希分区”。
26.2.1 范围分区
  • 范围分区是最简单、最有效的分区方法之一。所谓范围分区指的是将特定范围的 key 映射到指定的 Redis 实例上。key 的命名格式如下:
object_name:<id>
  • 比如:user:1、user:2 …用来表示不同 id 的用户。下面通过一个示例了解范围分区的具体流程:
  • 假设现在共有 3000 个用户,可以把 id 从 0 到 1000 的用户映射到实例 R0 上,id 从 1001 到 2000 的用户映射到实例 R1 上,以此类推,将 id 从 2001 到 3000 的用户映射到实例 R2 上。
  • 范围分区不仅简单,而且实用,适合许多的特定场景。但当存储的 key 不能按照范围划分时,那么范围分区就不再适用了,比如 key 是一组 uuid(通用唯一识别码)。如下所示:
9eb4d81b-31ec-4c69-a721-c7e1771413dd
  • 此时范围分区就不再适用,就要用到另外一种分区方式——哈希分区。
26.2.2 哈希分区
  • 哈希分区与范围分区相比,它最显著的优势是适合任何形式的 key。哈希分区方法并不复杂,id 表达式如下所示:
id=hash(key)%N
  • 这里的 id 指的是 Redis 实例的编号,而 N 表示共有多少个 Redis 实例。首先调用一个 crc32() 哈希函数,它可以将 key 转换为一个整数。 如下所示:
crc32(key)
  • 假如转换后的整数是 93024922,此时共有 4 个 Redis 实例,对整数与实例的数量进行取模运算,就会得到一个 0 到 3 之间的整数,如下所示:
93024922 % 4 = 2
  • 上述计算结果为 2 ,我们就把这个 key 映射到 R2 实例中,如果为 3 就映射到 R3实例中。以此类推,通过这种方式可以将所有的 key 分散到 4 个不同的 Redis 实例中。
26.7 分区技术的不足和解决
  • 虽然 Redis 分区技术有诸多优势,但是它也存在一些不足之处。下面做简单介绍:
  • 涉及操作多个 key 时,通常不被支持。这是由于批量操作的 key 会被映射到不同的 Redis 实例中,此时无法实现在一个实例中操作分散开的 key;
  • 不支持包含多个 key 的 Redis 事务;
  • 当使用分区的时候,数据的处理变的非常复杂,比如需要处理多个 .rdb 或者 .aof 存储文件,并且还需要从多个 Redis 实例中备份数据;
  • 添加、删除实例变的复杂,比如 Redis 集群支持在运行时增加或减少实例,分区技术不支持这种功能。
  • 我们知道,应用 Redis 分区技术时存在一些不足之处,比如在增加、删除 Redis 实例时会非常麻烦,但这种情况在实际应用中经常遇到。比如今天需要删除 10 台 Redis 实例,明天又要增加 20 台实例。那么对于这种问题,有没有一种较好的解决办法呢?下面进行简单介绍:
  • 其实 Redis 是一种很轻量级的服务(每个实例仅占用 1 MB),针对它的这种特性,我们提出以下解决办法:
  • 在一台机器上开启多个 Redis 实例,可以从中选择一定数量的实例作为 Redis 工作集群。当集群中某一台机器存储不足时,可以将一部分 Redis 实例移动到另外一台机器上,依次类推。这样就保证了 Redis 的实例总数不变,又达到了增加机器的目的。

27.Pipeline管道技术

  • Redis 服务器是以单线程的方式来处理客户端的网络 IO 请求的。如果每执行一次请求都要创建和断开一次连接,就会消耗过多的时间,导致执行效率降低。因此 Redis 提供了 Pipeline(管道技术),使用该技术可以一次性向服务器发送多条命令,并返回多个执行结果。这样就节省了发送命令和创建连接的时间,从而提高了执行效率。

需要在 Liunx 系统上使用 Pipeline 管道技术。

27.1 Pipeline的作用
  • Redis 是使用了客户端-服务器(C/S)模型和请求/响应协议的 TCP 服务器。这意味着发送一个请求会遵循以下步骤:
  • 客户端通常以阻塞的方式向服务器发送命令,以获取服务器的响应。
  • 服务器接收并处理命令,然后将响应发送回客户端。

阻塞式,指的是只有当客户端接收完当前命令的响应信息,服务端才可以继续处理下一条指令,即一条一条的逐次执行。

  • 不管命令是以数据包的形式从客户端传输到服务端,还是客户端获得服务端的响应信息,这个过程都需要花费一定的时间,我把这个时间称为“往返延时”。因此当客户端执行一串请求的时候很容易看出延时对其性能造成的影响。
  • 如果我们可以减少网络请求的次数,那么就可以大幅度提高 Redis 应用性能。Redis 的 Pipeline 就是这样一种技术,它能够把多次网络请求打包成一次请求发送给服务端,从而减少多次请求的“往返时间”。

注意,记住“速度不够,管道来凑”,能够帮助理解管道技术的作用。

27.2 执行Pipeline语句
  • Pipeline 技术有其固定的语法格式,以下是在 Linux 终端非redis客户端执行的语句,具体命令如下:
(echo -en "auth xxxx\r\n ping\r\n set name zs\r\n get name\r\n incr num\r\n decr num\r\n incr num\r\n"; sleep 3)|nc localhost 6379
  • 上述语句,首先使用 PING 命令检查 Redis 是否正常工作,然后又分别使用了 SET/GET/INCR 命令,以及 sleep 阻塞 3 秒,最后将这些命令一次性的提交给 Redis 服务器,Redis 服务器在阻塞了3 秒之后,一次性输出了所有命令的响应信息。

注意: 每个命令字符串必须以 \r\n 结尾。至于语句最后的 nc localhost 6379 是固定格式无需更改。

  • 客户端一次性接收到所有命令的执行结果,如下所示
remote:0>(echo -en "auth xxxx\r\n ping\r\n set name zs\r\n get name\r\n incr num\r\n decr num\r\n incr num\r\n"; sleep 3)|nc localhost 6379

+OK
+PONG
+OK
$2
zs
:1
:0
:1

注意:上述示例需要在 Linux 系统终端执行,Windows 由于缺少nc命令,无法执行成功。