Redis:管道技术、分区

来自Wikioe
跳到导航 跳到搜索


管道技术

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:

  1. 客户端向服务端发送一个查询请求,并监听 Socket 返回,通常是以“阻塞”模式,等待服务端响应。
  2. 服务端处理命令,并将结果返回给客户端。

但,Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应


示例,通过使用 PING 命令查看redis服务是否可用,之后设置了 runoobkey 的值为 redis,然后获取 runoobkey 的值并使得 visitor 自增 3 次:

$(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379

+PONG
+OK
redis
:1
:2
:3

在返回的结果中我们可以看到这些命令一次性向 redis 服务提交,并最终一次性读取所有服务端的响应


综上所述,pipeline 就是把一组命令进行打包,然后一次性通过网络发送到 Redis,同时将执行的结果批量的返回回来。通过管道技术能够减少的I/O的调用次数。


管道技术最显著的优势是提高了 redis 服务的性能。

测试:
require 'rubygems' 
require 'redis'
def bench(descr) 
start = Time.now 
yield 
puts "#{descr} #{Time.now-start} seconds" 
end
def without_pipelining 
r = Redis.new 
10000.times { 
    r.ping 
} 
end
def with_pipelining 
r = Redis.new 
r.pipelined { 
    10000.times { 
        r.ping 
    } 
} 
end
bench("without pipelining") { 
    without_pipelining 
} 
bench("with pipelining") { 
    with_pipelining 
}
without pipelining 1.185238 seconds 
with pipelining 0.250783 seconds

如上,开启管道后,速度效率提升了5倍。

分区

分区就是分割数据到多个Redis实例,每个实例只保存key的一个子集


优点:

  • 通过利用多台计算机内存的和值,允许我们构造更大的数据库
  • 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。

缺点:

  • 涉及多个 key 的操作通常不被支持
    比如,当两个set映射到不同的redis实例上时,不能对这两个set执行交集操作。
  • 涉及多个 key 的 redis 事务不能使用
  • 数据处理较为复杂
    比如,需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
  • 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。然而,一种叫做presharding的技术对此是有帮助的。

分区类型

Redis 有两种类型分区。

假设有 4 个 Redis 实例 R0,R1,R2,R3,和类似 user:1,user:2 这样的表示用户的多个 key,对既定的 key 有多种不同方式来选择这个 key 存放在哪个实例中。

也就是说,有不同的系统来映射某个 key 到某个 Redis 服务。

范围分区

最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的 Redis 实例。

比如,ID 从 0 到 10000 的用户会保存到实例 R0,ID 从 10001 到 20000 的用户会保存到 R1,以此类推。
  • 这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表
  • 这个表要被管理,同时还需要各种对象的映射表,通常对 Redis 来说并非是好的方法。

哈希分区

另外一种分区方法是 hash 分区。


这对任何key都适用,也无需是 object_name: 这种形式,像下面描述的一样简单:

  1. 用一个 hash 函数将 key 转换为一个数字。
    比如使用 crc32 hash函数。对 key “foobar”执行“crc32(foobar)”会输出类似 93024922 的整数。
  2. 对这个整数取模,将其转化为 0-3 之间的数字,就可以将这个整数映射到 4 个 Redis 实例中的一个了。
    93024922 % 4 = 2,就是说 key “foobar”应该被存到 R2 实例中。