首页 > 代码库 > redis-cluster的安装管理

redis-cluster的安装管理

redis-cluster的安装管理

 

声明:

本文只允许用于个人学习交流使用,如有错误之处请多多指正。

文档版本:Version 1.0

修改记录:2015-10-30


环境介绍

系统环境:RedHat Enterprise Linux Server release 6.2 (Santiago)

内核版本:Linuxzxt-02.com 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64x86_64 x86_64 GNU/Linux

软件版本:redis-3.0.5

主机名:redis-01.comredis-02.com

主机IP192.168.1.193 192.168.1.176

安装所需软件环境:

Zlibruby(必须1.9.2以上)、rubygemgem-redis

注:在阅读文本文档之前需要读者知道的是本文档以及目前网络上的大部分相近的文档都来源于http://redis.io。如果您的英文阅读能较好的话建议您阅读Reis官方文档。http://redis.io/topics/cluster-spec

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

redis-cluster简介:

Redis 集群是一个可以在多个Redis节点之间进行数据共享的设施(installation)。Redis 集群不支持那些需要同时处理多个键的Redis 命令,因为执行这些命令需要在多个Redis 节点之间移动数据,并且在高负载的情况下,这些命令将降低Redis 集群的性能,并导致不可预测的行为。

Redis 集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。

Redis集群提供了以下两个好处:

将数据自动切分(split)到多个节点的能力。

当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力

Redis 集群的数据分片

Redis 集群没有使用一致性hash,而是引入了哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash,举个例子,比如当前集群有3个节点,那么:

  • 节点 A 包含 0 5500号哈希槽

  • 节点 B 包含5501 11000 号哈希槽.

  • 节点 C 包含11001 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D,我需要从节点 A, B, C中得部分槽到D. 如果我像移除节点A,需要将A中得槽移到BC节点上,然后将没有任何槽的A节点从集群中移除即可.

由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

Redis 集群的主从复制模型

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

在我们例子中具有ABC三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.

然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1B1C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了

不过当BB1 都失败后,集群是不可用的.

Redis 一致性保证

Redis 并不能保证数据的强一致性.这意味这在实际中集群在特定的条件下可能会丢失写操作.

第一个原因是因为集群是用了异步复制. 写操作过程:

    客户端向主节点B写入一条命令.

    主节点B向客户端回复命令状态.

    主节点将写操作复制给他得从节点 B1,B2 B3.

 

主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。

 

注意:Redis 集群可能会在将来提供同步写的方法。

Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。.

 

举个例子 假设集群包含 A B C A1 B1 C1 六个节点, 其中 A B C 为主节点, A1 B1 C1 ABC的从节点, 还有一个客户端 Z1

 

假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A C A1 B1 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .

 

Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.

 

注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), Redis 集群的一个重要的配置选项:

部署环境

redis-cluster要求最少需要3个节点,由于测试环境我这里使用两台虚拟机安装多个节点来模拟redis集群。

主机节点分配:

node1    192.168.1.193:6379

node2    192.168.1.193:6479

node3    192.168.1.193:6579

备机节点:

node1    192.168.1.176:6379

node2    192.168.1.176:6479

node3    192.168.1.176:6579     

安装redis cluste及依赖软件:

1)   安装zlib软件;

Zlib软件可以根据心情选择yum安装或者编译安装

Yum安装

[zxt@redis-01 ~]$ yum install -y zlib*
[zxt@redis-01 ~]$ rpm -qa |grep zlib 
zlib-1.2.3-27.el6.x86_64
zlib-devel-1.2.3-27.el6.x86_64


 编译安装:

#download:  http://www.zlib.net/
tar zxf  zlib-1.2.7.tar.gz
cd zlib 
./configure  
make  
make install


2)   安装ruby: version(1.9.2)

想要运行Redis cluter必须安装ruby并需安装1.9.2及以上版本。此处不要使用yum安装,因为RedHat6.2系统yum安装默认版本为1.8.7

#ruby-2.1.7.tar.gz  
tar   zxvf  ruby-2.1.7.tar.gz
cd  ruby-2.1.7
./configure -prefix=/usr/local/ruby  
make  
make install  
cp ruby /usr/local/bin


3)   安装rubygem:version(1.8.5)

