• Redis+SpringBoot企业版集群实战------【华为云版】


     

    目录

    安装

    复制及集群

    bgsave

     rdb

    aof

    SpringBoot+Redis操作

    操作string

    操作hash

    操作set

    操作sorted set

    获取所有key&删除

    设置key的失效时间

    SpringDataRedis整合使用哨兵机制


    安装

    下载地址

    Redis

    上传至服务器

     解压

    tar zxvf redis-5.0.3.tar.gz
    

    安装依赖

    yum -y install gcc-c++ autoconf automake

     预编译

    切换到解压目录

    cd redis-5.0.3/
    make
    

    创建安装目录

    mkdir -p /usr/local/redis

    不使用:make install(make install默认安装到/usr/local/bin目录下)

    使用:如果需要指定安装路径,需要添加PREFIX参数

    make PREFIX=/usr/local/redis/ install

    安装成功如图

    Redis-cli :客户端

    Redis-server :服务器端

    安装的默认目标路径:/usr/local/redis/bin

     启动

    ./redis-server

     默认为前台启动,修改为后台启动

    复制redis.conf至安装路径下

    cp redis.conf /usr/local/redis/bin/

    修改安装路径下的redis.conf,将 daemonize 修改为yes

    启动时,指定配置文件路径即可

     通过windows客户端访问

    安装Redis客户端

    建立连接->失败 

     修改配置文件redis.conf

    注释掉 bind 127.0.0.1 可以使所有的ip访问redis,若是想指定多个ip访问,但并不是全部的ip访问,可以bind设置

    关闭保护模式,修改为no

    添加访问认证 

    修改后kill -9 XXXX杀死redis进程,重启redis 

     再次建立连接 -> 成功

     我们可以修改默认数据库的数量 默认16

     修改database 32则默认为32个数据库

    修改后kill -9 XXXX杀死redis进程,重启redis即可看到效果

    复制及集群

    持久化方案

    bgsave

     rdb

    redis.conf  中的 dbfilename dump.rdb  配置(rdb是默认开启的)

     会生成一个 dump.rdb 文件

     输入命令 进入 dump.rdb 文件(vim  dump.rdb

    下面的意思是(可以根据自己需求进行添加):

     1、900秒之内有一个key发生变化就会把数据存入到磁盘里面

     2、300秒之内有十个key发生变化就会把数据存入到磁盘里面

     3、60秒之内有一万个key发生变化就会把数据存入到磁盘里面

    aof

     如何进行开启,把 appendonly 改成 yes

    会发现多了一个 appendonly.aof 文件

    添加一个key

     

    打开 appendonly.aof 文件 ,如下图所示:

    主从复用

    读写分离

    创建三个目录(数据文件、日志文件、配置文件)

     复制redis.conf至/opt/redis/conf目录下

    修改redis-common.conf公共配置文件 

    注释掉bind 127.0.0.1

     关闭保护模式,修改为no

    注释公共配置端口 

     修改为后台启动

    注释进程编号记录文件 

     注释公共配置日志文件

    注释公共配置数据文件、修改数据文件路径 

    在默认情况下,Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。当然,这里可以通过修改 redis.conf 配置文件来对数据存储条件进行定义,规定在“ N 秒内数据集至少有 M 个改动”这一条件被满足时,自动保存一次数据集。也可以通过调用save 或bgsave ,手动让Redis进行数据集保存操作

     添加从服务器访问主服务器认证

    添加访问认证 

    注释公共配置追加文件 

    根据需求配置是否打开追加文件选项

    appendonly yes -> 每当Redis执行一个改变数据集的命令时(比如 SET),这个命令就会被追加到 AOF 文件的末尾。这样的话,当Redis重新启时,程序就可以通过重新执行 AOF文件中的命令来达到重建数据集的目的

    appendfilenamedir组合使用,找dir(/opt/redis/data)路径生成数据文件 

     从服务器默认是只读不允许写操作(不用修改)

    添加3个服务的私有配置文件 

    touch 或者 vi 都可以创建空白文件

    touch 直接创建空白文件, vi 创建并且进入编辑模式, :wq 创建成功,否则不创建

    cd /opt/redis/conf/

    ​​​​​​​ 

     redis-6379.conf

    1. #引用公共配置
    2. include /opt/redis/conf/redis-common.conf
    3. #进程编号记录文件
    4. pidfile /var/run/redis-6379.pid
    5. #进程端口号
    6. port 6379
    7. #日志记录文件
    8. logfile "/opt/redis/log/redis-6379.log"
    9. #数据记录文件
    10. dbfilename dump-6379.rdb
    11. #追加文件名称
    12. appendfilename "appendonly-6379.aof"
    13. #下面的配置无需在6379里配置
    14. #备份服务器从属于6379推荐配置配局域网IP
    15. slaveof 192.168.10.100 6379

    复制redis-6379.conf的内容至redis-6380.conf,redis-6381.conf并且修改其内容,将6379替换即可。

    运行3个redis进程

    cd /usr/local/redis/bin/

    ​​​​​​​

     查看redis服务器主从状态

    redis-6379

     

    redis-6380

    redis-6381

    在主服务器下添加数据并测试从服务器数据是否正常显示 

    从服务器只读,不允许写操作

     主备切换

    主从节点redis.conf配置

    参照 读写分离 的相应配置

    修改sentinel-common.conf 哨兵公共配置文件

    从redis解压目录下复制sentinel.conf至/opt/redis/conf/
    cp sentinel.conf /opt/redis/conf/sentinel-common.conf

    注释哨兵监听进程端口号

    指示 Sentinel 去监视一个名为 master 的主服务器,这个主服务器的IP地址为 127.0.0.1,端口号为6379,而将这个主服务器判断为失效至少需要1个(一般设置为2个)。 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)。 这个要配局域网IP,否则远程连不上。 

    设置masterslaves的密码

    Sentinel 认为服务器已经断线所需的毫秒数 

     若 sentinel 在该配置值内未能完成 failover 操作(即故障时master/slave自动切换),则认为本次 failover 失败。

     关闭保护模式,修改为no

    ​​​​​​​

     修改为后台启动

     添加3个哨兵的私有配置文件

    touch 或者 vi 都可以创建空白文件

    touch 直接创建空白文件, vi 创建并且进入编辑模式, :wq 创建成功,否则不创建

     sentinel-26379.conf

    1. #引用公共配置
    2. include /opt/redis/conf/sentinel-common.conf
    3. #进程端口号
    4. port 26379
    5. #进程编号记录文件
    6. pidfile /var/run/sentinel-26379.pid
    7. #日志记录文件(为了方便查看日志,先注释掉,搭好环境后再打开)
    8. logfile "/opt/redis/log/sentinel-26379.log"

    复制 sentinel-26379.conf 的内容至 sentinel-26380.conf , sentinel-26381.conf 并且修改其内容,将26379 替换即可。

    启动测试 

    启动3个redis服务

    1. /usr/local/redis/bin/redis-server /opt/redis/conf/redis-6379.conf
    2. /usr/local/redis/bin/redis-server /opt/redis/conf/redis-6380.conf
    3. /usr/local/redis/bin/redis-server /opt/redis/conf/redis-6381.conf

    启动3个哨兵服务 

    1. /usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26379.conf
    2. /usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26380.conf
    3. /usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26381.conf

    查看主从状态 

    redis-6379

    redis-6380 

     redis-6381

    检测哨兵功能是否配置成功 

    kill -9 终止redis-6379,查看哨兵是否选举了新的主节点

    ​​​​​​​

     已选举6380为主节点,从节点目前只有6381

     重新启动6379节点,再次查看主从状态

    发现6379已被发现且成为从节点

     6380之前不可以写操作,现在可以写操作,因为已成为主节点。

    最后,公共配置文件修改为后台启动,私有配置文件打开日志记录文件,环境搭建成功。

    SpringBoot+Redis操作

    创建项目

     

    添加依赖 

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.bootgroupId>
    4. <artifactId>spring-boot-starter-data-redisartifactId>
    5. dependency>
    6. <dependency>
    7. <groupId>org.apache.commonsgroupId>
    8. <artifactId>commons-pool2artifactId>
    9. dependency>
    10. <dependency>
    11. <groupId>org.springframework.bootgroupId>
    12. <artifactId>spring-boot-starter-webartifactId>
    13. dependency>
    14. <dependency>
    15. <groupId>org.springframework.bootgroupId>
    16. <artifactId>spring-boot-starter-testartifactId>
    17. <scope>testscope>
    18. dependency>
    19. dependencies>

     添加application.yml配置文件

    1. spring:
    2. redis:
    3. # Redis服务器地址
    4. host: 192.168.10.100
    5. # Redis服务器端口
    6. port: 6379
    7. # Redis服务器端口
    8. password: root
    9. # Redis服务器端口
    10. database: 0
    11. # 连接超时时间
    12. timeout: 10000ms
    13. lettuce:
    14. pool:
    15. # 最大连接数,默认8
    16. max-active: 1024
    17. # 最大连接阻塞等待时间,单位毫秒,默认-1ms
    18. max-wait: 10000ms
    19. # 最大空闲连接,默认8
    20. max-idle: 200
    21. # 最小空闲连接,默认0
    22. min-idle: 5

    测试环境测试环境是否搭建成功

    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringDataRedisApplication.class)
    3. public class SpringDataRedisApplicationTests {
    4. @Autowired
    5. private RedisTemplate redisTemplate;
    6. @Autowired
    7. private StringRedisTemplate stringRedisTemplate;
    8. @Test
    9. public void initconn() {
    10. ValueOperations ops = stringRedisTemplate.opsForValue();
    11. ops.set("username","lisi");
    12. ValueOperations value = redisTemplate.opsForValue();
    13. value.set("name","wangwu");
    14. System.out.println(ops.get("name"));
    15. }
    16. }

    自定义模板解决序列化问题

    默认情况下的模板 RedisTemplate,默认序列化使用的是 JdkSerializationRedisSerializer ,存储二进制字节码。这时需要自定义模板,当自定义模板后又想存储 String 字符串时,可以使StringRedisTemplate的方式,他们俩并不冲突。

    序列化问题:

    要把 domain object 做为 key-value 对保存在 redis 中,就必须要解决对象的序列化问题。Spring Data Redis给我们提供了一些现成的方案: 

    JdkSerializationRedisSerializer 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class), 但缺点是序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗 Redis 服务器的大量内存。

    Jackson2JsonRedisSerializer 使用 Jackson 库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class 对象)。通过查看源代码,发现其只在反序列化过程中用到了类型信息。 

    GenericJackson2JsonRedisSerializer 通用型序列化,这种序列化方式不用自己手动指定对象的 Class。 

    1. @Configuration
    2. public class RedisConfig {
    3. @Bean
    4. public RedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory){
    5. RedisTemplate redisTemplate = new RedisTemplate<>();
    6. //为string类型key设置序列器
    7. redisTemplate.setKeySerializer(new StringRedisSerializer());
    8. //为string类型value设置序列器
    9. redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    10. //为hash类型key设置序列器
    11. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
    12. //为hash类型value设置序列器
    13. redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
    14. redisTemplate.setConnectionFactory(redisConnectionFactory);
    15. return redisTemplate;
    16. }
    17. }
    1. //序列化
    2. @Test
    3. public void testSerial(){
    4. User user = new User();
    5. user.setId(1);
    6. user.setUsername("张三");
    7. user.setPassword("111");
    8. ValueOperations value = redisTemplate.opsForValue();
    9. value.set("userInfo",user);
    10. System.out.println(value.get("userInfo"));
    11. }

    操作string

    1. // 1.操作String
    2. @Test
    3. public void testString() {
    4. ValueOperations valueOperations = redisTemplate.opsForValue();
    5. // 添加一条数据
    6. valueOperations.set("username", "zhangsan");
    7. valueOperations.set("age", "18");
    8. // redis中以层级关系、目录形式存储数据
    9. valueOperations.set("user:01", "lisi");
    10. valueOperations.set("user:02", "wangwu");
    11. // 添加多条数据
    12. Map userMap = new HashMap<>();
    13. userMap.put("address", "bj");
    14. userMap.put("sex", "1");
    15. valueOperations.multiSet(userMap);
    16. // 获取一条数据
    17. Object username = valueOperations.get("username");
    18. System.out.println(username);
    19. // 获取多条数据
    20. List keys = new ArrayList<>();
    21. keys.add("username");
    22. keys.add("age");
    23. keys.add("address");
    24. keys.add("sex");
    25. List resultList = valueOperations.multiGet(keys);
    26. for (Object str : resultList) {
    27. System.out.println(str);
    28. }
    29. // 删除
    30. redisTemplate.delete("username");
    31. }
    32. 操作hash

      1. // 2.操作Hash
      2. @Test
      3. public void testHash() {
      4. HashOperations hashOperations = redisTemplate.opsForHash();
      5. /*
      6. * 添加一条数据
      7. * 参数一:redis的key
      8. * 参数二:hash的key
      9. * 参数三:hash的value
      10. */
      11. hashOperations.put("userInfo","name","lisi");
      12. // 添加多条数据
      13. Map map = new HashMap();
      14. map.put("age", "20");
      15. map.put("sex", "1");
      16. hashOperations.putAll("userInfo", map);
      17. // 获取一条数据
      18. String name = hashOperations.get("userInfo", "name");
      19. System.out.println(name);
      20. // 获取多条数据
      21. List keys = new ArrayList<>();
      22. keys.add("age");
      23. keys.add("sex");
      24. List resultlist =hashOperations.multiGet("userInfo", keys);
      25. for (String str : resultlist) {
      26. System.out.println(str);
      27. }
      28. // 获取Hash类型所有的数据
      29. Map userMap = hashOperations.entries("userInfo");
      30. for (Entry userInfo : userMap.entrySet()) {
      31. System.out.println(userInfo.getKey() + "--" + userInfo.getValue());
      32. }
      33. // 删除 用于删除hash类型数据
      34. hashOperations.delete("userInfo", "name");
      35. }

      操作list

      1. // 3.操作list
      2. @Test
      3. public void testList() {
      4. ListOperations listOperations = redisTemplate.opsForList();
      5. // 左添加(上)
      6. // listOperations.leftPush("students", "Wang Wu");
      7. // listOperations.leftPush("students", "Li Si");
      8. // 左添加(上) 把value值放到key对应列表中pivot值的左面,如果pivot值存在的话
      9. //listOperations.leftPush("students", "Wang Wu", "Li Si");
      10. // 右添加(下)
      11. // listOperations.rightPush("students", "Zhao Liu");
      12. // 获取 start起始下标 end结束下标 包含关系
      13. List students = listOperations.range("students", 0,2);
      14. for (Object stu : students) {
      15. System.out.println(stu);
      16. }
      17. // 根据下标获取
      18. Object stu = listOperations.index("students", 1);
      19. System.out.println(stu);
      20. // 获取总条数
      21. Long total = listOperations.size("students");
      22. System.out.println("总条数:" + total);
      23. // 删除单条 删除列表中存储的列表中几个出现的Li Si。
      24. listOperations.remove("students", 1, "Li Si");
      25. // 删除多条
      26. redisTemplate.delete("students");
      27. }
      28. 操作set

        1. // 4.操作set-无序
        2. @Test
        3. public void testSet() {
        4. SetOperations setOperations = redisTemplate.opsForSet();
        5. // 添加数据
        6. String[] letters = new String[]{"aaa", "bbb", "ccc", "ddd", "eee"};
        7. //setOperations.add("letters", "aaa", "bbb", "ccc", "ddd", "eee");
        8. setOperations.add("letters", letters);
        9. // 获取数据
        10. Set let = setOperations.members("letters");
        11. for (Object letter: let) {
        12. System.out.println(letter);
        13. }
        14. // 删除
        15. setOperations.remove("letters", "aaa", "bbb");
        16. }
        17. 操作sorted set

          1. // 5.操作sorted set-有序
          2. @Test
          3. public void testSortedSet() {
          4. ZSetOperations zSetOperations = redisTemplate.opsForZSet();
          5. ZSetOperations.TypedTuple objectTypedTuple1 = new DefaultTypedTuple("zhangsan", 7D);
          6. ZSetOperations.TypedTuple objectTypedTuple2 = new DefaultTypedTuple("lisi", 3D);
          7. ZSetOperations.TypedTuple objectTypedTuple3 = new DefaultTypedTuple("wangwu", 5D);
          8. ZSetOperations.TypedTuple objectTypedTuple4 = new DefaultTypedTuple("zhaoliu", 6D);
          9. ZSetOperations.TypedTuple objectTypedTuple5 = new DefaultTypedTuple("tianqi", 2D);
          10. Set> tuples = new HashSet>();
          11. tuples.add(objectTypedTuple1);
          12. tuples.add(objectTypedTuple2);
          13. tuples.add(objectTypedTuple3);
          14. tuples.add(objectTypedTuple4);
          15. tuples.add(objectTypedTuple5);
          16. // 添加数据
          17. zSetOperations.add("score", tuples);
          18. // 获取数据
          19. Set scores = zSetOperations.range("score", 0, 4);
          20. for (Object score: scores) {
          21. System.out.println(score);
          22. }
          23. // 获取总条数
          24. Long total = zSetOperations.size("score");
          25. System.out.println("总条数:" + total);
          26. // 删除
          27. zSetOperations.remove("score", "zhangsan", "lisi");
          28. }
          29. 获取所有key&删除

            1. // 获取所有key
            2. @Test
            3. public void testAllKeys() {
            4. // 当前库key的名称
            5. Set keys = redisTemplate.keys("*");
            6. for (String key: keys) {
            7. System.out.println(key);
            8. }
            9. }
            10. // 删除
            11. @Test
            12. public void testDelete() {
            13. // 删除 通用 适用于所有数据类型
            14. redisTemplate.delete("score");
            15. }

            设置key的失效时间

            1. @Test
            2. public void testEx() {
            3. ValueOperations valueOperations = redisTemplate.opsForValue();
            4. // 方法一:插入一条数据并设置失效时间
            5. valueOperations.set("code", "abcd", 180, TimeUnit.SECONDS);
            6. // 方法二:给已存在的key设置失效时间
            7. boolean flag = redisTemplate.expire("code", 180, TimeUnit.SECONDS);
            8. // 获取指定key的失效时间
            9. Long l = redisTemplate.getExpire("code");
            10. }

            SpringDataRedis整合使用哨兵机制

            application.yml

            1. spring:
            2. redis:
            3. # Redis服务器地址
            4. host: 192.168.10.100
            5. # Redis服务器端口
            6. port: 6379
            7. # Redis服务器端口
            8. password: root
            9. # Redis服务器端口
            10. database: 0
            11. # 连接超时时间
            12. timeout: 10000ms
            13. lettuce:
            14. pool:
            15. # 最大连接数,默认8
            16. max-active: 1024
            17. # 最大连接阻塞等待时间,单位毫秒,默认-1ms
            18. max-wait: 10000ms
            19. # 最大空闲连接,默认8
            20. max-idle: 200
            21. # 最小空闲连接,默认0
            22. min-idle: 5
            23. #哨兵模式
            24. sentinel:
            25. #主节点名称
            26. master: mymaster
            27. #节点
            28. nodes: 192.168.10.100:26379,192.168.10.100:26380,192.168.10.100:26381

          30. 相关阅读:
            【性能优化】单一接口优化过程全记录(主要涉及Redis)
            第5章 多媒体知识
            埃隆·马斯克旗下xAI推出PromptIDE工具,加速提示工程和可解释性研究
            浅谈性能测试稳定性 Constant Throughput Timer(常数吞吐量定时器)
            深入了解网络流量清洗--使用免费的雷池社区版进行防护
            如何在 PyTorch 中冻结模型权重以进行迁移学习:分步教程
            LIS系统 检验系统源码 检验科LIS系统源码
            Redis
            配音工具大jiemi|盘点市面上那些超好用的配音神器,短视频作者看过来
            Multiscale Vision Transformers 论文详解
          31. 原文地址:https://blog.csdn.net/m0_58719994/article/details/132395469