Redis cluster tutorial Redis集群教程 官方教程 翻译 (一)


官方教程原地址:
http://redis.io/topics/cluster-tutorial


这篇文档是一个总体介绍, 不使用复杂的分布式概念. 本文介绍如何建立一个集群, 测试和使用, 详细说明请参看 Redis Cluster specification

注意, 如果你打算实际使用Redis集群, 推荐看正式的规范文档.

Redis集群现在还在alpha测试, 请加入Redis邮件列表, 或Github repository的讨论组.

*Redis集群 101

Redis集群实现了数据自动分片于多个节点.

Redis集群不支持处理多个key, 因为这可能需要在多个节点间移动数据, 这样会使得性能下降.

Redis集群拥有一定程度的可用性, 当一个节点挂掉或者不可访问时, 集群可继续提供正确的服务.

所以在实际应用上, Redis集群可提供:
@自动分割数据集合在多个节点上;
@当某个节点挂掉或者不可访问时, 集群继续正确地提供服务.

*Redis集群TCP端口
每个节点需要使用两个TCP端口. 一个普通端口给客户端使用, 比如6379, 另外个则在这个数字上加1000, 本例中也就是16379.

后者这个高位端口是作为集群总线用的, 是节点对节点的二进制数据通信频道. 集群总线用作节点间的宕机侦测, 配置变更, 故障转移认证等等. 客户端应该不使用集群总线端口, 而应该使用那个普通端口. 确保这两个端口都没被防火墙禁掉, 否则Redis集群会工作不正常.

普通端口和集群总线端口之间的差值固定是1000.

要使集群工作正常, 注意以下两点:

1. 普通端口(通常为6379)要对所有需要连接的客户端开放, 也要对其他节点开放, 为了key的迁移.

2. 集群总线端口(普通端口+1000)必须对其他节点开放.

*Redis集群数据分片

Redis集群没使用一致性哈希, 而用的是不同的分片方式, 每个key都是hash slot的逻辑组成部分.

Redis集群有16384个hash slot, 计算一个给定key的hash slot, 则是把该key的CRC16值对16384取模.

集群中的每个节点覆盖hash slot的一部分, 比如一个集群有3个节点, 则:
@节点A覆盖0到5500;
@节点B覆盖5501到11000;
@节点C覆盖11001到16384.

这样使得添加和删除节点很容易. 比如我想添加一个新节点D, 则只要把一些hash slot从ABC挪到D. 类似的, 我想移除节点A, 我只要把A下的slot hash移到B和C, 当节点A空了我就可以把A完全移除掉了.

因为移动hash solt不需要停止节点的运行, 所以添加删除节点, 或者改变节点持有的hash slot百分比, 都不会有什么宕机时间.

*Redis集群主从模式

当一个节点挂掉或者不可访问时, 为了保证可用性, Redis集群使用了主从模式, 一个主节点对应一个或多个从节点.

上面那个例子里, 集群有ABC三个节点, 如果B挂掉了, 我们就没法访问5501到11000的hash slot了.

如果在集群建立的时候(或者建完后), 我们为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A B C, 以及从节点A1 B1 C1, 那么即使B挂掉系统也可以继续正确工作.

B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。

不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了。

*Redis集群一致性保证

Redis集群无法保证强一致性。实际情况下这意味着,某些情况下Redis集群有可能会忘记一个已被系统接受的写操作。

Redis集群会丢失写操作的一个原因是它使用异步复制. 这表示写操作包含以下几个步骤:
@客户端写数据到主节点B.
@主节点B回复客户端OK.
@主节点B传播本次写操作给它的从节点B1,B2和B3.

你可以发现, 节点B并没有在回复客户端之前等待B1,B2和B3的接受, 因为这将会造成很大的延迟. 所以当客户端写入数据到B中, B接受了数据, 但是在传播给它的从节点之前就挂了, 那么被提升为主节点的某个从节点将会永久丢失这个写操作.

