一、序言
之前文章 http://blog.youkuaiyun.com/strburnchang/article/details/78634226 介绍了redis单机版服务搭建过程。
这次是来学习集群版redis搭建及其使用。因硬件条件限制,仅在一台服务器做demo
二、Redis单机版搭建过程
三、Redis集群版搭建过程。
1、Redis集群架构图,
架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
注:
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
2、集群搭建
集群中应该至少有三个节点,每个节点有一备份节点。需要6台服务器。搭建伪分布式,需要6个redis实例。
(因环境限制,仅是在同一台服务器上使用6个不同端口启动redis个实例,3个作为主节点,3个作为备用节点)
(1)搭建步骤
A、创建6个redis实例并指定端口(7001-7006)
在redis目录下创建 redis-cluster目录
cd /usr/local/redis/;mkdir redis-cluster
将redis源码复制6份放到redis-cluster目录下
B、修改redis配置文件(六个都需要改)
vi ./redis01/etc/redis.conf
将cluster-enable yes注释打开
然后修改对应端口 port 7001(其他依次为 7002 ...)
C、安装ruby环境(因为集群运行需要一个ruby脚本)
1、yum install ruby
2、安装redis集群需要的包
gem install redis -v 3.3.3
[root@localhost /usr/local/redis]#gem install redis -v 3.3.3
Fetching: redis-3.3.3.gem (100%)
Successfully installed redis-3.3.3
Parsing documentation for redis-3.3.3
Installing ri documentation for redis-3.3.3
1 gem installed
D、写一个shell脚本用来启动redis集群所有服务
vim start-all.sh
#!/bin/bash
clusterpath="/usr/local/redis/redis-cluster/"
cd $clusterpath
redis_arr=(01 02 03 04 05 06)
for num in ${redis_arr[@]}
do
echo "start ${num}nth redis server..."
cd redis${num}/bin/
redis-server ../etc/redis.conf
cd ..
cd ..
done
chmod +x start-all.sh
启动所有rediss实例
./start-all.sh
E、使用redis-trib.rb创建集群
命令
./redis-trib.rb create --replicas 1 192.168.1.102:7001 192.168.1.102:7002 192.168.1.102:7003 192.168.1.102:7004 192.168.1.102:7005 192.168.1.102:7006
发现这个命令会出错。说我没有权限。然后给前面加了ruby 表明是ruby脚本。
ruby ./redis-trib.rb create --replicas 1 192.168.1.102:7001 192.168.1.102:7002 192.168.1.102:7003 192.168.1.102:7004 192.168.1.102:7005 192.168.1.102:7006
这个也出错,说不能连接到7001节点。百度了下,是因为redis配置文件中已经打开了认证功能(密码),所以挨着关闭了。
更改配置文件之后,再重新启动节点
./start-all.sh
ruby ./redis-trib.rb create --replicas 1 192.168.1.102:7001 192.168.1.102:7002 192.168.1.102:7003 192.168.1.102:7004 192.168.1.102:7005 192.168.1.102:7006
成功
F、创建cluster过程可能会遇到一些问题:
参考:http://www.2bowl.info/centos7%E4%B8%8A%E6%90%AD%E5%BB%BAredis-cluster/
1)、>>> Creating cluster
[ERR] Node 192.168.1.102:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解决方法:
删除每个节点下的dump.rdb文件
或挨个进行flushdb
redis-cli -h 192.168.1.102 -p 6390
flushdb
2)、/usr/local/share/gems/gems/redis-3.3.3/lib/redis/client.rb:121:in call': ERR Slot 741 is already busy (Redis::CommandError)
block in method_missing’
from /usr/local/share/gems/gems/redis-3.3.3/lib/redis.rb:2705:in
from /usr/local/share/gems/gems/redis-3.3.3/lib/redis.rb:58:in block in synchronize'
mon_synchronize’
from /usr/share/ruby/monitor.rb:211:in
from /usr/local/share/gems/gems/redis-3.3.3/lib/redis.rb:58:in synchronize'
method_missing’
from /usr/local/share/gems/gems/redis-3.3.3/lib/redis.rb:2704:in
from ./redis-trib.rb:212:in flush_node_config'
block in flush_nodes_config’
from ./redis-trib.rb:776:in
from ./redis-trib.rb:775:in each'
flush_nodes_config’
from ./redis-trib.rb:775:in
from ./redis-trib.rb:1296:in create_cluster_cmd'
from ./redis-trib.rb:1701:in
解决方法: 由于上一次的配置不正确导致的,重新删除节点中node.conf文件,重启节点即可
四、使用redis的java客户端jedis
1、添加maven依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2、创建测试类
package com.gs.redis;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.HashSet;
import java.util.Set;
public class TestRedis {
private final String REDIS_HOST = "192.168.1.102";
@Test
public void testJedisCluster() throws Exception {
//创建一个JedisCluster对象
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort(REDIS_HOST, 7001));
nodes.add(new HostAndPort(REDIS_HOST, 7002));
nodes.add(new HostAndPort(REDIS_HOST, 7003));
nodes.add(new HostAndPort(REDIS_HOST, 7004));
nodes.add(new HostAndPort(REDIS_HOST, 7005));
nodes.add(new HostAndPort(REDIS_HOST, 7006));
//在nodes中指定每个节点的地址
//jedisCluster在系统中是单例的。
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("name", "zhangsan");
jedisCluster.set("value", "100");
String name = jedisCluster.get("name");
String value = jedisCluster.get("value");
System.out.println(name);
System.out.println(value);
//系统关闭时关闭jedisCluster
jedisCluster.close();
}
}
到此,redis集群搭建完成。后面会再记录redis整合spring(单机版和集群版本)