创建并进入cluster目录

mkdir /usr/local/redis-6.2.6/cluster/
cd /usr/local/redis-6.2.6/cluster/

redis.conf授权777

chmod -R 777 /usr/local/redis-6.2.6/redis.conf

软连接redis-server、redis-cli、redis-sentinel到/usr/bin

ln -s /usr/local/redis-6.2.6/bin/redis-server /usr/bin
ln -s /usr/local/redis-6.2.6/bin/redis-cli /usr/bin
ln -s /usr/local/redis-6.2.6/bin/redis-sentinel /usr/bin

主从复制、哨兵模式、cluster集群搭建

vim /usr/local/redis-6.2.6/cluster/redis6379.conf
include /usr/local/redis-6.2.6/redis.conf
pidfile "/var/run/redis_6379.pid"
port 6379
dbfilename "dump6379.rdb"
#可配可不配(建议配,可以查看报错信息)
logfile "/usr/local/redis-6.2.6/cluster/redis6379.log"
#打开集群模式
cluster-enabled yes
#设置节点配置文件名
cluster-config-file nodes-6379.conf
#设定节点失联时间。超过该时间(毫秒数),集群自动进行主从切换
cluster-node-timeout 15000

哨兵模式(当主服务器宕机,从服务器变成主服务器,即反客为主)必须叫sentinel.conf

vim /usr/local/redis-6.2.6/cluster/sentinel.conf
#后台启动
daemonize yes
# mymaster为监控对象起的服务器名称,1为最少有多少个哨兵同意迁移的数量。
sentinel monitor mymaster 127.0.0.1 6379 1

启动哨兵sentinel

[root@node1 cluster]# redis-sentinel /usr/local/redis-6.2.6/cluster/sentinel.conf

在cluster文件夹下面复制5个redis6379.conf,文件名和里面的内容都分别改成6380、6381、6382、6383、6384

[root@node1 ~]# cd /usr/local/redis-6.2.6/cluster
[root@node1 cluster]# redis-server redis6379.conf
[root@node1 cluster]# redis-server redis6380.conf
[root@node1 cluster]# redis-server redis6381.conf
[root@node1 cluster]# redis-server redis6382.conf
[root@node1 cluster]# redis-server redis6383.conf
[root@node1 cluster]# redis-server redis6384.conf

这里不能配置127.0.0.1,要用真实ip地址,cluster-replicas 1采用最简单的方式配置集群,一主一从,正好三组,最少三组

[root@node1 src]# redis-cli --cluster create --cluster-replicas 1 192.168.10.111:6379 192.168.10.111:6380 192.168.10.111:6381 192.168.10.111:6382 192.168.10.111:6383 192.168.10.111:6384

Can I set the above configuration? (type ‘yes’ to accept): 直接输入yes
出现[OK] All nodes agree about slots configuration.说明集群启动成功了

连接redis集群

[root@node1 src]# redis-cli -c -p 6379
#cluster nodes查看集群信息,其中6379、6380、6381是主,6382、6383、6384是从
127.0.0.1:6379> cluster nodes
#主机ID										主机IP		主机port		主机									主机slot插槽
bfdbb642d3752f53961cd9debdb60b42635cfbfb 192.168.10.111:6380@16380 master - 0 1653203971000 2 connected 5461-10922
43b3a0090b77262e11a3752057e275652ed77181 192.168.10.111:6381@16381 master - 0 1653203970128 3 connected 10923-16383
51caf405d658bcd4e8bcc4f828983f574881acee 192.168.10.111:6384@16384 slave 43b3a0090b77262e11a3752057e275652ed77181 0 1653203973156 3 connected
b7adf13c6f20ce956c482f4378eb831303134ec5 192.168.10.111:6379@16379 myself,master - 0 1653203972000 1 connected 0-5460
#从机ID										从机IP		从机port		从机  从机对应的主机ID
9a01951e96db134bc623dea8605bf5f4b8bf8246 192.168.10.111:6383@16383 slave bfdbb642d3752f53961cd9debdb60b42635cfbfb 0 1653203972147 2 connected
0dd6f7cddae11fbde59f49417e9e3d2ebec44292 192.168.10.111:6382@16382 slave b7adf13c6f20ce956c482f4378eb831303134ec5 0 1653203971137 1 connected

设置Redis集群密码

# 123456就是密码
127.0.0.1:6379> config set requirepass 123456
OK
# rewrite重写配置文件,使配置文件生效
127.0.0.1:6379> config rewrite
OK

springboot 集成redis cluster集群

application.yml配置

spring:
  redis:
    #过期时间
    timeout: 15000
    #cluster集群配置(首先要在linux搭建好主从复制(三主三从)、哨兵模式监听master、cluster集群)
    cluster:
      #重定向的最大数量,比如第一台挂了,连第二台,第二台挂了连第三台
      max-redirects: 3
      #redis节点:ip+port
      nodes:
        - 192.168.1.11:6381
        - 192.168.1.11:6382
        - 192.168.1.11:6383
        - 192.168.1.11:6384
        - 192.168.1.11:6385
        - 192.168.1.11:6386
    lettuce:
      pool:
        enabled: true
      cluster:
        refresh:
          # 防止redis重启节点更换,spring boot没有动态感知,导致抛出超时或异常。
          adaptive: true
          # 定时刷新时间(单位秒s)
          period: 2000

RedisConfig.java序列化配置

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    /**
     * 防止数据存入redis乱码
     */
    @Bean(name="redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        // 设置序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置redisTemplate
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        RedisSerializer<?> stringSerializer = new StringRedisSerializer();
        // key序列化
        redisTemplate.setKeySerializer(stringSerializer);
        // value序列化,可序列化对象
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(stringSerializer);
        // Hash value序列化,可序列化对象
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

controller.java

	@Resource
    RedisTemplate<String,Object> redisTemplate;
    @GetMapping("hello")
    public String hello() {
        redisTemplate.opsForValue().set("test","a",300,TimeUnit.SECONDS);
        String msg = (String) redisTemplate.opsForValue().get("test");
        System.out.println(msg);
        return "hello";
    }

启动springboot项目,访问一下hello接口,查看redis集群里面是否包含key为test。
spring boot 连接redis connect time out看看你linux防火墙有没有开放6379、6380、6381、6382、6383、6384端口(自己玩建议关闭防火墙,正式环境还是不要关,用哪个开哪个。)
在这里插入图片描述
这里只展示了3个,剩余3个就不展示了。


redis分布式锁setnx key value nx ex 过期时间

setnx设置锁(设置锁时必须设置过期时间,防止系统故障导致死锁

127.0.0.1:6779> setnx k1 v1 nx ex 10

ttl查看key的锁的过期时间

127.0.0.1:6779> ttl k1

del释放锁

127.0.0.1:6779> del k1

高并发情况下可能会存在误删。解决方案设置value为UUID,判断UUID是否一致再释放锁。(但会有问题)

127.0.0.1:6779> setnx k1 UUID nx ex 1

步骤:

  1. 上锁setnx并设置value为UUID,防止误删锁
  2. lua脚本释放锁del
    (1)比较UUID是否一致
    (2)删除操作时,正要删除,还没删除,锁到了过期时间,自动释放(不能保证原子性)
    遇到上面(2)这种情况,使用lua脚本使用同一把锁来实现删除。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