Redis

发布于:2025-06-20 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

Redis简介      

Redis安装及配置

Redis持久化机制

RDB 持久化机制

AOF 持久化机制

RDB 、AOF 比较

Redis架构模式

主从复制模式

哨兵模式

集群模式

3种模式比较

Redis与SpringBoot集成

Redis 穿透&雪崩


Redis简介      

        Redis是一个开源的高性能键值存储数据库,它提供了多种数据结构来存储数据。它能提供海量的数据存储访问、数据存储在内存,读取更快。        

        从分布式、缓存数据持久化的维度对比其他缓存框架,见下图:

对比维度 Redis Ehcache Memcache
集群、分布式 支持 不支持 支持
数据持久化 支持 支持 不支持

Redis安装及配置

        本文演示环境:1、系统:Ubuntu20.04;2、redis版本:5.0.7,安装步骤如下:

        1、sudo apt install redis-server,直接安装

        2、查看版本redis 版本

        3、配置redis,修改/etc/redis/redis.conf文件

         配置后台启动:

        指定工作目录:

        启动redis-server:  sudo systemctl start redis-server.service

Redis持久化机制

        Redis 是内存数据库,数据默认存储在内存中,一旦服务器宕机或重启,内存中的数据将会丢失。为了解决这个问题,Redis 提供了两种持久化机制:RDB(Redis Database)和 AOF(Append-Only File)。

RDB 持久化机制

        RDB 是通过生成数据快照(Snapshot)来保存数据库的当前状态。Redis 可以根据配置文件中设置的规则,自动在满足条件时生成RDB 文件。下方示例中修改生成快照规则,60秒内10个key改变就生成数据快照。

        修改redis.conf文件,通过redis-cli快速设置超过10个key,观察数据快照,发现dump.rdb文件被修改了。

AOF 持久化机制

        AOF 持久化机制通过记录 Redis 服务器执行的每一条写命令来保存数据。AOF 文件是一个文本文件,记录了所有修改数据库状态的命令。当 Redis 重启时,可以通过重新执行 AOF 文件中的命令来恢复数据。下方示例演示AOF持久化,修改redis.conf文件并重启redis sever服务(sudo systemctl restart redis-server.service ),设置key,观察appendonly.aof文件

        通过redis-cli设置name=zhangsan后,appendonly.aof文件中追加了以上数据。

RDB 、AOF 比较

特性 RDB AOF
持久化方式 生成数据快照 记录写命令
文件格式 二进制文件 文本文件
​数据安全性 可能会丢失最后一次快照后的数据 最多丢失一秒钟的数据
文件体积 较小 较大
恢复速度 较快 较慢
性能影响 较小(后台生成快照) 较大(实时写入)
适用场景 数据备份、恢复速度要求高的场景 数据安全性要求高的场景

Redis架构模式

主从复制模式

        主从复制模式,就是系统中只有1个节点是主节点master,其他节点都是从节点slave,客户端写入请求会发送到主节点,然后主节点同步数据到从节点,读取数据到从节点获取,架构图如下:

        修改redis.conf文件实现主从复制模式,在从节点主机的redis.conf文件中,加上:

replicaof masterIP master端口

哨兵模式

        在哨兵模式下,哨兵节点会定期检查主节点和从节点的运行状态。如果发现主节点发生故障,哨兵节点会在从节点中选举出一个新的主节点,并通知其他的从节点和哨兵节点。  示意图如下:

        上图中有3个节点,1个master,2个slave,分别修改对应节点的sentinel.conf文件实现哨兵模式,然后启动哨兵:redis-sentinel sentinel.conf,启动后节点1是master,2和3是slave,当节点1停止服务后,sentinel会自动选举出一个slave节点充当master。

bind 127.0.0.1
protected-mode no  #关闭保护模式
port 26379 #哨兵端口
#哨兵监控主机(127.0.0.1 6379),数字2表示2个哨兵认为主机挂掉后,需要做故障转移,选择其他salve成为主机。
sentinel monitor mymaster 127.0.0.1 6379 2 

集群模式

        Redis集群模式,可以支持高并发同时容纳海量数据,Redis 集群通过数据分片sharding来进行数据的共享,同时提供复制和故障转移的功能。Redis 通过集群分片的形式来保存数据,整个集群数据库被分为 16384 个 slot。集群模式示意图如下:

        上图中实现了3主3从的集群模式,在每个节点修改redis.conf文件:

