redis 基础概述与使用

2023-11-19

一. redis 概述

  1. redis 基于内存的单线程非关系型数据库,每秒支持十万并发
  2. 架构模式: 单机版, 主从复制,哨兵模式,分片集群
  3. 使用场景: 热点数据缓存,生成令牌,网站计数器,通过redis实现接口幂,存储验证码,分布式锁,生成分布式ID
  4. redis集群使用哈希槽算法进行负载,redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置在哪个槽,集群的每个节点负责一部分hash槽,思考为什么哈希槽数量是16384(2 ^14)呢,CRC16算法产生的hash值是16bit,该算法可以产生2 ^16约等于65536,换句话来说值是分布在0-65535之间,那在mod运算是为什么不是要mod65535而选择mod16384,

防止发送心跳包过大,假设槽数未65536,发送心跳的消息头为65535/8/1024=8k,因为集群情况下redis每秒都会发送一个心跳包,这样就太大了
集群节点越多,心跳包消息体内携带的数据越多,如果超过了1000也会导致网络拥堵,对于节点在1000内的redis cluster集群,16384个槽位就够了,没必要拓展到65535
槽位越小,节点少的情况下,压缩比高,更容易传输,redis主节点的配置信息中他所负责的哈希槽是通过bitmap的形式保存的,在传输过程中会对bitmap进行压缩,如果bitmap的填充率 slots/节点数 很高,bitmap的压缩率就很低,如果节点数少,哈希槽数量很多,bitmap的压缩率就会很低

redis 主从同步执行流程

在集群环境中多个redis 分为master主库与Salve从库,当Salve启动后会连接到master主库,并发送一个sync命令,master接收到该命令后台启动一个进程,收集接收到的操作数据指令缓存为快照文件,当缓存完毕后,将这个文件发送给所有连接到该master的Salve从库,Salve将文件接收保存到磁盘上,然后加载到内存中,后续master主库接收到的修改数据指令都会通过这个后台进程发送给Salve

redis 淘汰策略

在这里插入图片描述

缓存常见问题

在这里插入图片描述

KEYS指令与SCAN指令

