Redis数据库基础总结

本文详细介绍了Redis在缓存、数据库操作、分布式锁、消息队列和一致性策略等方面的应用,探讨了其单线程高效、数据结构、过期策略、分布式架构(哨兵和集群)以及高并发下的设计。重点讲解了如何利用Redis实现缓存淘汰、一致性保证和布隆过滤器的应用。
摘要由CSDN通过智能技术生成

1. Redis可以做什么

缓存、分布式缓存
数据库, 比如实现点赞、关注、排行等频繁读写的数据库的操作
分布式锁、消息队列、
比如电商项目中:商品SPU放入Redis, 用Redis实现分布式锁和分布式缓存
博客项目中:Redis存文章点赞数

2. Redis数据类型

字符串、哈希、列表、集合、有序集合

3. Redis单线程为什么快?

Redis单线程是指网络IO和键值对读写是一个线程完成的。

  1. 单线程避免线程切换和竞争产生的消耗
  2. Redis大部分操作是在内存上完成的
  3. Redis采用IO多路复用机制,使其在网络IO操作中能并发处理大量客户端请求

在这里插入图片描述

4.set和 zset区别

set中元素是无序的,不可重复的,集合最多存 232-1个元素,除了增删改查,还支持求并集、交集、差集操作

zset除了有set的特点, 还会为集合每个元素设置一个分数,并以此为排序的依据

5.Redis的watch命令

很多时候要确保事务中的数据没有被其他客户端修改才执行改事务,watch命令可以解决这个问题,这是一种乐观锁机制, 通过watch命令对一个或多个key进行监视,如果在客户端事务执行前这些key发生了变化,就拒绝执行事务,并返回空值

6.你如何设计Redis的过期时间

设置过期时间得考虑缓存穿透、缓存击穿、缓存雪崩
缓存穿透: 请求不存在的值,请求直接落到数据库,缓存失去意义。解决办法把不存在的值也存入缓存并设置一个短暂的过期时间,5分钟以下
缓存击穿: 大量数据请求热点数据,热点数据刚好过期了,导致大量请求落到数据库上并进行重建缓存,使用分布式锁,只允许一个线程做数据库查询和重建缓存。其他请求去查缓存。或者设置热点数据永不过期
缓存雪崩: 大量缓存同时过期。 可以设置缓存的时候加一个随机时间,防止缓存同时过期

7.Redis中,sexnx命令的返回值是什么,如何使用该命令实现分布式锁?

setnx命令返回整数值,当返回1时表示设置值成功,当返回0时表示设置值失败(key已存在)。

一般不建议用 setnx 实现分布式锁,因为为了避免出现死锁,我们得给锁设置一个自动过期时间。但是setnx 命令和设置过期时间不是一个原子操作,可能导致假设成功而设置过期时间失败,存在死锁的隐患。

通过 set...nx..命令,把加锁和过期时间编排到一起,变成一个原子操作,避免死锁隐患
SET lock_key unique_value NX PX 10000 
解锁就是删除键值对
del key

占锁的时候,值设置为UUID, 每个人只能删除自己上的锁
解锁时是先判断再释放,这两步最好也是原子操作,可以用lua脚本把命令编排到一起

8.说一说Redis的持久化策略

RDB持久化、AOF持久化、RDB-AOF混合持久化

RDB:以快照的形式持久化
AOF:以独立日志的方式,记录每次写入命令
通过使用RDB-AOF混合持久化,可以把丢失数据的时间窗口限制在 1s 之内。

9.如何实现Redis的高可用

Redis实行高可用主要有 哨兵 和 集群 两种方式。
Redis 哨兵是一个分布式架构,包含若干个哨兵节点和数据节点。每个哨兵节点会对数据节点和其余哨兵节点进行监控,如果发现节点不可达时,会对节点做出下线标识。如果被标识的是主节点时,他就会与其他哨兵节点进行协商,如果多数哨兵节点认为主节点不可达时,它们会选举出一个哨兵节点来完成自动故障转移的工作,同时还会将这个变化实时通知给应用方。整个过程是自动的不需要人工介入,实现了Redis的高可用。
在这里插入图片描述
Redis 集群没有用一致性hash,而是采用哈希槽分区来实现数据分片,它把所有的键根据哈希函数映射到一个0-16383整数槽内,每个节点负责维护一部分槽以及槽所映射的键值数据。

请介绍Redis集群的实现方案

Redis集群的分片机制

Redis集群的应用和优劣势

10.Redis的主从同步是如何实现的

Redis使用psync命令完成主从数据同步,同步过程分为全量复制和部分复制。全量复制一般用于初次复制的场景,部分复制用于处理网络中断等原因导致的数据丢失。

11.Redis为什么存的快,内存断电数据怎么恢复

Redis存的快是因为它的数据都存放在内存里,并且为了保证数据的安全性,Redis还提供了三种数据的持久化机制,即RDB持久化、AOF持久化、RDB-AOF混合持久化。若服务器断电,那么我们可以利用持久化文件,对数据进行恢复。理论上来说,AOF/RDB-AOF持久化可以将丢失数据的窗口控制在1S之内。

12.介绍一下Redis的过期策略

两种过期策略:
惰性删除:客户端访问一个key的时候,先看过期时间,过期了就删除
定期删除:Redis把设置了过期时间的key放到一个独立的字典中,并对字典进行每秒10次的过期扫描。
过期扫描不会遍历所有key,而是从过期字典随机选20个key,删除20个key中过期的key,如果过期的key比例超过25%,则重复

13.说一说Redis的缓存淘汰策略

当写入数据将导致超出maxmemory限制时,Redis会采用maxmemory-policy所指定的策略进行数据淘汰。
该策略一共包含如下8种选项:
在这里插入图片描述
直接返回错误、从带过期时间的键中随机、LRU、LFU、过期时间最小选、 从不带过期时间的键中、随机、LRU、LFU选。

