Redis在3.0版正式引入redis-cluster集群这个特性。Redis集群是一个提供在多个Redis间节点间共享数据的程序集。Redis集群是一个分布式(distributed)、容错(fault-tolerant)的Redis内存K/V服务,集群可以使用的功能是普通单机Redis所能使用的功能的一个子集(subset),比如Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误。还有比如set里的并集(unions)和交集(intersections)操作,就没有实现。通常来说,那些处理命令的节点获取不到键值的所有操作都不会被实现。在将来,用户或许可以通过使用MIGRATE COPY命令,在集群上用计算节点(Computation Nodes) 来执行多键值的只读操作, 但Redis集群本身不会执行复杂的多键值操作来把键值在节点间移来移去。Redis集群不像单机版本的Redis那样支持多个数据库,集群只有数据库0,而且也不支持SELECT命令。Redis集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。
Redis集群的优点:
无中心架构,分布式提供服务。数据按照slot存储分布在多个redis实例上。增加slave做standby数据副本,用于failover,使集群快速恢复。实现故障auto failover,节点之间通过gossip协议交换状态信息;投票机制完成slave到master角色的提升。支持在线增加或减少节点。降低硬件成本和运维成本,提高系统的扩展性和可用性。
Redis集群的缺点:
client实现复杂,驱动要求实现smart client,缓存slots mapping信息并及时更新。目前仅JedisCluster相对成熟,异常处理部分还不完善,比如常见的“max redirect exception”。客户端的不成熟,影响应用的稳定性,提高开发难度。节点会因为某些原因发生阻塞(阻塞时间大于clutser-node-timeout),被判断下线。这种failover是没有必要,sentinel也存在这种切换场景。
#hosts文件配置
cat >> /etc/hosts << EOF 192.168.5.65 redis65 192.168.5.66 redis65 EOF
一、搭建redis5.0集群
从redis 3.0之后版本支持redis-cluster集群,redis-4.0.0开始支持module,redis-5.0.0开始支持类似于kafka那样的消息队列,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。这样就可以很好的保证redis的高可用性,下面就来部署个Redis Cluster,在两台服务器上部署6个redis节点
IP和端口配置文件名
192.168.5.65:600165_6001/redis.conf
192.168.5.65:600265_6002/redis.conf
192.168.5.65:600365_6003/redis.conf
192.168.5.66:600166_6001/redis.conf
192.168.5.66:600266_6002/redis.conf
192.168.5.66:600366_6003/redis.conf
1、修改系统参数
#修改最大可打开文件数
cat >> /etc/security/limits.conf << EOF * soft nofile 102400 * hard nofile 102400 EOF
#TCP监听队列大小
echo "net.core.somaxconn = 32767" >> /etc/sysctl.conf sysctl -p
#OOM相关:vm.overcommit_memory
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf sysctl -p
#开启内核的“Transparent Huge Pages (THP)”特性
echo never > /sys/kernel/mm/transparent_hugepage/enabled
#请将“echo never > /sys/kernel/mm/transparent_hugepage/enabled”加入到文件/etc/rc.local中
2、安装redis并配置redis-cluster
[root@redis65 /]# cd /opt [root@redis65 /]# wget http://download.redis.io/releases/redis-5.0.0.tar.gz [root@redis65 /]# tar -zxvf redis-5.0.0.tar.gz [root@redis65 /]# cd redis-5.0.0/ [root@redis65 /]# make [root@redis65 /]# make install PREFIX=/usr/local/redis-cluster
#创建实例目录
[root@redis65 redis-5.0.0]# mkdir -p /usr/local/redis-cluster/{65_6001,65_6002,65_6003} [root@redis66 redis-5.0.0]# mkdir -p /usr/local/redis-cluster/{66_6001,66_6002,66_6003}
#配置官方配置文件,去掉#开头的和空格行
cat redis.conf |grep -v ^# |grep -v ^$
#redis65 6001配置文件
[root@redis65 /]#cd /usr/local/redis-cluster [root@redis65 redis-cluster]# cat >> 65_6001/redis.conf << EOF bind 0.0.0.0 protected-mode no port 6001 daemonize no dir /usr/local/redis-cluster/65_6001 cluster-enabled yes cluster-config-file /usr/local/redis-cluster/65_6001/nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes pidfile /usr/local/redis-cluster/65_6001/redis.pid logfile /usr/local/redis-cluster/65_6001/redis.log EOF
#redis65 6002配置文件
[root@redis65 redis-cluster]# sed 's/6001/6002/g' 65_6001/redis.conf > 65_6002/redis.conf
#redis65 6003配置文件
[root@redis65 redis-cluster]# sed 's/6001/6003/g' 65_6001/redis.conf > 65_6003/redis.conf
#写一个启动脚本start-redis-cluster.sh
[root@redis65 /]#cat /usr/local/redis-cluster/start-redis-cluster.sh
#!/bin/sh REDIS_HOME=/usr/local/redis-cluster $REDIS_HOME/bin/redis-server $REDIS_HOME/65_6001/redis.conf $REDIS_HOME/bin/redis-server $REDIS_HOME/65_6002/redis.conf $REDIS_HOME/bin/redis-server $REDIS_HOME/65_6003/redis.conf
chmod +x /usr/local/redis-cluster/start-redis-cluster.sh /usr/local/redis-cluster/start-redis-cluster.sh
#redis66 6001配置文件
[root@redis66 /]# cd /usr/local/redis-cluster [root@redis66 redis-cluster]# cat >> 66_6001/redis.conf << EOF bind 0.0.0.0 protected-mode no port 6001 daemonize no dir /usr/local/redis-cluster/66_6001 cluster-enabled yes cluster-config-file /usr/local/redis-cluster/66_6001/nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes pidfile /usr/local/redis-cluster/66_6001/redis.pid logfile /usr/local/redis-cluster/66_6001/redis.log EOF
#redis66 6002配置文件
[root@redis66 redis-cluster]# sed 's/6001/6002/g' 66_6001/redis.conf > 66_6002/redis.conf
#redis66 6003配置文件
[root@redis66 redis-cluster]# sed 's/6001/6003/g' 66_6001/redis.conf > 66_6003/redis.conf
[root@redis66 /]#cat /usr/local/redis-cluster/start-redis-cluster.sh
#!/bin/sh REDIS_HOME=/usr/local/redis-cluster $REDIS_HOME/bin/redis-server $REDIS_HOME/66_6001/redis.conf $REDIS_HOME/bin/redis-server $REDIS_HOME/66_6002/redis.conf $REDIS_HOME/bin/redis-server $REDIS_HOME/66_6003/redis.conf
chmod +x /usr/local/redis-cluster/start-redis-cluster.sh
#启动redis
/usr/local/redis-cluster/start-redis-cluster.sh
#查看redis进程启动状态
ps -ef | grep redis
#创建redis cluster,如果只是想快速创建和启动redis集群,可使用redis官方提供的脚本create-cluster,注意redis-5.0.0版本开始才支持“--cluster”
cd /usr/local/redis-cluster/bin ./redis-cli --cluster create 192.168.5.65:6001 192.168.5.65:6002 192.168.5.65:6003 192.168.5.66:6001 192.168.5.66:6002 192.168.5.66:6003 --cluster-replicas 1
如果配置项cluster-enabled的值不为yes,则执行时会报错“[ERR] Node 192.168.5.65:6001 is not configured as a cluster node.”。这个时候需要先将cluster-enabled的值改为yes,然后重启redis-server进程,之后才可以重新执行redis-cli创建集群。
redis-cli的参数说明:
1) create
表示创建一个redis集群。
2) --cluster-replicas 1
表示为集群中的每一个主节点指定一个从节点,即一比一的复制
#查看redis进程是否已切换为集群状态(cluster)
ps -ef|grep redis
#停止redis实例,直接使用kill命令即可
kill -9 15025
#命令行工具redis-cli
[root@redis65 /]# ln -s /usr/local/redis-cluster/bin/redis-cli /bin/redis-cli [root@redis65 bin]# redis-cli -c -p 6001
#查看集群中的节点:
127.0.0.1:6001> cluster nodes
127.0.0.1:6002> set name 65-7001 -> Redirected to slot [5798] located at 192.168.5.66:6001 OK 192.168.5.66:6001> quit [root@redis65 bin]# redis-cli -c -p 6003 127.0.0.1:6003> get name -> Redirected to slot [5798] located at 192.168.5.66:6001 "65-7001"
[root@redis65 bin]# redis-cli -h 192.168.5.66 -p 6002
#检查节点状态
[root@redis65 bin]# redis-cli --cluster check 192.168.5.66:6001
#查看集群信息
[root@redis65 bin]# redis-cli -c -p 6003 127.0.0.1:6003> cluster info
#给redis cluster集群加上认证,登录到redis节点执行下面的操作
[root@redis65 /]# redis-cli -h 192.168.5.65 -p 6001 -c > config set masterauth zxc789 > config set requirepass zxc789 > auth zxc789 > config rewrite
#各个节点都完成上面的3条config操作,重启redis各节点,看下各节点的redis.conf,可以发现最后多了3行内容
[root@redis65 /]# killall redis-server [root@redis65 /]# /usr/local/redis-cluster/start-redis-cluster.sh [root@redis66 ~]# cat /usr/local/redis-cluster/66_6001/redis.conf
#加了认证的redis登录
redis-cli -h 192.168.5.65 -p 6001 -c -a 'zxc789'
二、安装php的redis扩展
1、在现有的web服务器上安装php的redis扩展
[root@web33 ~]# cd /opt [root@web33 opt]# wget -c -t 0 https://github.com/owlient/phpredis/archive/master.zip [root@web33 opt]# unzip master.zip [root@web33 opt]# cd phpredis-master/ [root@web33 phpredis-master]# /usr/local/php/bin/phpize [root@web33 phpredis-master]# ./configure --with-php-config=/usr/local/php/bin/php-config [root@web33 phpredis-master]# make && make install
#这里进行make的时候报错
2、那是因为最新的 phpredis 分了几大分支,针对最新的PHP稳定发行版 php7 有专门为php7的分支,所以我们从github拉下phpredis 源码 需要切换到PHP7的分支 首先git clone phpredis下来
[root@web33 ~]# cd /opt [root@web33 ~]# git clone https://github.com/nicolasff/phpredis [root@web33 ~]# git checkout php7 [root@web33 opt]# cd phpredis [root@web33 phpredis]# /usr/local/php/bin/phpize [root@web33 phpredis]# ./configure --with-php-config=/usr/local/php/bin/php-config [root@web33 phpredis]# make && make install
3、修改php.ini加上“extension=redis.so”
vi /usr/local/php/etc/php.ini extension = "redis.so"
4、重启php-fpm
/etc/init.d/php-fpm restart
#用phpinfo验证下redis扩展是否安装成功
5、单实例redis通过php连接测试
connect('192.168.5.65', 6001); $redis->auth('zxc789'); //redis认证 echo "Connection to server sucessfully"; //查看服务是否运行 echo "Server is running: " . $redis->ping(); ?>
#执行脚本,输出结果为:
Connection to server sucessfully
Server is running: PONG
6、Java操作Redis cluster集群可使用jredis,PHP要操作redis cluster集群有两种方式:
1)使用phpredis扩展,这是个c扩展,性能更高,但是这个方案参考资料很少
2)使用predis,纯php开发,使用了命名空间,需要php5.3+,灵活性高,我这里用的是predis,下载地址https://github.com/nrk/predis
[root@web33 tmp]# git clone https://github.com/nrk/predis.git #将predis放到网站根目录下 [root@web33 tmp]# mv predis /data/www/predis [root@web33 tmp]# cd /data/www/
[root@web33 www]# cat predis.php
'redis','parameters' => [ 'password' => 'zxc789' ]]; $client = new Predis\Client($servers,$options); $client->set('name1', '1111111'); $client->set('name2', '2222222'); $client->set('name3', '3333333'); $name1 = $client->get('name1'); $name2 = $client->get('name2'); $name3 = $client->get('name3'); var_dump($name1, $name2, $name3);die; ?>