reids分片,哨兵,集群搭建

springBoot整合reids

1.改pom文件

添加jar包

<!--spring整合redis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>

2.测试单机连接

package com.jt.test;

import com.baomidou.mybatisplus.annotation.TableId;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.params.SetParams;

//@SpringBootTest //如果需要在测试类中引入spring容器机制才使用该注解
public class TestRedis {

    /**
     * 测试远程redis服务器是否可用
     * host: 192.168.126.129
     * port: 6379
     * 思路:
     *      1.实例化链接对象
     *      2.利用对象执行redis命令
     *
     * 报错调试:
     *      1.检查Redis.conf的配置文件是否按照要求修改 ip/保护/后台
     *      2.redis启动方式      redis-server redis.conf
     *      3.关闭防火墙         systemctl  stop firewalld.service
     * */
    @Test
    public void test01(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.set("redis", "测试redis是否可用");
        System.out.println(jedis.get("redis"));
    }

    /**
     * String类型API学习
     * 需求: 判断key是否存在于Redis.如果存在则不赋值,否则入库.
     *
     */
    @Test
    public void test02(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        if(jedis.exists("redis")){
            System.out.println("数据已存在");
            jedis.expire("redis", 10);
        }else{
            jedis.set("redis", "aaaa");
        }
        System.out.println(jedis.get("redis"));
    }

    //可以利用优化的API实现业务功能.
    //业务: 如果数据存在则不赋值
    @Test
    public void test03(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.flushAll();   //清空redis服务器
        // 如果key存在则不做任何操作
        jedis.setnx("redis", "测试赋值操作!!!");
        System.out.println(jedis.get("redis"));
    }

    /**
     * 测试添加超市时间的有效性.
     * 业务: 向redis中保存一个数据之后,要求设定10秒有效.
     * 原子性: 要么同时成功,要么同时失败.
     */
    @Test
    public void test04(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
    /*    jedis.set("aa", "aa"); //该数据将永不删除.
        int a = 1/0;
        jedis.expire("aa", 10);*/
        jedis.setex("aa", 10, "aa"); //单位秒
        //jedis.psetex(, ); //设置毫秒
    }

    /**
     * 需求: 要求添加一个数据,只有数据存在时才会赋值,并且需要添加超时时间
     *      保证原子性操作.
     *  private static final String XX = "xx";  有key的时候才赋值
     *  private static final String NX = "nx";  没有key时才赋值
     *  private static final String PX = "px";  毫秒
     *  private static final String EX = "ex";  秒
     *  redis分布式锁的问题
     * */
    @Test
    public void test05(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        SetParams setParams = new SetParams();
        setParams.xx().ex(10);
        jedis.set("aaa", "aaa", setParams);
    }

    @Test
    public void testList(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        jedis.lpush("list2", "1,2,3,4,5");
        System.out.println(jedis.rpop("list2"));
    }

    /**
     * 控制redis事务
     * 说明:操作redisredis适用于事务控制
     *      但是如果是多台redis则不太适用事务.
     * */
    @Test
    public void testTx(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        //开启事务
        Transaction transaction = jedis.multi();
        try {
            transaction.set("bb", "bb");
            transaction.exec(); //提交事务
        }catch (Exception e){
            transaction.discard();
        }
    }

}



创建配置类

目的,项目的域名和端口号解耦

在这里插入图片描述


package com.jt.config;

importorg.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;

@Configuration //标识我是一个配置类
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {

    @Value("${redis.host}")
    private String  host;
    @Value("${redis.port}")
    private Integer port;
    /**
     * 将jedis对象交给spring容器管理
     */
    @Bean
    public Jedis jedis(){
        //由于将代码写死不利于扩展,所以将固定的配置添加到配置文件中
        return new Jedis(host,port);
    }

}

redis分片机制

为什么使用分片

当redis需要存储海量的数据存储,单个reids显然不能完成这个业务,如果一直扩容redis的内存,效果并不好,这时候就需要进行分片,开启多台redis,分别保存用户的数据,实现内存扩容