LRU就是一个链表,用过的或者新来的放头部,满了删尾部。缺点是如果数据只用过一次也会被当作热点数据。
LFU是LRU基础上对每个数据增加一个计数器,来统计这个数据的访问次数。LFU每次把访问次数最低的淘汰出内存,如果两个访问次数一样,再根据谁早淘汰谁

14.缓存穿透、击穿、雪崩

  1. 缓存穿透:高并发系统下, 大量请求查询不存在的值,缓存不会命中,请求直接落到数据库上。比如商品系统里查询不存在的商品。
    【解决方法:用户鉴权校验和参数校验,不合法是参数直接返回。 将不存在的数据也写入缓存,并设置的短暂的过期时间】
  2. 缓存击穿:某个热点数据被大量请求时,缓存突然过期,请求瞬间全部落到数据库上。比如秒杀进行过程中,秒杀商品缓存突然过期
    【加锁,大量并发只让一个线程去查,其他人等待,查到以后放入缓存,释放锁,其他人拿到锁先查缓存,如果有数据就不去数据库查】
  3. 缓存雪崩:在高并发下, 大量的缓存key在同一时间失效,导致大量请求落在数据库上。比如商品系统首页缓存突然过期。
    【给缓存原有的失效时间基础上增加一个随机值,比如1-5分钟的随机值,这样每个缓存的过期时间重复率就会降低,
    或者干脆不设置过期时间,更新内容的时候刷新缓存】

布隆过滤器

为了防止缓存穿透,布隆过滤器可以快速判断一个元素是否在一个集合中。
布隆过滤器原理:当一个元素被加入集合时,通过 K 个散列函数将这个元素映射成一个位数组(Bit array)中的 K 个点,把它们置为 1 。检索时,只要看看这些点是不是都是1就知道元素是否在集合中;如果这些点有任何一个 0,则被检元素一定不在;如果都是1,则被检元素很可能在(之所以说“可能”是误差的存在)。

15. 如何保证缓存和数据库的一致性?

双写模式

数据库和缓存都修改,不推荐这种方式,因为万一是写多读少,会带来大量的无效写入,浪费性能,删除的话,最多多一次查数据库。
而且也会有数据不一致情况,比如两个线程,顺序是:线程1写入数据库,线程2写入数据库,线程2更新缓存,线程1更新缓存。
后写入的数据的线程先更新完成了,导致数据不一致

失效模式

修改数据库,删除缓存
先更新数据库,再删除缓存。
数据库更新失败,捕获异常不再继续删除缓存,不会出现数据不一致
缓存删除失败或还没删除导致数据库是新数据,缓存是旧数据,出现数据不一致。
这种情况如果对数据实时性要求不高,可以给缓存加上过期时间,实现最终一致性

先删除缓存,再更新数据库
删除缓存失败,可以捕获异常,直接返回结果,不再更新数据库,不会出现数据不一致
删除缓存成功,更新数据库失败或还没更新。可能会出现数据不一致。
比如一个线程删了缓存,数据更新还没成功,另一个线程取数据发现缓存没了,从数据库读取旧数据放入缓存,然后数据库更新了数据,导致数据库和缓存数据不一致
可以用延迟双删来解决这个问题

延迟双删
先删除缓存,再更新数据库,再延长3-5秒后删除缓存,实现最终一致性
【这个延迟时间是业务读数据的时间+几百毫秒】

订阅MySQL二进制日志

可以使用canal订阅binlog的方式,只要发现数据库有更新,canal就会自动更新缓存

16.Redis底层数据结构

17.Redis 中如何实现的消息队列?实现的方式有几种

  1. 使用 list 类型实现
  2. 使用 zset 类型实现
  3. 使用 发布订阅者模式实现
  4. 使用 Stream 实现

list

List 类型实现的方式最为简单和直接,它主要是通过 lpush、rpop 存入和读取实现消息队列的
lpush brpop :阻塞式 ( 推荐此种方式 )
优点:使用 List 实现消息队列的优点是消息可以被持久化,List 可以借助 Redis 本身的持久化功能,AOF 或者是 RDB 或混合持久化的方式,用于把数据保存至磁盘,这样当 Redis 重启之后,消息不会丢失。
缺点:消息不支持重复消费、没有按照主题订阅的功能、不支持消费消息确认等。

zset

和list优缺点类似: 用zadd 和 zrangebyscore 来实现存入和读取消息的。 而且zset不能有重复数据

发布订阅

我们可以使用一个消费者“queue_*”来订阅所有以“queue_”开头的消息队列
在这里插入图片描述
优点是可以按照主题订阅。
缺点是不能持久化,发布订阅模式是“发后既忘”的工作模式,如果有订阅者离线重连之后就不能消费之前的历史消息,不支持消费者确认机制,稳定性不能得到保证。

Stream 类型实现

使用 Stream 的 xadd 和 xrange 来实现消息的存入和读取了,并且 Stream 提供了 xack 手动确认消息消费的命令,用它我们就可以实现消费者确认的功能了,使用命令如下:

127.0.0.1:6379> xack mq group1 1580959593553-0
(integer) 1

消费确认增加了消息的可靠性,一般在业务处理完成之后,需要执行 ack 确认消息已经被消费完成,整个流程的执行如下图所示:
在这里插入图片描述
其中“Group”为群组,消费者也就是接收者需要订阅到群组才能正常获取到消息。

18.高并发怎么设计Redis架构

https://blog.csdn.net/weixin_41753567/article/details/124110380
Redis Cluster, 当遇到单机内存、并发、流量等瓶颈时,可以采用0Cluster架构方案达到负载均衡的目的

在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值