前期准备
-
centos 7 系统
-
docker
-
拉取镜像并且改名
docker pull registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5
docker tag registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5 redis:v5
哨兵模式和集群模式的区别
- 哨兵模式监控权交给了哨兵系统,集群模式中是工作节点自己做监控
- 哨兵模式发起选举是选举一个leader哨兵节点来处理故障转移,集群模式是在从节点中选举一个新的主节点,来处理故障的转移
通俗点讲,就是存储方式不一样。哨兵模式就相当于mysql的主从备份,而集群模式就相当于mysql的分库分表。集群模式下每一个Put的值都会进行hash值计算,然后落在16384个hash槽的其中一个上面。
单机模式
- 拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5
docker tag registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5 redis:v5
- 有配置
docker run -d \
--restart=always \
--name redis \
-v /home/redis/redis.conf:/usr/local/redis/redis.conf \
-v /data:/data \
-p 6379:6379 \
redis:v5 redis-server /usr/local/redis/redis.conf
- 无配置
docker run -d \
--restart=always \
--name redis \
-v /home/redis/redis.conf:/usr/local/redis/redis.conf \
-v /data:/data \
-p 6379:6379 \
redis:v5 --requirepass admin@123
主从模式
主从模式:redis的主从模式,使用异步复制,slave节点异步从master节点复制数据,master节点提供读写服务,slave节点只提供读服务(这个是默认配置,可以通过修改配置文件 slave-read-only 控制)。master节点可以有多个从节点。配置一个slave节点只需要在redis.conf文件中指定 slaveof master-ip master-port 即可。
本示例:一个master节点有两个slave节点
- 创建主从模式文件夹
mkdir /home/redis-master && cd /home/redis-master
- 创建需要的节点配置文件
for node in `seq 6380 6382`;do \
mkdir $node \
&& mkdir /home/redis-master/$node/data \
&& echo "port $node" > /home/redis-master/$node/redis.conf ; \
done
主节点配置文件vim redis.conf.conf
port 6380
从节点配置文件vim redis.conf
,根据端口号不同修改,因为是docker环境,其他配置暂不需要
for node in `seq 6381 6382`;do \
echo "slaveof 192.168.66.168 6380" >> /home/redis-master/$node/redis.conf; \
done
- 启动三台服务
for node in `seq 6380 6382`;do \
docker run -d \
--restart=always \
--name redis-$node \
-v /home/redis-master/$node/redis.conf:/usr/local/redis/redis.conf \
-v /home/redis-master/$node/data:/data \
-p $node:$node \
redis:v5 redis-server /usr/local/redis/redis.conf ;\
done
哨兵模式
- 创建哨兵模式文件夹
mkdir /home/redis-sentinel && cd /home/redis-sentinel
- 创建节点配置文件,根据不同情况修改以下内容
for node in `seq 6380 6382`;do \
mkdir $node \
&& mkdir $node/conf \
&& mkdir $node/data \
&& echo "port $node
slaveof 192.168.66.168 6380" > $node/conf/redis.conf \
&& echo "# 禁止保护模式,redis在启动的时候默认会启动一个保护模式,只有同一个服务器可以连接上redis。别的服务器连接不上这个redis
port 2$node
protected-mode no
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 192.168.66.168 6380 2" > $node/conf/sentinel.conf \
&& chmod 777 $node/conf/sentinel.conf ; \
done
- 删除master节点下的
slaveof 192.168.66.168 6380
- 启动服务
for node in `seq 6380 6382`;do \
docker run -d \
-u root \
--restart=always \
--name redis-$node \
--privileged=true -v /home/redis-sentinel/$node/conf/redis.conf:/usr/local/redis/redis.conf \
--privileged=true -v /home/redis-sentinel/$node/conf/sentinel.conf:/usr/local/redis/sentinel.conf \
-v /home/redis-sentinel/$node/data:/data \
--network host \
redis:v5 redis-server /usr/local/redis/redis.conf; \
done
- 启动哨兵
for node in `seq 6380 6382`;do
docker exec -d redis-$node /usr/local/bin/redis-sentinel /usr/local/redis/sentinel.conf ;\
done
- java代码连接,首先导入redis包,然后连接redis
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
// 哨兵信息
Set<String> sentinels = new HashSet<String>(Arrays.asList("192.168.66.168:26380",
"192.168.66.168:26381","192.168.66.168:26382"));
// 创建连接池
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
Jedis jedis = pool.getResource();
// 执行两个命令
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println(value);
集群模式
- 拉取镜像,版本为redis-5.0.7
docker pull registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5
docker tag registry.cn-hangzhou.aliyuncs.com/sasiki/redis:v5 redis:v5
- 创建集群文件夹
mkdir /home/redis-cluster
cd /home/redis-cluster
- 在文件夹下创建模板文件
vim redis-cluster.tmpl
,内容如下,使用需要把注释去掉
port ${PORT} ##节点端口
cluster-enabled yes ##cluster集群模式
cluster-config-file nodes.conf ##集群配置名
cluster-node-timeout 5000 ##超时时间
cluster-announce-ip 192.168.66.168 ##实际为各节点网卡分配ip 先用上网关ip代替
cluster-announce-port ${PORT} ##节点映射端口
cluster-announce-bus-port 1${PORT} ##节点总线端
appendonly yes ##持久化模式
- 创建节点配置文件
cd /home/redis-cluster
for port in `seq 7010 7015`; do \
mkdir -p ./${port}/conf \
&& PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf \
&& mkdir -p ./${port}/data; \
done
- 检查是否创建成功,如果成功则根据配置启动docker文件
for port in `seq 7010 7015`; do \
docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} \
--privileged=true -v /home/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
--privileged=true -v /home/redis-cluster/${port}/data:/data \
--restart always --name redis-${port} \
--sysctl net.core.somaxconn=1024 redis:v5 redis-server /usr/local/etc/redis/redis.conf; \
done
- 验证容器是否启动
docker ps
- redis5.0之后,集群启动不需要ruby,可以使用自带的redis-cli客户端启动,随便进入一个容器
docker exec -it redis-7010 /bin/bash
cd /usr/local/bin
./redis-cli --cluster create 192.168.66.168:7010 192.168.66.168:7011 192.168.66.168:7012 192.168.66.168:7013 192.168.66.168:7014 192.168.66.168:7015 --cluster-replicas 1
- 不要退出容器,查看主从情况
root@67fedec5b8ac:/usr/local/bin# ./redis-cli -p 7010 cluster nodes
3f16abec2cb00d238e05c129e590ab9118028b92 192.168.66.168:7013@17013 slave 13bf330ec7d8ddca9f25904384a4b2dac95ee65d 0 1577431614669 4 connected
13bf330ec7d8ddca9f25904384a4b2dac95ee65d 192.168.66.168:7012@17012 master - 0 1577431614066 3 connected 10923-16383
4961884c920478d7a71453ba2d2236cfa67a2412 192.168.66.168:7010@17010 myself,master - 0 1577431613000 1 connected 0-5460
81ded58d39c604db93b2073caff8457dec73523c 192.168.66.168:7014@17014 slave 4961884c920478d7a71453ba2d2236cfa67a2412 0 1577431613159 5 connected
975bae49314b178bda5c17935d00e1cafe878002 192.168.66.168:7011@17011 master - 0 1577431613562 2 connected 5461-10922
1bf508a8d6bd5760c4bdc3207f79acf43c4f87ec 192.168.66.168:7015@17015 slave 975bae49314b178bda5c17935d00e1cafe878002 0 1577431614165 6 connected
- 测试是否成功
root@67fedec5b8ac:/usr/local/bin# ./redis-cli -p 7010
127.0.0.1:7010> set a 1
(error) MOVED 15495 192.168.66.168:7012
- java代码
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(20);
config.setMaxIdle(2);
HostAndPort hp0 = new HostAndPort("192.168.66.168", 7010);
HostAndPort hp1 = new HostAndPort("192.168.66.168", 7011);
HostAndPort hp2 = new HostAndPort("192.168.66.168", 7012);
HostAndPort hp3 = new HostAndPort("192.168.66.168", 7013);
HostAndPort hp4 = new HostAndPort("192.168.66.168", 7014);
HostAndPort hp5 = new HostAndPort("192.168.66.168", 7015);
Set<HostAndPort> hps = new HashSet<HostAndPort>();
hps.add(hp0);
hps.add(hp1);
hps.add(hp2);
hps.add(hp3);
hps.add(hp4);
hps.add(hp5);
// 超时,最大的转发数,最大链接数,最小链接数都会影响到集群
JedisCluster jedisCluster = new JedisCluster(hps, 5000, 10, config);
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
jedisCluster.set("sn" + i, "n" + i);
}
long end = System.currentTimeMillis();
System.out.println("Simple @ Sharding Set : " + (end - start) / 10000);
for (int i = 0; i < 100; i++) {
System.out.println(jedisCluster.get("sn" + i));
}
jedisCluster.close();