Redis集群模式

1.Redis集群模式--解决redis单点故障

        单点故障问题主要是由于redis是单机运行的,该机器出现故障后,会间接导致使用redis的程序出现错误。因此我们可以使用redis的集群模式来避免这个问题。

        redis集群模式有哪些?

        1.主从复制模式

        2.哨兵模式

        3.集群化模式

1.1 主从复制模式 

主从模式:一主多从,一个主节点,多个从节点,其中主节点拥有读写操作权限,从节点只能拥有读权限,由此可以降低主节点的读取压力,降低损坏风险。

当主节点完成写操作后,会将数据同步到从节点中,从而实现数据共享。

(1)如何搭建主从关系(查看主从关系:info replication)

1.原则:配从不配主

2.准备:一主二从-----三台服务器----即开启三台虚拟机

3.开启三台机器的redis服务(此时查看三台机器的角色发现都是master)

4.改变两台从节点的角色------->命令:slaveof 主节点的ip 主节点redis服务的端口号

5.此时再看三台机器的角色发现,两台从节点的角色变成了slave

6.此时操作时发现,三台机器都拥有读权限,而只有主节点拥有写权限

 (2)主从模式的相关问题

1.当主节点挂掉了,从节点是否会自动成为主节点?

答:不会,需要手动调整主从关系。

2.如果有新增的从节点,那么新的从节点是否会自动同步数据?

答:会,主从之间的数据会自动同步

 1.2 哨兵模式

由于主从模式会出现从节点不会自动上位的问题,需要手动配置,相对比较麻烦,因此使用哨兵模式解决这个问题。

在原有的主从关系基础上,添加哨兵服务,当主节点出现问题(例如,宕机、服务器关闭等)以后,哨兵会从主节点下的从节点中,挑选一个从节点成为新的主节点[采用哨兵投票机制决定由谁升级为主节点]。

实现哨兵模式

1.完成主从复制模式搭建

2.修改sentinel.conf配置文件

 3.启动哨兵服务------>命令:redis-sentinel sentinel.conf

 启动成功

哨兵模式下会出现的问题是,原来的主节点恢复后,不再是主节点,而是作为新任主节点的从节点继续存在

1.3 集群化模式(多主多从)

以上的两种方式都无法解决单节点写操作的故障,此时就可以使用集群化模式(去中心化模式)来解决这个问题。

原理:

redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个整数结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里有很多key。

注:crc16算法可参考如下博客:CRC16 - yueyuef - 博客园

(1)搭建集群

准备:三主三从(主节点的个数应为奇数个,因为当主节点故障数量超过半数时,判定redis集群故障),所有机器的redis都需要以下要求:

1.开启远程访问权限;2.同时开启aof持久化;3.开启集群模式

开始搭建:

1.开启六台机器的redis服务

2.分配槽:redis-cli --cluster create --cluster-replicas 1(此处的数字代表每个主节点有几个从节点) 机器1ip:机器1端口 机器2ip:机器2端口 机器3ip:机器3端口 机器4ip:机器4端口 机器5ip:机器5端口 机器6ip:机器6端口 

其中前三台机器是主节点,紧接着是三台从节点分别对应给主节点(对应位:1-4,2-5,3-6)

(2) 测试集群

任意访问其中一台机器的端口都可以实现对集群的访问

2.Java操作redis---需要允许redis远程链接

从redis官网的文档中可以看到redis都支持那些语言,可以看到redis可以与很多语言进行对接,包括Java 

点击java可以跳转到对应的位置,查看所封装的好的接口

使用java通过Jedis链接redis的前提是,添加Jedis依赖(也可以说导入jedis相关jar包)

2.1 单独链接redis

(1)创建Jedis类的实例化对象

Jedis jedis = new Jedis("192.168.1.78",6379);

(2)测试链接

@Test
    void test01(){
        Jedis jedis = new Jedis("192.168.1.78",6379);
        String set = jedis.set("k12", "张三");
        System.out.println(set);
    }

 2.2 使用连接池链接redis

(1)实例化JedisPool类,并初始化配置