# rubygems-1.8.5.tgz  
tar zxvf  rubygems-1.8.5.tgz
cd rubygems-1.8.5
ruby setup.rb  
cp bin/gem /usr/local/bin

4)   安装gem-redis:version(3.0.5)

安装运行redis集群所必需的redisruby的接口。

gem install redis --version 3.0.5

 

#由于某些原因,gem源不能访问或者可能下载失败可能下载失败,以下提供两种解决方案:

法一:手动下载下来安装 

#download地址:
http://rubygems.org/gems/redis/versions/3.0.0  
gem install -l /soft/redis-3.0.5.gem


法二:更换gem 源

gem sources --removehttps://rubygems.org/
gem sources -ahttp://ruby.sdutlinux.org/
gem sources -l
*** CURRENT SOURCES***
https://ruby.taobao.org

常用的源

http://rubygems.org/
http://gems.github.com
http://gems.rubyforge.org
http://ruby.sdutlinux.org/
  #国内应该找个比较靠谱了,适合安装大多数常见的gem

5)   安装redis

tar xzfredis-3.0.5.tar.gz
cp  -r redis-3.0.5  /opt/app/
ln -s /opt/app/redis-3.0.5/   /opt/redis
cd  /opt/redis
make test
make
make install

说明:

make install命令执行完成后,会在/usr/local/bin目录下生成本个可执行文件,分别是redis-serverredis-cliredis-benchmarkredis-check-aof redis-check-dump,它们的作用如下:

redis-serverRedis服务器的daemon启动程序

redis-cliRedis命令行操作工具。也可以用telnet根据其纯文本协议来操作

redis-benchmarkRedis性能测试工具,测试Redis在当前系统下的读写性能

redis-check-aof:数据修复

redis-check-dump:检查导出工具

配置redis cluster

1)配置集群初始化脚本:

cd /opt/redis 
cp/opt/redis/src/redis-trib.rb /usr/local/bin

2)配置redis cluster配置文件

daemonize yes
#以后台进程redis运行.
pidfile/opt/redis/run/redis_6379.pid
#若以后台进程运行Reids,则需指定pid文件及路径.
port 6379
#指定redis监听端口.
tcp-backlog 511
#在高并发的环境中,为避免客户端的连接缓慢问题.
bind 0.0.0.0
#绑定主机IP.(这里设置为4个0可以方便程序调用).
timeout 0
#客户端连接时的超时时间,单位为秒.
tcp-keepalive 60
#在 Linux 上,指定值(秒)用于发送 ACKs 的时间,注意关闭连接需要双倍的时间.默认为 0
loglevel notice
#日志记录等级,有4个可选值,debug,verbose(默认值),notice,warning
logfile"/var/log/redis/redis_6379.log"
#log 文件地址
databases 16
#可用数据库数
save 900 1
save 300 10
save 60 10000
#根据给定的时间间隔和写入次数将数据保存到磁盘,单位为秒
stop-writes-on-bgsave-erroryes
#后台存储错误停止写。
rdbcompression yes
#存储至本地数据库时(持久化到dump.rdb文件)是否压缩数据,默认为 yes
rdbchecksum yes
#是否校验rdb文件.
dbfilenamedump_6379.rdb
#本地持久化数据库文件名,默认值为 dump.rdb
dir /opt/redis/data
#数据库镜像备份的文件放置的路径。
#slaveof<masterip> <masterport>
#设置该数据库为其他数据库的从数据库时启用该参数。
#masterauth<master-password>
#slave服务连接master的密码
slave-serve-stale-datayes
slave-read-only yes
#slave只读
repl-diskless-syncno
repl-diskless-sync-delay5
repl-disable-tcp-nodelayno
slave-priority 100
#requirepassfoobared
#设置客户端连接密码
appendonly yes
#打开aof持久化 
appendfilename"appendonly_6379.aof"
#aof文件名,默认为appendonly.aof
appendfsync everysec
#每秒一次aof写
no-appendfsync-on-rewriteyes
#关闭在aof rewrite的时候对新的写操作进行fsync 
auto-aof-rewrite-percentage100
#部署在同一机器的redis实例,把auto-aof-rewrite搓开,因为cluster环境下内存占用基本一致. 
#防止同一机器下瞬间fork所有redis进程做aof rewrite,占用大量内存(ps:cluster必须开启aof)
auto-aof-rewrite-min-size64mb
aof-load-truncatedyes
lua-time-limit 5000
cluster-enabled yes
#打开redis集群
cluster-config-filenodes-6379.conf
#集群节点配置文件(启动自动生成)
cluster-node-timeout15000
#节点互连超时的阀值 
cluster-migration-barrier1
slowlog-log-slower-than10000
slowlog-max-len 128
latency-monitor-threshold0
notify-keyspace-events""
hash-max-ziplist-entries512
hash-max-ziplist-value64
list-max-ziplist-entries512
list-max-ziplist-value64
set-max-intset-entries512
zset-max-ziplist-entries128
zset-max-ziplist-value64
hll-sparse-max-bytes3000
activerehashing yes
client-output-buffer-limitnormal 0 0 0
client-output-buffer-limitslave 256mb 64mb 60
client-output-buffer-limitpubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsyncyes

