认识Redis
认识NoSQL
1.结构化 非结构化
2.关联的 非关联的
3.SQL查询 非SQL
4.事务 ACID BASE
认识Redis
Redis 是一个开源的、基于键值对的数据结构存储系统,被广泛应用于缓存、消息队列、分布式锁等多种场景。它支持多种数据结构,如字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)等,还提供了持久化、事务、Lua脚本、Pub/Sub等高级功能。
特征
高性能:Redis使用内存存储数据,支持高读写速度,是许多高性能系统中不可或缺的组件。
数据结构丰富:除了基本的键值对,Redis提供了多种数据结构,便于开发者灵活选择最适合存储和操作数据的方式。
持久化:支持RDB(快照)和AOF(追加文件)两种持久化方式,确保数据不会因进程退出而丢失。
主从复制:支持数据复制,可以配置多个从节点,提高数据可用性和系统的扩展性。
集群:Redis Cluster提供了自动分片功能,可以将数据分布在多个节点上,实现水平扩展和故障转移。
发布/订阅(Pub/Sub):提供发布消息和订阅频道的能力,可以构建实时通知、聊天系统等。
基本命令
•设置值:SET key value
•获取值:GET key
•删除键:DEL key
•列表操作:LPUSH key value(左侧插入),RPUSH key value(右侧插入),LPOP key(左侧弹出),RPOP key(右侧弹出)
•集合操作:SADD key member(添加元素),SMEMBERS key(获取集合所有成员)
•有序集合操作:ZADD key score member(添加成员并指定分数),ZRANGE key start stop [WITHSCORES](按分数范围获取成员)
•哈希操作:HSET key field value(设置哈希表字段值),HGETALL key(获取哈希表所有字段和值)
Redis常见面试问题
使用场景
缓存三兄弟(穿透、击穿、雪崩)、双写一致、持久化、数据过期策略,数据淘汰策略
1. 高速缓存:Redis最广泛的应用之一是作为数据库查询结果的缓存,以减轻数据库压力,加速数据访问。它特别适合存储频繁访问但不经常变更的数据,如网页内容、用户会话信息等。
2. 会话管理:利用Redis的高速读写特性,可以将用户会话信息存储在内存中,实现会话的集中管理,支持高并发下的会话访问。
3. 消息队列与发布/订阅:Redis的发布/订阅模式(Pub/Sub)可以构建轻量级的消息系统,用于消息传递、实时通知、聊天应用等,支持一对多的消息广播。
4. 实时分析与计数器:Redis的原子操作和高性能特性使其非常适合实时数据分析和计数器应用,如网站访问计数、投票系统、实时统计等。
5. 排行榜系统:有序集合(Sorted Set)数据结构天然支持排序,非常适合构建各种排行榜系统,如游戏积分榜、评论热度排名等。
6. 分布式锁与同步:Redis的SETNX、GETSET等命令可以用来实现分布式锁,解决分布式系统中的并发控制问题,保障数据一致性。
7. 事务处理:虽然Redis的事务不支持回滚,但其提供了简单的事务管理能力,适用于需要一次性执行多个操作且这些操作需要原子性完成的场景。
8. 数据过期策略:Redis支持设置键的生存时间(TTL),可以自动删除过期数据,适用于实现限时优惠、会话超时等场景。
缓冲穿透
缓存穿透是指在使用缓存系统时,客户端请求的数据既不在缓存中也不在数据库中。这种情况通常发生在查询一个数据库中并不存在的数据时,缓存因为未命中而直接将请求转发到数据库,而数据库中也查不到这个数据,于是每次这样的请求都会穿透缓存直接打到数据库上,给数据库带来不必要的压力,同时也失去了缓存提高效率的意义。
解决方案一:缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存
解决方案二:布隆过滤器
bitmap(位图):相当于是一个以(bit)位为单位的数组,数组中每个单元只能存储二进制数0或1
布隆过滤器作用:布隆过滤器可以用于检索一个元素是否在一个集合中。
存储数据:id为1的数据,通过多个hash函数获取hash值,根据hash计算数组对应位置改为1
查询数据:使用相同hash函数获取hash值,判断对应位置是否都为1
hash误判:误判率:数组越小误判率就越大,数组越大误判率就越小,但是同时带来了更多的内存
缓冲击穿
缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
解决方案一:互斥锁 强一致 性能差
解决方案二:逻辑过期 高可用 性能优
缓冲雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
大量的key过期和Redis服务宕机
给不同的Key的TTL添加随机值
利用Redis集群提高服务的可用性 哨兵模式、集群模式
给缓存业务添加降级限流策略 ngxin或spring cloud gateway
给业务添加多级缓存 Guava或Caffeine
redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)
双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间
写操作:延迟双删
异步通知
异步通知保证数据的最终一致性
基于Canal的异步通知
redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)
1.介绍自己简历上的业务,我们当时是把文章的热点数据存入到了缓存中,虽然是热点数据,但是实时要求性并没有那么高,所以,我们当时采用的是异步的方案同步的数据
2.我们当时是把抢券的库存存入到了缓存中,这个需要实时的进行数据同步,为了保证数据的强一致,我们当时采用的是redisson提供的读写锁来保证数据的同步
你来介绍一下异步的方案(你来介绍一下redisson读写锁)
允许延时一致的业务,采用异步通知
①使用MQ中间中间件,更新数据之后,通知缓存删除
②利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存
强一致性的,采用Redisson提供的读写锁
①共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
②排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作
Redis持久化
Redis 提供了两种主要的持久化机制来保证数据不会因服务器故障而丢失:RDB(快照)和 AOF(Append Only File)。
RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据
RDB(Redis Database)持久化
•原理:RDB 持久化是通过快照的方式,将某一时刻的 Redis 数据集保存到一个磁盘文件中。Redis 会定期根据配置自动执行保存操作,或者在接收到 SAVE 或 BGSAVE 命令时手动执行。
•优点:
•恢复速度快:RDB 文件是经过压缩的二进制文件,体积小,加载速度快。
•数据备份友好:RDB 文件是一个完整的数据快照,适合做数据备份。
Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:
# 900秒内,如果至少有1个key被修改,则执行bgsave
save 900 1
save 300 10
save 60 10000
AOF(Append Only File)持久化•
原理:AOF 持久化是将 Redis 执行的写命令(增、删、改)以追加的方式写入到一个文件中。当Redis重启时,会重新执行文件中的命令来恢复数据。
•模式: •AOF 有多种写入模式,如everysec(默认,每秒写入一次)、always(每次写入命令后同步)、no(操作系统决定何时同步)。
•优点:
•数据安全性高:AOF 可以提供更细粒度的数据恢复,即使服务器突然宕机,也只丢失一秒的数据(如果配置为 everysec)。
•持久化实时性好:持续记录每一次写操作,数据更完整。
RDB | AOF | |
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
宕机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
系统资源占用 | 高,大量CPU和内存消耗 | 低,主要是磁盘IO资源 但AOF重写时会占用大量CPU和内存资源 |
使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
假如redis的key过期之后,会立即删除吗?
Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。
惰性删除:设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key
定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。
定期清理有两种模式:
SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf 的hz 选项来调整这个次数
FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms
Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用
数据的淘汰策略
数据的淘汰策略:当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
Redis支持8种不同策略来选择要删除的key:
noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
allkeys-random:对全体key ,随机进行淘汰。
volatile-random:对设置了TTL的key ,随机进行淘汰。
allkeys-lru: 对全体key,基于LRU算法进行淘汰
volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
allkeys-lfu: 对全体key,基于LFU算法进行淘汰
volatile-lfu: 对设置了TTL的key,基于LFU算法进行淘汰
redis分布式锁
Redis分布式锁是一种在分布式系统中协调多个节点对共享资源进行互斥访问的技术手段。它利用Redis的高性能和单线程特性,确保在任何给定时间,只有一个客户端可以持有锁,从而防止并发操作导致的数据不一致等问题。
基本实现步骤
1. 生成锁的唯一标识:每个客户端在尝试获取锁时,需要生成一个全局唯一的锁标识符(通常是UUID),这样可以区分不同的锁请求。
2. 设置锁:客户端使用SET命令设置一个键值对来尝试获取锁。使用SETNX(Set if Not Exists,如果不存在则设置)或SET命令的NX选项可以实现锁的互斥性。同时,设置一个锁的过期时间来避免死锁,可以使用PX或EX选项指定过期时间(毫秒或秒)。
SET resource_name my_random_value NX PX 30000
3. 获取锁的结果:如果SET命令执行成功,表示客户端成功获取了锁;如果执行失败,则表示锁已经被其他客户端持有。
4. 释放锁:客户端在完成操作后,需要删除锁。为了确保安全释放锁(即防止误删其他客户端的锁),客户端应该在删除锁之前验证锁的标识符仍然是自己之前设置的那个值。
if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end