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

官方教程原地址:

http://redis.io/topics/cluster-tutorial

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

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

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

*Redis集群101

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

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

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

所以在实际应用上,Redis集群可提供:

@自动分割数据集合在多个节点上;

@当某个节点挂掉或者不可访问时,集群继续正确地提供服务.

*Redis集群TCP端口

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

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

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

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

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

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

*Redis集群数据分片

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

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

集群中的每个节点覆盖hashslot的一部分,比如一个集群有3个节点,则:

@节点A覆盖0到5500;

@节点B覆盖5501到11000;

@节点C覆盖11001到16384.

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

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

*Redis集群主从模式

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

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

如果在集群建立的时候(或者建完后),我们为每个主节点都添加了从节点,比如像这样,集群包含主节点ABC,以及从节点A1B1C1,那么即使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实例,最简单的配置文件包含以下几项:

port7000

cluster-enabledyes

cluster-config-filenodes.conf

cluster-node-timeout5000

appendonlyyes

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

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

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

命令如下:

mkdircluster-test

cdcluster-test

mkdir700070017002700370047005

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

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

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

cd7000

../redis-server./redis.conf

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

[82462]26Nov11:56:55.329*Noclusterconfigurationfound,I'm97a3a64667477371c4479320d683e4c8db5858b1

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

*创建集群

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

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

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

./redis-trib.rbcreate--replicas1127.0.0.1:7000127.0.0.1:7001\

127.0.0.1:7002127.0.0.1:7003127.0.0.1:7004127.0.0.1:7005

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

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

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

[OK]All16384slotscovered

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

*使用集群

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

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

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

@redis-py-cluster,

@流行的Predis支持Redis集群,这功能刚被开发.

@Java使用最多的Jedis最近开始支持Redis集群,请查看JedisCluster的README.

@redis-cli工具实现了一个基本的集群支持,启动时加上-c参数.

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

$redis-cli-c-p7000

redis127.0.0.1:7000>setfoobar

->Redirectedtoslot[12182]locatedat127.0.0.1:7002

OK

redis127.0.0.1:7002>sethelloworld

->Redirectedtoslot[866]locatedat127.0.0.1:7000

OK

redis127.0.0.1:7000>getfoo

->Redirectedtoslot[12182]locatedat127.0.0.1:7002

"bar"

redis127.0.0.1:7000>gethello

->Redirectedtoslot[866]locatedat127.0.0.1:7000

"world"

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

*使用redis-rb-cluster写一个示例程序

(待续)

相关推荐