注意:其他节点只需要复制配置文件将所有端口号更改即可。

rediscluster运维操作

1、分别启动这6redis实例节点

192.1.168.1.193
cd  /opt/redis
redis-serverredis_6379.conf
redis-serverredis_6479.conf
redis-serverredis_6579.conf
192.1.168.1.193
cd  /opt/redis
redis-serverredis_6379.conf
redis-serverredis_6479.conf
redis-serverredis_6579.conf

启动之后使用netstat –lntp 命令查看端口是否监听,如图所示则启动正常。

技术分享


2、使用自带的redis-trib.rb构建集群

redis-trib.rb create--replicas 1 192.168.1.193:6379 192.168.1.193:6479
192.168.1.193:6579 192.168.1.176:6379192.168.1.193:6479 192.168.1.193:6579

注:

#redis-trib.rbcreate子命令构建

#--replicas则指定了为Redis Cluster中的每个Master节点配备几个Slave节点 

#节点角色由顺序决定,master之后是slave(为方便辨认,slave的端口比master1000)

3、检查集群状态

#redis-trib.rbcheck子命令

#ip:port可以是集群的任意节点 

redis-trib.rb check 192.168.1.193:6379

最后输出如下信息,没有任何警告或错误(如图),表示集群启动成功并处于ok状态

技术分享

4、添加新master节点

创建一个空节点(empty node),然后将某些哈希插槽移动到这个空节点上。

a)、创建新节点配置文件:

为了方便区分我这里再开启一台虚拟机增加一对节点:

192.168.1.187:6379

192.168.1.187:6479

cd /opt/redis
scp redis_6379.conf 192.168.1.187:/opt/redis/
cp redis_6379.conf   redis_6479.conf
sed –ie  s/6379/6479/g  redis_6479.conf


b)、启动新节点:

      

 redis-server redis_6379.conf

c)、将新节点加入集群:

redis-trib.rbadd-node 192.168.1.187:6379 192.168.1.193:6379

 

add-node  将一个节点添加到集群里面,第一个是新节点ip:port, 第二个是任意一个已存在节点ip:port

注意:在添加新节点时,新节点中不能包含任何数据,否则会添加失败。

技术分享

技术分享

因为它没有包含任何哈希插槽。新加入的加点是一个主节点,当集群需要将某个从节点升级为新的主节点时,这个新节点不会被选中,同时新的主节点因为没有包含任何哈希插槽,不参加选举和failover

d)、手动为新节点添加哈希插槽:

  

redis-trib.rb reshard 192.168.1.187:6379

#根据提示选择要迁移的哈希插槽数量 

How many slots do you want to move (from 1 to 16384)? 1000 

技术分享

#选择要接受这些哈希插槽的node-id 

What is the receiving node ID? 36c46361327dbb15d098a0c3794ac3d72869e508

技术分享

#选择哈希插槽来源

#all表示从所有的master重新分配, 

#或者数据要提取哈希插槽的master节点id,最后用done结束 

 Please enter all the source node IDs. 

  Type ‘all‘ to use all the nodes as sourcenodes for the hash slots. 

  Type ‘done‘ once you entered all thesource nodes IDs. 

Source node #1:all 

技术分享

    #打印被移动的哈希插槽后,输入yes开始移动哈希插槽以及对应的数据

#Do you want to proceed with the proposed reshard plan (yes/no)?yes 

技术分享

#结束 

可以使用命令查看对比哈希槽的分配情况(如图)

redis-trib.rbcheck 192.168.1.176:6379