假设需要在reid中获取某个key的数据,或者匹配获取某些key的数据,需要考虑redis中数据大小的问题,如果数据过大,由于redis是基于内存的,使用keys指令去查询会读取所有数据进行匹配会造成服务器卡顿现象,推荐使用SCAK指令

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RedisHelper {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    /**
     * scan 实现
     * @param pattern   表达式
     * @param consumer  对迭代到的key进行操作
     */
    public void scan(String pattern, Consumer<byte[]> consumer) {
        this.stringRedisTemplate.execute((RedisConnection connection) -> {
            try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build())) {
                cursor.forEachRemaining(consumer);
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 获取符合条件的key
     * @param pattern   表达式
     * @return
     */
    public List<String> keys(String pattern) {
        List<String> keys = new ArrayList<>();
        this.scan(pattern, item -> {
            //符合条件的key
            String key = new String(item,StandardCharsets.UTF_8);
            keys.add(key);
        });
        return keys;
    }
}


SpringBoot 整合 redis

  1. 引入 resid 依赖
	<!-- SpringBootRedis支持 -->
	<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>
	<!--如果使用jedis操作redis数据的话添加这个依赖 -->
	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	    <version>2.9.0</version>
	</dependency>
  1. yml 文件中配置redis连接
    单机版:
spring:
  redis:
	#设置数据存放在redis的哪个库中,此处为默认的0库
    database: 0
    host: 132.232.44.194
    port: 6379
    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000

集群版

spring:
  redis:
    database: 0
#集群版本不需这些设置(否则会走单机连接)
#    host: 132.232.44.194
#    port: 6379
#    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000
    cluster:
      nodes:
        - 192.168.212.149:9001
        - 192.168.212.149:9002
        - 192.168.212.149:9003
        - 192.168.212.149:9004
        - 192.168.212.149:9005
        - 192.168.212.149:9006
  1. 代码中使用 StringRedisTemplate 或 RedisTemplate 操作redis
	@Autowired
    private StringRedisTemplate stringRedisTemplate;
	//StringRedisTemplate
	//StringRedisTemplate.opsForValue().* //操作String字符串类型
	//StringRedisTemplate.delete(key/collection) //根据key/keys删除
	//StringRedisTemplate.opsForList().*  //操作List类型
	//StringRedisTemplate.opsForHash().*  //操作Hash类型
	//StringRedisTemplate.opsForSet().*  //操作set类型
	//StringRedisTemplate.opsForZSet().*  //操作有序set


	 @Autowired
    private RedisTemplate<String, String> redisTemplate;
	/* RedisTemplate对象,可以理解为一个map集合对象,通过这个对象操作redis中的各种类型数据,
    * redisTemplate.opsForValue() -> ValueOperations<String, Object>;// 操作字符串
    * redisTemplate.opsForHash() -> HashOperations<String, String, String>;// 操作 hash
    * redisTemplate.opsForList() -> ListOperations<String, Object>;// 操作 list
    * redisTemplate.opsForSet() -> SetOperations<String, Object>;// 操作 set
    * redisTemplate.opsForZSet() -> ZSetOperations<String, Object>;// 操作 SortedSet */

StringRedisTemplate 与 RedisTemplate

  • StringRedisTemplate 继承了 RedisTemplate 但是连着操作的数据不是共通的,StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据
  • RedisTemplate 使用JdkSerializationRedisSerializer 序列化机制,存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
  • StringRedisTemplate使用的是StringRedisSerializer
  • 推荐: 存储数据是字符串类型的时候,就算存储对象也是将对象转换为JSON串,使用StringRedisTemplate即可。如果存储的数据是复杂的对象类型,取出的时候又不想做数据转换,直接从Redis里面取出一个对象,使用RedisTemplate
  • RedisTemplate 中存取数据都是字节数组。当redis中存入的数据是可读形式而非字节数组时,使用redisTemplate取值的时候会无法获取导出数据,获得的值为null。可以使用 StringRedisTemplate 试试
    在这里插入图片描述

redis 支持事物控制与锁

  1. 以代码举例(在实际项目中可以通过拦截器,操作redis的事物)
    在这里插入图片描述
  2. redis支持锁,在使用锁
    在这里插入图片描述

redis 设置key失效

调用expire(),方法,指定哪个key,指定存活时间,时间单位

	//设置redis中指定key的失效时间(毫秒)
    public boolean setTime(String key, Long time){
        if(null != key || time !=0){
           return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        }else {
            return false;
        }
    }

redis 指定库

redis 默认有16个库,从0开始,默认使用0库,可以通过配置修改库的个数,可以手动指定选择哪个库

	@Test
    public void test2() {
        //1.通过jedisPool获取连接
        Jedis conn = jedisPool.getResource();
        //2.通过stringRedisTemplate获取连接
        JedisConnectionFactory factory = (JedisConnectionFactory) stringRedisTemplate.getConnectionFactory();
        //3.通过redisTemplate获取连接
        JedisConnectionFactory factory2 = (JedisConnectionFactory) redisTemplate.getConnectionFactory();
        
        //指定使用redis中的哪个库(默认16个从0开始)
        factory2.setDatabase(1);
    }

redis 的 setnx() 与 getset()

  • setnx() 向redis中存储一个key-value,如果redis库中已存在,当前存储失败返回0,如果不存在,存储成功,返回1
  • get(key) 获取key的值,如果存在,则返回;如果不存在,则返回nil;
  • getset()命令:这个命令主要有两个参数 getset(key, newValue)。该方法是原子的,对key设置newValue这个值,并且返回key原来的旧值。
 	@Autowired
    public Jedis jedis;

    @Autowired
    public JedisPool jedisPool;

    @Test
    public void test() {
        //1.建立redis连接
        Jedis conn = jedisPool.getResource();

        long currentTime = System.currentTimeMillis();//当前时
        String lockTimeDuration = String.valueOf(currentTime);
        //将当前时间作为value 存储到redis中,存储成功返回1,否则返回0
        Long i = jedis.setnx("keys", lockTimeDuration);

    }

封装操作 redis 数据的工具类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.Set;
import java.util.concurrent.TimeUnit;
//封装向redis中存储获取数据的方法
//将工具类注入到容器中
@Component 
public class RedisUtils {
    //通过StringRedisTemplate对象操作redis,向redis中存储数据
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    //公用的存储方法,方法中判断数据类型,根据数据类型
    //向redis中存储,并设置有效时间
    public void set(String key, Object object, Long time) {
        // 存放String 类型
        if (object instanceof String) {
            setString(key, object);
        }
        // 存放 set类型
        if (object instanceof Set) {
            setSet(key, object);
        }
        // 设置redis中指定key的有效时间
        stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
    }
    //向redis中存储String类型数据
    public void setString(String key, Object object) {
        // 如果是String 类型
        String value = (String) object;
        stringRedisTemplate.opsForValue().set(key, value);
    }
    //向redis中存储set类型数据
    public void setSet(String key, Object object) {
        Set<String> value = (Set<String>) object;
        for (String oj : value) {
            stringRedisTemplate.opsForSet().add(key, oj);
        }
    }
    //通过key获取redis中String数据
    public String getString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
    
    //设置redis中指定key的失效时间(毫秒)
    public boolean setTime(String key, Long time){
        if(null != key || time !=0){
           return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        }else {
            return false;
        }
    }

}

二. java 操作 redis 各种类型数据示例

注意点: 此处使用 StringRedisTemplate 操作redis数据,存储与获取都是字符串类型,如果存储对象需要先将对象转换为JSON串,然后进行存储,如果存储与获取时不进行类型转换,例如对象就直接存储对象,获取时直接获取为该对象类型不进行转换则使用 RedisTemplate,该对象向redis中存储的是字节数组
通过命令操作

  1. 操作 String 类型,二进制安全的。意思是可以包含任何数据。比如jpg图片或者序列化的对象 ,最基本的数据类型,一个键最大能存储512MB。
	@Test
    public void test01() {

        //创建操作redis中String类型数据的对象 ValueOperations
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

        //1.添加数据set()添加数据(如果添加这个数据在库中已经存在就变为了修改)
        valueOperations.set("username", "mingming");

        /*2.以层级关系目录形式添加数据*/
        valueOperations.set("user:01", "wwww");
        valueOperations.set("user:01", "cccc");

        //3.添加多条数据multiSet()
        //map中的key为redis的key,map中的值为redis的值
        Map<String,String> stringMap=new HashMap<>();
        stringMap.put("数据1","值1");
        stringMap.put("数据2","值2");
        stringMap.put("数据3","值3");

        valueOperations.multiSet(stringMap);

        //4.查询
        Object username=valueOperations.get("username");

        //5.查询多条,以集合中的数据为key进行查询
        List<String> keyStr=new ArrayList<>();
        keyStr.add("数据1");
        keyStr.add("数据2");
        keyStr.add("数据3");
        List<String> valL=valueOperations.multiGet(keyStr);

        //6.删除指定key数据
        stringRedisTemplate.delete("username");

        //6.模糊匹配
        Set<String> keys = stringRedisTemplate.keys("noteUserListenedPoi:" + "*");

        //7.批量删除
        stringRedisTemplate.delete(keys);

    }
  1. 操作 Hash 散列类型,是一个string类型的field和value的映射表,hash特别适合用于存储对象
	@Test
    public void test02(){
        //1.创建操作 Hash类型数据的对象
        HashOperations<String ,String,String> hashOperations = stringRedisTemplate.opsForHash();

        //2.添加数据,第一个为redis的key,第二个为当前数据的field,点三个为值
        hashOperations.put("userInfo","name","gggg");

        //3.添加多条 map类型
        Map<String ,String> map=new HashMap<>();
        map.put("age","18");
        map.put("sex","1");

        //userInfo为redis的key,map中的键为field,值为value
        hashOperations.putAll("userInfo", map);

        //4.根据key,与field查询redis中的Hash类型数据
        String name=hashOperations.get("userInfo","name");

        //5.查询多条,创建查询的field集合
        List<String> keyS=new ArrayList<>();
        keyS.add("age");
        keyS.add("sex");

        //查询多条返回List集合
        List<String> hashValL=hashOperations.multiGet("userInfo",keyS);
        //查询多条返回Map集合
        Map<String,String>hashValue= hashOperations.entries("userInfo");


       //6.删除
        hashOperations.delete("userInfo","name");
    }
  1. 操作 List 列表类型,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边),通过list进行指定下标的查询,可以做到简单分页,
	@Test
    public void test03(){
        //1.创建操作List类型数据的对象
        ListOperations<String ,String> listOperations= stringRedisTemplate.opsForList();

        //2.左上添加,第一个添加的会被后一个添加的挤压到下面
        listOperations.leftPush("student","liuliuliu");
        //3.右下追加,第一个添加的会被后一个添加的挤到上面
        listOperations.rightPush("students", "Zhao Liu");

        //4.查询,根据key与下标获取指定位置的数据,左闭右闭,两边包含,返回一个List
        List<String> students = listOperations.range("student", 0,2);

        //5.根据key与指定下标获取单个数据
        String stu = listOperations.index("student", 1);

        //6.获取当前List类型数据的长度
        Long total = listOperations.size("student");

        //7.删除List类型数据,key为student的,value值为"Li",在List中第二次出现的,
        listOperations.remove("student", 2, "Li");

        // 删除多条,有左删除一条,右删除一条等
        stringRedisTemplate.delete("student");
        //8.从左边开始获取并删除
        String srt1 = listOperations.leftPop("student");
        //9.右边开始获取并删除
        String str2= listOperations.rightPop("student");
    }
  1. 操作 Set 无序集合类型,不允许重复的成员,是通过哈希表实现的,所有添加,删除,查找的复杂度都是O(1),优点:天然去重,可以取交集,差集等
	@Test
    public void testSet() {
        //1.创建操作Set类型数据的对象
        SetOperations<String, String> setOperations = stringRedisTemplate.opsForSet();

        //模拟数据
        String[] letters = new String[]{"aaa", "bbb", "ccc", "ddd", "eee"};

        //1.批量添加
        setOperations.add("letters", letters);
        //2.批量获取
        Set<String> let = setOperations.members("letters");

        //3.删除redis中key为letters的set类型数据中的aaa,bbb数据*
        setOperations.remove("letters", "aaa", "bbb");
    }
  1. 操作 SortedSet 有序集合,不允许重复的成员,每个元素都会关联一个double类型的分数,通过分数来为集合中的成员进行从小到大的排序,zset的成员是唯一的,但分数(score)却可以重复
	@Test
    public void testSortedSet() {
        //1.创建操作sorted set数据的对象
        ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();

        //2.向redis中添加 sorted set 类型数据,需要将数据封装到 ZSetOperations 中
        //传递一个dubbo值指定该数据在sortedSet集合中的排序位置,
        ZSetOperations.TypedTuple<String> objectTypedTuple1 = new DefaultTypedTuple<String>("zhangsan", 99D);
        ZSetOperations.TypedTuple<String> objectTypedTuple2 = new DefaultTypedTuple<String>("lisi", 96D);
        ZSetOperations.TypedTuple<String> objectTypedTuple3 = new DefaultTypedTuple<String>("wangwu", 92D);
        ZSetOperations.TypedTuple<String> objectTypedTuple4 = new DefaultTypedTuple<String>("zhaoliu", 100D);
        ZSetOperations.TypedTuple<String> objectTypedTuple5 = new DefaultTypedTuple<String>("tianqi", 95D);

        Set<ZSetOperations.TypedTuple<String>> tuples = new HashSet<ZSetOperations.TypedTuple<String>>();
        tuples.add(objectTypedTuple1);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        tuples.add(objectTypedTuple4);
        tuples.add(objectTypedTuple5);

        //添加数据
        zSetOperations.add("score", tuples);
        //获取多条数据,左闭右闭,返回Set集合
        Set<String> scores = zSetOperations.range("score", 0, 4);

        //获取长度
        Long total = zSetOperations.size("score");

        //删除redis的key为score,value值为 zhangsan和lisi的两个数据
        zSetOperations.remove("score", "zhangsan", "lisi");
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redis 基础概述与使用 的相关文章

随机推荐

  • 【Git系列】Git配置SSH免密登录

    Git配置SSH免密登录 1 设置用户名和邮箱 2 生成密钥 3 远程仓库配置密钥 2 免密登录 其他系列 Git最详细的体系化教程 在以上push操作过程中 我们第一次push时 是需要进行录入用户名和密码的 比较麻烦 而且我们使用的是h
  • 刷脸支付技术更多的是想要助力数字化运营

    刷脸支付是在原有的收银系统基础上增加一种收款方式 不影响收银系统 收银更有效 支付更便捷 体验感更好 节省时间成本 资金更安全 支付宝 微信官方为推广刷脸支付 两大官方投入巨额资金普及刷脸支付 日常生活中可避免忘记带手机 手机没电 通话中
  • C++17中utf-8 character literal的使用

    一个形如42的值被称作字面值常量 literal 这样的值一望而知 每个字面值常量都对应一种数据类型 字面值常量的形式和值决定了它的数据类型 由单引号括起来的一个字符称为char型字面值 双引号括起来的零个或多个字符则构成字符串型字面值 字
  • 两万字带你认识黑客在kali中使用的工具

    目录 前言 一 信息收集工具 二 脆弱性分析工具 三 漏洞利用工具 四 嗅探与欺骗工具 五 密码攻击工具 六 权限提升工具 七 Web应用工具 八 无线攻击工具 九 硬件黑客工具 十 维持访问工具 十一 取证工具 十二 逆向工程工具 十三
  • Linux动态链接库.so文件的创建与使用

    1 介绍 使用GNU的工具我们如何在Linux下创建自己的程序函数库 一个 程序函数库 简单的说就是一个文件包含了一些编译好的代码和数据 这些编译好的代码和数据可以在事后供其他的程序使用 程序函数库可以使整个程序更加模块化 更容易重新编译
  • Qt 简述QSettings配置文件保存使用数据

    前言 在开发中 需要将一些信息保存到本地 以便下次程序启动时使用 文件读写 数据库都是可以的 但是Qt提供了QSettings接口方法 将需要的信息写入或者读取配置文件中 其方法类似键值对 QSettings可以存储一系列设置 每个设置包括
  • 探讨Socks5代理IP在跨境电商与网络游戏中的网络安全应用

    随着全球互联网的迅猛发展 跨境电商和在线游戏成为了跨国公司和游戏开发商的新战场 然而 与此同时 网络安全问题也日益突出 本文将探讨如何利用Socks5代理IP来增强跨境电商和网络游戏的网络安全 保障数据传输的隐私和安全性 第一部分 Sock
  • 五分钟,带你彻底掌握 MyBatis 缓存的工作原理

    点击上方 芋道源码 选择 设为星标 管她前浪 还是后浪 能浪的浪 才是好浪 每天 8 55 更新文章 每天掉亿点点头发 源码精品专栏 原创 Java 2020 超神之路 很肝 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络
  • Quartz框架多个trigger任务执行出现漏执行的问题分析

    一 问题描述 使用Quartz配置定时任务 配置了超过10个定时任务 这些定时任务配置的触发时间都是5分钟执行一次 实际运行时 发现总有几个定时任务不能执行到 二 示例程序 1 简单介绍 采用spring quartz整合方案实现定时任务
  • docker菜鸟入门

    菜鸟入门Docker 说明 一 什么是Docker 1 虚拟机和Linux容器 二 Docker用途 三 Docker安装 1 设置仓库 2 安装 Docker Engine Community 3 验证安装成功 四 Docker启动与停止
  • VoVNet论文解读

    摘要 1 介绍 2 高效网络设计的影响因素 2 1 内存访问代价 2 2 GPU计算效率 3 建议的方法 3 1 重新思考密集连接 3 2 One Shot Aggregation 3 3 构建 VoVNet 网络 4 实验 5 代码解读
  • 01背包(c++版)

    dp i j 表示从下标为 0 i 的物品里任意取 放进容量为j的背包 价值总和最大是多少 void test 2 wei bag problem1 vector
  • 上班族为何需要做副业?如何靠副业月入过万?

    网上统计某某城市平均工资8千以上 诶 一看自己3 4千 其实现在每个背井离乡在外上班的打工人都挺难的 城市很繁华 工资很现实 在工厂打螺丝的更是苦逼的生活 被资本家无情的压榨 在豪华的写字楼上班的白领 也过着996的生活 甚至是007的日子
  • 操作系统复习题

    一 选择题 在计算机系统中 操作系统是 核心系统软件 网络操作系统 不是基本的操作系统 实时性 不是分时系统的基本特征 关于操作系统的叙述 能方便用户编程的程序 是不正确的 操作系统的发展过程是 设备驱动程序组成的原始操作系统 管理程序 操
  • Response 456错误

    今天使用某share拉取股票数据时 遇到了Response 456错误 然而在网上查也没有查到 感觉是是较为少见的错误 http response code HTTP状态码对照表 t 332741160的专栏 CSDN博客 后来发现这个错误
  • 【Bun1.0】使用 Bun.js 构建快速、可靠和安全的 JavaScript 应用程序

    bun js Bun 是一个现代的JavaScript运行环境 如Node Deno 主要特性如下 启动速度快 更高的性能 完整的工具 打包器 转码器 包管理 官网 https bun sh 优点 与传统的 Node js 不同 Bun j
  • python数据分析与挖掘实战 -第四章数据预处理

    数据清洗 目的 删除原始数据集中的无关数据 重复数据 平滑噪声数据 筛选掉与挖掘主题无关的数据 处理缺失值 异常值等 缺失值处理方法 删除记录 数据插补和不处理 拉格朗日插值法 对于平面上已知的N个点 无两点在一条直线上 可以找到一个N 1
  • 解决vue中样式不起作用:样式穿透/深度选择器(/deep/)

    原因1 组件内部使用组件 添加了scoped属性 原因2 动态引入html 也添加了scoped属性 原因3 非以上两种 一 添加了scoped属性 Vue中的scoped属性的效果主要是通过PostCss实现的 以下是转译前的代码
  • 关于数据结构中的叶节点和二度节点的关系(通俗的理解)。

    简单记录一下自己的一些地方和对于这个问题我的一些见解 有说的不好的地方欢迎指正 这里只给出一种理解 另一种利用公式进行理解的 我就不写了 因为csdn里面太多了 先说结论 叶节点的数目 二度节点 1 首先来看这张图 可以看到这个图大体是包含
  • redis 基础概述与使用

    目录 一 redis 概述 redis 主从同步执行流程 redis 淘汰策略 缓存常见问题 KEYS指令与SCAN指令 SpringBoot 整合 redis StringRedisTemplate 与 RedisTemplate red