配置redis分片

在Linux系统中,给分片备好专门的文件夹,在redis根目录中创建一个shards目录

mkdir shards

由于redis启动时更具配置文件redis.conf 运行的,所以需要多少台reids就需要复制几份配置文件到 shards目录.

在这里插入图片描述

将复制好的配置文件的端口号进行修改

在这里插入图片描述

在这里插入图片描述

修改好之后依次启动,也可以使用 sell脚本启动,这样就是分片机制,既多开

springboot测试

 /**
     * 测试Redis分片机制
     */
    @Test
    public void testShards(){
    	//泛型是redis提供的类型,专门用于存redis服务
        List<JedisShardInfo> list = new ArrayList<>();
       //分别将多台reids添加进容器
       list.add(new JedisShardInfo("192.168.126.129", 6379));
        list.add(new JedisShardInfo("192.168.126.129", 6380));
        list.add(new JedisShardInfo("192.168.126.129", 6381));
      //构造分片服务器,使用默认的一致性hash算法进行数据的存储
      ShardedJedis shardedJedis = new ShardedJedis(list);
        shardedJedis.set("2005", "redis分片学习");
        System.out.println(shardedJedis.get("2005"));
    }

分片的 一致性hash算法

什么是一致性hash算法

是一种特别的哈希算法,更具hash的取值范围,获取node节点: 2^32冥,从开始到结尾形成一个圈,有多少台redis的个数获取多少个reids的节点,将每个存入的数组的key进行hash计算,得到的hash值按照顺时针反向找到最近的redis服务节点存入

一致性hash算法的特性

平衡性:hash的结果应该平均分配到各个节点,从算法上解决负载均衡

​ 说明.如果发现节点中存储的数据负载不均衡,会启用虚拟节点的方式实现数据的平衡

单调性:指在新增或者删除节点时,不影响系统的正常运行,会自动实现数据转移

分散性:指数据应该分散的存放在各个节点中,没有必要每个节点都存储所有的数据

分片的缺点

功能主要的作用是实现内存数据的扩容,但是如果宕机了不能实现高可用

springboot整合redis分片

#添加redis的配置

#添加单台配置
#redis.host=192.168.126.129
#redis.port=6379

#配置多台的redis信息
redis.nodes=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381

redis主从实现

为了实现redis高可用的前提条件,可以实现主redis宕机后从redis服务器顶上去

准备工作

构建一个专用的目录用于实现主从配置,避免混淆

mkdir sentinel

向文件中复制好配置文件

在这里插入图片描述

修改好端口号,并启动

搭建 进入到第一台redis服务器

使用命令检查主从状态

 info replication

在这里插入图片描述

role 显示 master 说明是主机

进入准备做从机的redis服务器使用命令进行主从挂载

slaveof 主机IP 主机端口

在这里插入图片描述

检查是否是从机

在这里插入图片描述

role显示是 slave, 表示是从机

master_host:显示主机的ip

master_port:显示主机的端口号

主从挂载错误说明

当挂载错误后,可以将reids服务器全部关闭,之后再重启,默认条件下主从挂载会失效,重新挂载即可,因为主从挂载的命令只做用与内存中.

需要永久有效,需要写到配置文件中

redis的哨兵机制

为了实现redis服务的高可用,解决主机宕机后由那个从机顶上

哨兵工作原理

  • 当哨兵启动时,会监控当前的主机信息,同时获取连接当前主机的从机信息

  • 哨兵会使用心跳检查机制监控主机是否宕机,如果主机连续3次没有响应,则认为主机宕机,开始选举机制挑选一个从机当主机

  • 当新的主机被确定,其他从机将会成为新主机的从机,当之前主机恢复后,也会成为从机

配置哨兵机制

准备 : 将原有哨兵配置文件sentinel.conf 复制一份到之前准备好的文件夹中,尽量不修改原配置文件,避免配置文件写错后,没有备用

在这里插入图片描述

修改哨兵的配置文件,将保护模式关闭

在这里插入图片描述