这很类似于数据库每时每刻刷新配置到磁盘, 所以这种情况你应该已经了解, 因为传统数据库系统并不涉及分布式. 同样的, 为了提高一致性, 你可以在回复客户端之前强制刷新数据到磁盘, 但是这通常会降低性能.

基本上, 在一致性和性能之间, 都需要权衡一下.

注意: Redis集群会在将来允许用户配置同步写操作, 如果确实需要的话.

*创建和使用Redis集群

首先我们需要几个运行在集群模式下的Redis实例, 最简单的配置文件包含以下几项:

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

可以看到启用集群主要依靠cluster-enabled配置项. 每个Redis实例都包含一个文件, 默认为nodes.conf. 这个文件用户不用管, 它是在Redis集群每个实例启动的时候自动生成的, 以及在需要的时候自动更新的.

注意, 最小的Redis集群需要包含至少3个主节点. 头次试验, 强烈建议创建6个节点, 3个主节点, 3个从节点.

如下步骤实现以上操作: 进入一个新目录, 然后创建以Redis实例端口号命名的目录, 用以运行每一个Redis实例.

命令如下:

mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005

每个目录中都创建一个redis.conf文件. 注意修改文件中的端口号.

现在把redis-server的可执行文件复制到cluster-test目录, 然后打开6个shell终端.

启动每个实例, 命令如下:

cd 7000
../redis-server ./redis.conf

你可以从每个实例的日志中看到, 由于一开始没 nodes.conf 文件, 所以每个节点分配了一个新ID.

[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1

以后每个实例就一直用自己头一次生成的ID了, 每个节点都是通过ID来记住其他节点, 而不是IP或端口号. IP地址和端口号会改变, 但是ID是唯一的,不变的. 这个叫做 Node ID.

*创建集群

现在我们有了一些Redis实例在运行了, 我们需要创建我们的Redis集群, 通过对节点写入配置项来实现.

这很容易搞定, 因为有个叫 redis-trib 的Redis集群命令行工具来帮忙, 它是个Ruby程序, 用来在Redis实例中执行特殊命令, 比如创建一个集群, 修改已存在的集群等等.

redis-trib 工具在Redis的src目录中. 以下命令用以创建Redis集群:

./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

因为我们要新建集群, 所以这里使用create命令. --replicas 1 参数表示为每个主节点创建一个从节点. 其他参数是实例的地址集合.

很明显, 我们的需求只是设置一个拥有3个主节点,3个从节点的集群.

Redis-trib会提示你做了什么配置, 输入yes接受. 集群就被配置和加入了, 意思是, 实例会经过互相交流后启动. 一切都OK的话最终你会看到个信息类似于:

[OK] All 16384 slots covered

这表示至少一个主节点覆盖到了全部16384个slot.

*使用集群

此时Redis集群的一个问题是客户端库的缺乏.

我知道的有以下几个客户端库实现:

@redis-rb-cluster, 我(@antirez)用Ruby写的, 作为一个其他语言的参考. 它是原始redis-rb的简单包装, 实现使用集群的最小功能.

@redis-py-cluster,
@流行的Predis支持Redis集群, 这功能刚被开发.
@Java使用最多的Jedis最近开始支持Redis集群, 请查看Jedis Cluster的README.
@redis-cli工具实现了一个基本的集群支持, 启动时加上-c参数.

使用redis-cli方式, 举个例子:

$ redis-cli -c -p 7000
redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
redis 127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
redis 127.0.0.1:7000> get foo
-> Redirected to slot [12182] located at 127.0.0.1:7002
"bar"
redis 127.0.0.1:7000> get hello
-> Redirected to slot [866] located at 127.0.0.1:7000
"world"

redis-cli仅支持最基础的功能, 所以它一般只用来测试集群节点是否被正确地导向. 一个严谨的客户端能更好地实现此功能, 还能缓存hash slots和节点地址的映射, 能把连接正确地导向到节点. 这个映射只会在集群配置有变动时刷新, 比如某节点挂掉, 或者管理员添加删除了节点.

*使用redis-rb-cluster写一个示例程序
(待续)

猜你喜欢

转载自kennykinte.iteye.com/blog/2116416