技术分享

至此,一个新的主节点就添加完成了,执行命令查看现在的集群中节点的状态

redis-trib.rbcheck 192.168.1.176:6379
redis-cli-c -p 6379 cluster nodes

5、添加新slave节点

a):前三步操作同添加master一样

注意:新添加的节点群集默认分配为master但是节点没有分配任何插槽(如图)

技术分享

b)第四步:redis-cli连接上新节点shell,输入命令:clusterreplicate 对应masternode-id(这里我们输入节点192.168.1.187:6379id)。

redis-cli  -h 192.168.1.187 -p 6479
clusterreplicate 36c46361327dbb15d098a0c3794ac3d72869e508 
exit

技术分享

也可通过查看集群状态确定是否添加成功

技术分享

注意:在线添加slave 时,需要bgsave整个master数据,并传递到slave,再由 slave加载rdb文件到内存,rdb生成和传输的过程中消耗Master大量内存和网络IO,以此不建议单实例内存过大,线上小心操作。

5、删除一个slave节点

法一:  

#redis-tribdel-node ip:port ‘<node-id>‘ 
redis-trib.rbdel-node  192.168.1.187:6479  4655fccff00ef4a7b99c10ffd590c8328ec6db8d

技术分享

法二:直接停止或kill 节点即可

Redis-cli–p 6479 shutdown
or
kill-9  `cat /opt/redis/run/redis_6479.pid`

6、删除一个master节点

a):删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点

#192.168.1.187:6379当前master迁移到192.168.1.176:6579

redis-trib.rbreshard 192.168.1.176:6579

#根据提示选择要迁移的哈希插槽数量 

How manyslots do you want to move (from 1 to 16384)? 1000

(被删除master的所有哈希插槽数量

#选择要接受这些哈希插槽的192.168.1.176:6579

What isthe receiving node ID? e1c06dd4682a37eb6773d6cb1d5709034a3f2769(ps: 192.168.1.176:6579node-id) 

Pleaseenter all the source node IDs. 

Type‘all‘ to use all the nodes as source nodes for the hash slots. 

Type‘done‘ once you entered all the source nodes IDs. 

Sourcenode #36c46361327dbb15d098a0c3794ac3d72869e508 (被删除masternode-id) 

Sourcenode #2:done 

技术分享

#打印被移动的哈希插槽后,输入yes开始移动哈希插槽以及对应的数据

#Do youwant to proceed with the proposed reshard plan (yes/no)? yes 

技术分享

 

b):删除空master节点

redis-trib.rbdel-node  192.168.1.187:6379 ‘36c46361327dbb15d098a0c3794ac3d72869e508‘

三、redis cluste常用命令

1、查看集群状态

redis-trib.rbcheck 127.0.0.1:6379


2、查看集群信息

redis-cli-c –p 6379 cluster nodes

3、查看集群主从情况

redis-cli-c -p 6379 info Replication

4、查看集群信息

redis-cli-c –p 6379 cluster info

附录一:redis集群常用命令系统管理相关指令简介

集群 

CLUSTER INFO 打印集群的信息 

CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。 

节点 

CLUSTER MEET <ip> <port> ip port 所指定的节点添加到集群当中,让它成为集群的一份子。 

CLUSTER FORGET <node_id> 从集群中移除node_id 指定的节点。 

CLUSTER REPLICATE <node_id> 将当前节点设置为node_id 指定的节点的从节点。 

CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。 

(slot) 

CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。 

CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。 

CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。 

CLUSTER SETSLOT <slot> NODE<node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。 

CLUSTER SETSLOT <slot> MIGRATING<node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。 

CLUSTER SETSLOT <slot> IMPORTING<node_id> node_id 指定的节点中导入槽 slot 到本节点。 

CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。 

 

CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。 

CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。 

CLUSTER GETKEYSINSLOT <slot><count> 返回 count slot 槽中的键。

参考资料与扩展知识:

http://hot66hot.iteye.com/blog/2050676/

Redis指令大全:

http://redis.io/commands

一个redis爱好者创建的相关问题讨论网站:

http://www.rediscookbook.org/

 

为什么使用 Redis及其产品定位:

http://www.infoq.com/cn/articles/tq-why-choose-redis

 

Redis内存使用优化与存储:

http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage

 

redis-cluster的安装管理