//连接池配置类
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(20);
        //最小空闲连接数
        jedisPoolConfig.setMinIdle(20);
        //最大等待时间
        jedisPoolConfig.setMaxWait(Duration.ofMillis(3000));

        JedisPool jedisPool = new JedisPool(jedisPoolConfig,"192.168.1.78",6379);

(2)测试链接

@Test
    void testJedisPool(){
        //连接池配置类
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大空闲连接数
        jedisPoolConfig.setMaxIdle(20);
        //最小空闲连接数
        jedisPoolConfig.setMinIdle(20);
        //最大等待时间
        jedisPoolConfig.setMaxWait(Duration.ofMillis(3000));

        JedisPool jedisPool = new JedisPool(jedisPoolConfig,"192.168.1.78",6379);

        //从连接池中获取Jedis对象
        Jedis jedis = jedisPool.getResource();
        String set = jedis.set("k13", "李四");
        System.out.println(set);
    }

(3)为何要使用jedis连接池

当访问数量过多时,使用链接池的效率要远高于直接使用jedis对象;

2.3 链接redis集群

(1)实例化JedisCluster类

3.springboot整合redis

springboot对redis的操作封装了两个类,StringRedisTemplate类和RedisTemplate类

StringRedisTemplate是RedisTemplate的子类,StringRedisTemplate只能存储String类型,无法存储对象类型。要想用StringRedisTemplate存储对象,则必须将对象转为JSON字符串。

在springboot中使用以上所说的两个类,首先就需要引入相关依赖

3.1 StringRedisTemplate

3.2 RedisTemplate

3.3 二者如何选择

一般情况下都会使用,可以根据实际存储的内容进行选择,如果所存储的value值为String类型,则使用StringRedisTemplate较为方便,如果是其他类型,则使用RedisTemplate。

4.redis的使用场景

4.1 redis存储热点数据

4.2 redis实现分布式锁

4.2.1 redis实现分布式锁的缺陷

Redis实现分布式锁,无法解决超时问题,分布式锁有一个超时时间,程序的执行时间如果超过了锁的超时时间就会出现问题。

解决方案:使用redisson来解决;

redisson解决redis分布锁超时问题的原理:

 为持有锁资源的线程开启一个守护线程,该守护线程,会每隔十秒检查当前线程时候还持有锁,如果仍持有,则会延长锁的持有时间。

4.2.2 使用redisson解决redis实现分布式锁的缺陷

(1)引入redisson对象

        

(2)

5.Redis常见面试题

5.1 什么是缓存穿透?如何解决?

缓存穿透:数据库中没有该记录,缓存中也没有该记录,此时有人恶意大量访问这样的数据,这样就会导致该请求绕过缓存直接访问数据库,从而造成数据库压力过大,这种现象就是缓存穿透。

解决方案:(建议三种都用)

1.在controller层添加数据校验,过滤非正常数据

2.我们可以在redis中存入一个空对象,而且给空对象设置过期时间,不宜过长否则将会存在大量的空对象,一般不超过5分钟

3.我们可以使用布隆过滤器,底层有一个bitmap数组,里面存储了某表中的所有id 

 5.2 什么是缓存雪崩?如何解决?

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据 库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发 查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。 (一般发生在缓存时间大量到期、项目刚上线或者redis发生宕机)

解决方案:

1.上线前预先将热点数据存入缓存中

2.将缓存过期时间设置为散列值

3.搭建redis集群

 5.3 什么是缓存击穿?如何解决?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这 时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案:
缓存击穿解决方案 :
1. 设置永久不过期。【这种只适合访问量十分巨大的数据】
2. 使用互斥锁 (mutex key) 业界比较常用的做法,是使用 mutex。简单 地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db ,而是先使用缓存工具的某些带成功操作返回值的操作(比如 Redis的 SETNX 或者 Memcache ADD )去 set 一个 mutex key,当操作返回成功 时,再进行 load db 的操作并回设缓存;否则,就重试整个 get 缓存的方
法。

 5.4 redis的淘汰策略有哪些?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值