• redis的基本概念和常见问题的解决!


    一、什么是redis 

    Redis是一个NoSQL(非关系型数据库)数据库之一,是一个用C语言开发的一个开源的高性能键值对(key-value)数据库或者说是一个缓存键值对数据库 ,用作数据库、缓存、消息中间件等。它支持多种数据结构,包括字符串、哈希表、列表、集合、有序集合等,并且支持丰富的操作命令,如查找、插入、删除等。 

    (1)从Redis缓存中获取数据,如果存在数据,直接返回值。

    (2)如果不存在,执行数据库的查询方法

    (3)将数据库中的值放入缓存,并返回值

    二、redis的优点

    1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) ;
    2. 支持丰富数据类型,支持string,list,set,sorted set,hash;
    3. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行 
    4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除。

    三、redis的数据结构

    五种数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)
    • String:可以是字符串、整数或者浮点数,字符串最大支持512MB。对整个字符串或者字符串的其中一部分执行操作;对象和浮点数执行自增(increment)或者自减(decrement)     (使用场景:缓存数据,简单计数,定期过时)
    • List:有序的字符串列表,可以当做栈、队列或者阻塞队列使用。读取单个或者多个元素;根据值来查找或者移除元素。                  (使用场景:用户排队,有序消息)
    • Set:无序的字符串集合,添加、获取、移除单个元素;检查一个元素是否存在于某个集合中;计算交集、并集、差集;从集合里随机获取元素。    (使用场景:去重,交集,并集,差集,获取随机数)
    • Hash:包含键值对的无序散列表。添加、获取、移除单个键值对;获取所有键值对。      (使用场景:同一资源的不同属性)
    • Zset:字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定,添加、获取、删除单个元素;根据分值范围(range)或者成员来获取元素。       (使用场景:排行榜,分数)

    四、Redis的持久化功能

    Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘上,一旦服务器退出,数据库状态约会消失。所以,Redis提供了持久化功能。两种方式:

    • RDB方式:在指定的时间间隔内将内存中的数据集快照写入磁盘,它恢复时是将快照文件直接读到内存里。
    • AOF方式:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令,达到恢复数据的目的。

    五、key过期后的回收(删除策略

    • 定时删除在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。
    • 惰性删除放任过期键不管,每次从键空间中获取键时,检查该键是否过期,如果过期,就删除该键,如果没有过期,就返回该键。
    • 定期删除每隔一段时间,程序对数据库进行一次检查,删除里面的过期键,至于要删除哪些数据库的哪些过期键,则由算法决定。

    其中定时删除和定期删除为主动删除策略,惰性删除为被动删除策略

    六、逐出算法

    Redis使用内存存储数据,在执行每个命令前会调用freeMenoryNeeded()方法检测内存是否充足,如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据作为当前指令清理存储空间。

    检查易失数据(可能会过去的数据)

    • volatile-lru:挑选最近最少使用的数据淘汰
    • volatile-lfu:挑选最近使用次数最少的数据淘汰
    • volatile-ttl:挑选将要过期的数据淘汰
    • volatile-random:任意选择数据淘汰

    检查全库数据

    • allkeys-lru:挑选最近最少使用的数据淘汰
    • allkeys-lfu:挑选最近使用次数最少的数据淘汰
    • allkeys-random:任意选择数据淘汰

    放弃数据驱逐

    • no-enviction:禁止驱逐数据

    七、redis常见问题的解决

    (1)缓存预热:

    就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据

    问题: 

    • 请求数量较大
    • 数据吞吐量较大
    • 数据同步操作频率较高

    解决方案:

    • 统计数据访问记录
    • 统计频率较高的热点数据 

    (2)缓存雪崩: 

    缓存雪崩是指缓存同一时间大面积的失效,所以,所有的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉

    解决方案:

    • 给不同的key的TTL 添加随机值
    • 利用redis集群提高服务的可用性
    • 给缓存业务添加降级限流策略
    • 给业务添加多级缓存

    (3)缓存击穿:

    是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

    解决方案:

    • 互斥锁:用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
    • 逻辑过期方案 :用户查询某个热门产品信息,如果缓存未命中(即信息为空),则直接返回空,不去查询数据库。如果缓存信息命中,则判断是否逻辑过期,未过期返回缓存信息,过期则重建缓存,尝试获得互斥锁,获取失败则直接返回已过期缓存数据,获取成功则开启独立线程去重构缓存然后直接返回旧的缓存信息,重构完成之后就释放互斥锁。

      (只要命中了缓存,无论是否过期,是否获得锁看,都返回同一个缓存信息。)

    (4)缓存穿透:

    是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

    解决方案:

    • 缓存空对象:请求的数据即使不存在也存进redis内存中 (简单易维护)
    • 布隆过滤:将数据库中所有的查询条件,放入布隆过滤器中,当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查;如果判断请求查询不存在,直接丢弃。

    八、Redis的模板类

    Redis的模板类是一种封装了常用 Redis 操作的类,它可以简化 Redis 操作的代码,并提高代码的可读性。通常情况下,使用 Redis 的模板类可以避免在代码中直接使用 Redis 命令,而是使用预定义的方法。(redis提供了两种模板类)

    RedisTemplate模板类:存时先将数据先序列化成字节数组再存入Redis。

    StringRedisTemplate模板类(继承自RedisTemplate):存时先将数据先序列化成字符串再存入Redis。

    两者的区别:

    (1)两者数据各自存,各自取,数据不互通

    • RedisTemplate存入数据后,key与value在Redis中均变为了字节数组。那么,如果使用StringRedisTemplate以相同的key去Redis中查询,会查询不到该key,则会报null。
    • StringRedisTemplate存入数据后,key与value在Redis中均为可读数据。那么,如果使用RedisTemplate以相同key去Redus中查询,key变为了字节数组的形式,查询不到该字节数组形式的key,则会报null。

    (2)序列化策略不同

    • RedisTemplate采用JDK的序列化策略
    • StringRedisTemplate采用String的序列化策略

     八、Redis的应用场景

    1. 缓存 :作为Key-Value形态的内存数据库,Redis 最先会被想到的应用场景便是作为数据缓存。而使用 Redis 缓存数据非常简单,只需要通过string类型将序列化后的对象存起来即可。
    2. 数据共享:数据共享分布式String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享
    3.  计数器:在 Redis 的数据结构中,stringhashsorted set都提供了incr方法用于原子性的自增操作。
    4. 时间轴:list作为双向链表,不光可以作为队列使用。如果将它用作栈便可以成为一个公用的时间轴。当用户发完微博后,都通过lpush将它存放在一个 key 为LATEST_WEIBOlist中,之后便可以通过lrange取出当前最新的微博。
    5. 抽奖:利用set结构的无序性,通过 Spop( Redis Spop 命令用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。 ) 随机获得值。
  • 相关阅读:
    java使用正则提取数据
    Docker部署微服务项目
    FastAPI 学习之路(十二)接口几个额外信息和额外数据类型
    [SpringMVC笔记] SpringMVC-06-JSON数据传递参数
    ModelSerializer序列化器实战
    8.3 C++ 定义并使用类
    Golang——从入门到放弃
    机器视觉面试-查漏补缺
    Pandas 使用教程 Series、DataFrame
    2023年浙大MEM英语二作文干货模版:临阵磨枪可用
  • 原文地址:https://blog.csdn.net/m0_63216218/article/details/132738926