cluster-enabled yes #打开集群模式
cluster-config-file node-6379.conf

        构建3主3从集群,通过redis-cli --cluster实现:

redis​-cli --cluster create host1:port1 ​host2:port2 host3:port3 host4:port4 ​host5:port5 host6:port6 --cluster-replicas 1

3种模式比较

比较项 主从模式  哨兵模式 集群模式
优点 读写分离(读请求走slave节点,写请求走master节点) 故障自动转移(通过哨兵自动发现redis master故障,然后选择其他slave充当master) 扩张性好(通过添加节点轻松扩展集群的存储容量和处理能力)、高可用性(集群中的每个节点都有自己的复制节点)
缺点 主节点故障会导致系统无法写操作 依赖于哨兵集群,哨兵出现故障后,Redis故障无法自动转移 节点多,数据的管理和维护相对复杂

Redis与SpringBoot集成

        集成步骤如下:

        1、添加项目对redis依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

        2、配置redis信息【application.yml】

        单节点:

server:
  port: 8080
spring:
  redis:
    host: 192.168.142.130
    database: 0
    port: 6379

        Redis哨兵模式:

server:
  port: 8080
spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 192.168.142.190:26379,192.168.142.191:26379,192.168.142.192:26379
    database: 0

        Redis集群模式:

server:
  port: 8080
spring:
  redis:
    cluster:
      nodes: 192.168.142.130:6379,192.168.142.131:6379,192.168.142.132:6379,192.168.142.133:6379,192.168.142.134:6379,192.168.142.135:6379

        3、编写测试方法,java操作redis核心的操作类是 RedisTemplate,下方示例演示设置缓存和查询缓存。

package com.gingko.redis.controller;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@RequestMapping("redis")
public class RedisController {

    @Resource
    private RedisTemplate redisTemplate;

    @GetMapping("/set")
    public String set(String key,String value) {
        redisTemplate.opsForValue().set(key,value);
        return "ok";
    }

    @GetMapping("/get")
    public Object get(String key) {
        Object result = redisTemplate.opsForValue().get(key);
        return result;
    }
}

        4、测试,测试结果符合预期

Redis 穿透&雪崩

        Redis 穿透问题(Cache Penetration)指的是当缓存中不存在的某些数据时,黑客可以利用这一点,通过构造一系列不存在的数据键来访问数据库,从而导致数据库压力过大,甚至崩溃。模拟代码如下:     

package com.gingko.redis.service;
import com.gingko.redis.entity.ProductInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class ProductInfoService {

    @Resource
    private RedisTemplate redisTemplate;

    static List<ProductInfo> productInfoList;

    static {
        productInfoList = new ArrayList<>();
        ProductInfo p1 = new ProductInfo(1,"小米手机","");
        ProductInfo p2 = new ProductInfo(2,"苹果手机","");
        ProductInfo p3 = new ProductInfo(3,"华为手机","");
        productInfoList.add(p1);
        productInfoList.add(p2);
        productInfoList.add(p3);
    }

    public String getById(int id) {
        String productName = (String)redisTemplate.opsForValue().get(id);
        if(productName == null) {
            log.info("从数据库获取产品信息...");
            productInfoList.stream().forEach(productInfo -> {
                if(productInfo.getId() == id) {
                    //数据库找到
                    redisTemplate.opsForValue().set(id,productInfo.getName());
                }
            });
        }
        return productName;
    }
}

        从上述的示意代码看出,假设模拟的id不在缓存中,数据库中也不存在,如果大量模拟请求:http://localhost:8080/redis/getProduct?id=9999 ,请求会穿透缓存直接打到数据库中,造成数据库压力增大。每次请求,后台都会请数据库发请求:

        解决办法可以使用Bloom Filter,简易的方法是把空的结果也缓存起来,无论数据库中是否查到结果,都直接进入缓存,下次发送请求时,就不会进入到数据库请求中。

        缓存雪崩:Redis中缓存的数据大面积同时失效,或者Redis宕机,从而会导致大量请求直接到数据库,压垮数据库。预防的方案有:1、设置某些缓存数据永不过期; 2、将key的过期时间错开(比如按照一定的过期时间基数+-随机数) 3、实现多缓存方案,比如redis+memcache一起实现缓存。  


网站公告

今日签到

点亮在社区的每一天
去签到