开启后台运行

在这里插入图片描述

修改哨兵的监控,其中的一表示投票数为1就生效,成为主机在这里插入图片描述

修改哨兵选举时间 , 意思是主机宕机10s 后开启进行选举

在这里插入图片描述

修改哨兵选举超时时间

在这里插入图片描述

保存设置,并启动哨兵,进行测试

  • 启动哨兵命令:
redis-sentinel sentinel.conf
  • 先关闭主机,之后等待10秒之后,检查从机是否当选主机.之后再次启动主机(宕机的),检查是否为新主机的从在这里插入图片描述

关于哨兵的说明

哨兵的脑裂现象:

​ 多个哨兵进行选举,如果连续3次投票失败,可能会引发脑裂,既多个主机

出现脑裂的几率为12.5%,

解决方法:增加选举的节点的数据,使用概率论

   /**
     * 哨兵的测试
     * 参数说明:  masterName: 主机的变量名称
     *           sentinels:   链接哨兵的集合.
     * 理解: 哨兵虽然链接3台redis. 但是3台redis中存储的数据都是一样的.对于用户而言
     * 就是一台.
     */
    @Test
    public void testSentinel(){
        Set<String> sets = new HashSet<>();
        sets.add("192.168.126.129:26379");
        //哨兵池,获取哨兵对象
        JedisSentinelPool sentinelPool =
                new JedisSentinelPool("mymaster",sets);
                //获取redis主机的服务对象
        Jedis jedis = sentinelPool.getResource();
        jedis.set("aaa", "wt");
        System.out.println(jedis.get("aaa"));
        jedis.close();
    }

reids集群

目的:整合分片和哨兵的功能

为了保证数据分散存储,同时保证数据存储的一致性.并且在内部实现高可用的机制.实现了服务故障的自动迁移.

准备 搭建最低配置

主从划分: 3台主机 3台从机共6台 端口划分7000-7005

1.准备一个专业文件夹 cluster 命令

Mkdir cluster

2.在cluster文件夹中分别创建7000-7005文件夹

mkdir 7000 7001 7002 7003 7004 7005

3.将redis根目录中的redis.conf文件复制到cluster/7000/ 并以原名保存

cp redis.conf cluster/7000/

编辑7000文件夹中的redis.conf文件

  • 注释本地绑定的ip地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jWO0ewH5-1602686255409)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173205989.png)]

  • 关闭保护模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GohvIb1m-1602686255411)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173240428.png)]

  • 修改端口号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EFvZ5O3K-1602686255413)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173304115.png)]

  • 启动后台启动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyZy6IPM-1602686255415)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173324221.png)]

  • 修改pid文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-heH4WYNo-1602686255417)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173351030.png)]

  • 修改持久化文件路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9N8eL70s-1602686255419)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173409711.png)]

  • 设定内存优化策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IeuU1PuZ-1602686255420)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173427307.png)]

  • 关闭AOF模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yn6QFNvy-1602686255421)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173450855.png)]

  • 开启集群配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uJI8EoLl-1602686255422)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173503607.png)]

  • 开启集群配置文件

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hx9ZRUtl-1602686255423)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173521563.png)]

  • 修改集群超时时间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YyCVp1UO-1602686255424)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013173537424.png)]

修改完毕保存

3.说明:将7000文件夹下的redis.conf文件分别复制到7001-7005中

[root@localhost cluster]# cp 7000/redis.conf 7001/

[root@localhost cluster]# cp 7000/redis.conf 7002/

[root@localhost cluster]# cp 7000/redis.conf 7003/

[root@localhost cluster]# cp 7000/redis.conf 7004/

[root@localhost cluster]# cp 7000/redis.conf 7005/

批量修改 配置文件

说明:分别将7001-7005文件中的7000改为对应的端口号的名称,

修改时注意方向键的使用

进入reids.conf文件中使用 %s/7000/7001/g 批量修改

vim 7000/redis.conf
%s/7000/7001/g

通过脚本启动

编辑脚本编辑启动脚本命令

 vim start.sh

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QPmrzhQP-1602686255427)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013190517008.png)]

编辑关闭脚本 命令

 vim shutdown.sh

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uLehjrK0-1602686255428)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013190624178.png)]

使用脚本启动,命令

sh start.sh

检查redis节点启动是否正常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dwL4Ox9-1602686255429)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013190755369.png)]

创建redis集群

重启reids服务并搭建集群

#5.0版本执行 使用C语言内部管理集群

redis-cli --cluster create --cluster-replicas 1 192.168.35.130:7000 192.168.35.130:7001 192.168.35.130:7002 192.168.35.130:7003 192.168.35.130:7004 192.168.35.130:7005

redis集群说明

存储的原理

hash槽算法也叫分区算法

根据哈希算法中的CRC16[key]%16384 进行映射存储,一共16384个槽位在这里插入图片描述

当向redis集群中插入数据时,首先将key进行计算.之后将计算结果匹配到具体的某一个槽的区间内,之后再将数据set到管理该槽的节点中.

Redis集群高可用推选原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-81TKpFsx-1602686255430)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013190945894.png)]

rredis的所有节点都会保存当前redis集群中全部主从状态信息,并且每个节点都能够相互通信,当一个节点发生宕机现象,则集群中的其他节点通过ping-pong检测机制检查redis节点是否宕机,当半数以上的节点认为宕机,则认为主节点宕机,同时由redis剩余的主节点进入选举机制,投票选举链接宕机的主节点的从机.实现故障迁移

redis集群宕机条件

特点:集群中如果主机宕机,那么从机可以继续提供服务,

当主机中没有从机时,则向其它主机借用多余的从机.继续提供服务.如果主机宕机时没有从机可用,则集群崩溃.

答案:9个redis节点,节点宕机5-7次时集群才崩溃.既半数以上宕机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0DdDcyOu-1602686255431)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20201013191758399.png)]

Redis内存优化

LRU算法:即最近最少使用是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。

维度:时间T
LRU算法是当下实现内存清理的最优算法.

LFU算法最不经常使用页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
维度: 引用次数

Random算法 随机删除

TTL算法说明:监控剩余的存活时间,将存活时间少的数据提前删除.

在redis.conf配置文件中设置

1.volatile-lru  在设定了超时时间的数据中,采用lru算法.
2.allkeys-lru  所有数据采用lru算法
3.volatile-lfu  在超时的数据中采用lfu算法
4.allkeys-lfu -> 所有数据采用lfu算法
5.volatile-random -> 设定超时时间的数据采用随机算法
6.allkeys-random -> 所有数据随机删除
7.volatile-ttl ->  删除存活时间少的数据
8.noeviction -> 不会删除数据,如果内存溢出报错返回.


在这里插入图片描述

面试题

假设你是项目组长,手下一个特别漂亮的妹子在线上执行了flushALL命令.问:如果是你应该怎么办??

解决方案: 应该将AOF模式中flushAll删除,之后重启redis即可.

redis的持久化机制

RDB:

但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
维度: 引用次数

Random算法 随机删除

TTL算法说明:监控剩余的存活时间,将存活时间少的数据提前删除.

在redis.conf配置文件中设置

1.volatile-lru  在设定了超时时间的数据中,采用lru算法.
2.allkeys-lru  所有数据采用lru算法
3.volatile-lfu  在超时的数据中采用lfu算法
4.allkeys-lfu -> 所有数据采用lfu算法
5.volatile-random -> 设定超时时间的数据采用随机算法
6.allkeys-random -> 所有数据随机删除
7.volatile-ttl ->  删除存活时间少的数据
8.noeviction -> 不会删除数据,如果内存溢出报错返回.


在这里插入图片描述

面试题

假设你是项目组长,手下一个特别漂亮的妹子在线上执行了flushALL命令.问:如果是你应该怎么办??

解决方案: 应该将AOF模式中flushAll删除,之后重启redis即可.

redis的持久化机制

RDB:

AOF:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值