框架源码专题-Redis-1、基本原理
1. 数据类型
1.1. String- 点赞
setex: 设置带过期时间的 key,动态设置。
setex 键秒值真实值
setnx: 只有在 key 不存在时设置 key 的值
点赞
1.2. List- 关注列表
一个双端链表的结构,容量是 2 的 32 次方减 1 个元素,大概 40 多亿,主要功能有 push/pop 等,一般用在栈、队列、消息队列等场景。
left、right 都可以插入添加;
如果键不存在,创建新的链表;
如果键已存在,新增内容;
如果值全移除,对应的键也就消失了。
- 它的底层实际是个 双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差
1 大 V 作者李永乐老师和 CSDN 发布了文章分别是 11 和 22
2 阳哥关注了他们两个,只要他们发布了新文章,就会安装进我的 List
lpush likearticle:阳哥id 11 22
3 查看阳哥自己的号订阅的全部文章,类似分页,下面 0~10 就是一次显示 10 条
lrange likearticle:阳哥id 0 9
1.3. Hash- 购物车
1.4. Set- 抽奖
1.5. Zset- 排行榜
1.6. Bitmaps
❕ ^akrc06
Redis 提供了 Bitmaps 这个“数据类型”可以实现对位的操作:
(1) Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。
(2) Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。
1.6.1. 使用场景
1.6.1.1. setbit
setbit<key><offset><value>
设置 Bitmaps 中某个偏移量的值(0 或 1)
每个独立用户是否访问过网站存放在 Bitmaps 中, 将访问的用户记做 1, 没有访问的用户记做 0, 用偏移量作为用户的 id。
设置键的第 offset 个位的值(从 0 算起) , 假设现在有 20 个用户,userid=1, 6, 11, 15, 19 的用户对网站进行了访问, 那么当前 Bitmaps 初始化结果如图
1.6.1.2. bitcount
bitcount<key>[start end]
统计字符串从 start 字节到 end 字节比特值为 1 的数量
计算 2022-11-06 这天的独立访问用户数量
start 和 end 代表起始和结束字节数, 下面操作计算用户 id 在第 1 个字节到第 3 个字节之间的独立访问用户数, 对应的用户 id 是 11, 15, 19。
1.6.1.3. bitop
bitop and(or/not/xor) <destkey> [key…]
bitop 是一个复合操作, 它可以做多个 Bitmaps 的 and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在 destkey 中。
2020-11-04 日访问网站的 userid=1,2,5,9。
setbit unique:users:20201104 1 1
setbit unique:users:20201104 2 1
setbit unique:users:20201104 5 1
setbit unique:users:20201104 9 1
1.6.2. Bitmaps 与 set 对比
1.6.3. 与布隆过滤器的区别
位图存在两个问题
• 处理数字很方便,但是处理字符就稍微有点困难了
• (关键)位图在数据量过大情况下导致了内存浪费 (太稀疏)
https://developer.aliyun.com/article/930143#slide-6
https://juejin.cn/s/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8%E5%92%8Cbitmap%E5%8C%BA%E5%88%AB
1.7. HyperLogLog
1.7.1. 什么是基数
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数 (不重复元素) 为 5。 基数估计就是在误差可接受的范围内,快速计算基数。
在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站 PV(PageView 页面访问量),可以使用 Redis 的 incr、incrby 轻松实现。
但像 UV(UniqueVisitor,独立访客)、独立 IP 数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。
解决基数问题有很多种方案:
(1)数据存储在 MySQL 表中,使用 distinct count 计算不重复个数
(2)使用 Redis 提供的 hash、set、bitmaps 等数据结构来处理
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。
能否能够降低一定的精度来平衡存储空间?Redis 推出了 HyperLogLog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
1.7.2. 命令
1.7.2.1. pfadd
1.7.2.2. pfadd
1.7.2.3. pfmerge
2. 持久化
2.1. RDB
2.1.1. 是什么
在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的 Snapshot 快照,它恢复时是将快照文件直接读到内存里
2.1.2. RDB 持久化原理
Redis 会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何 IO 操作的,这就确保了极高的性能 。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加高效。RDB 的缺点是 最后一次持久化后的数据可能丢失。
2.1.3. 触发条件
作用:用作主从同步
2.1.4. 自动触发默认配置
❕ ^hp0xn0
2.1.4.1. Redis6
2.1.4.2. Redis7
2.1.5. 手动触发
在 Linux 程序中,fork() 会产生一个和父进程完全相同的子进程,但子进程在此后多会 exec 系统调用,出于效率考虑,尽量避免膨胀。
2.1.6. 如何恢复⭐️🔴
备注:不可以把备份文件 dump.rdb 和生产 redis 服务器放在同一台机器,必须分开各自存储,以防生产机物理损坏后备份文件也挂了。
2.1.7. 优劣势
2.1.7.1. 优势
l 适合大规模的数据恢复
l 对数据完整性和一致性要求不高更适合使用
l 节省磁盘空间
l 恢复速度快
2.1.7.2. 劣势
l Fork 的时候,内存中的数据被克隆了一份,大致 2 倍的膨胀性需要考虑
l 虽然 Redis 在 fork 时使用了 写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
l 在备份周期在一定间隔时间做一次备份,所以如果 Redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。
2.1.8. 优化总结
默认 yes
如果配置成 no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确保 redis 继续接受新的写请求
默认 yes
对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis 会采用 LZF 算法进行压缩。
如果你不想消耗 CPU 来进行压缩的话,可以设置为关闭此功能
默认 yes
在存储快照后,还可以让 redis 使用 CRC64 算法来进行数据校验,但是这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能
rdb-del-sync-files:在没有持久性的情况下删除复制中使用的 RDB 文件启用。默认情况下 no,此选项是禁用的。
2.2. AOF
2.2.1. 是什么
以 日志 的形式来记录每个写操作(增量保存),将 Redis 执行过的所有写指令记录下来 (读操作不记录), 只许追加文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
默认情况下,Redis 没有开启 AOF,开启需要配置 appendonly yes
2.2.2. AOF 持久化流程
(1)客户端发起请求
(2)客户端的请求写命令会被 append 追加到 AOF 缓冲区内;
(3)AOF 缓冲区根据 AOF 持久化策略 [always,everysec,no]
将操作 sync 同步到磁盘的 AOF 文件中;默认为 everysec
(4)AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件 rewrite 重写,压缩 AOF 文件容量;
(5)Redis 服务重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的;
2.2.2.1. 持久化策略
2.2.3. 版本变化
2.2.4. 优劣势
2.2.4.1. 优势
备份机制更稳健,丢失数据概率更低。
可读的日志文本,通过操作 AOF 稳健,可以处理误操作。
2.2.4.2. 劣势
比起 RDB 占用更多的磁盘空间
恢复备份速度要慢
每次读写都同步的话,有一定的性能压力
存在个别 Bug,造成恢复不能
2.2.5. AOF 重写机制
2.2.6. 总结
2.2.7. 用哪个好
官方推荐两个都启用
如果对数据不敏感,可以选单独用 RDB
不建议单独用 AOF,因为可能会出现 Bug
如果只是做纯内存缓存,可以都不用
2.3. RDB+AOF 混合持久化 - 优先 AOF(如有)
❕ ^j8eolm
1 开启混合方式设置
设置 aof-use-rdb-preamble 的值为 yes yes 表示开启,设置为 no 表示禁用
2 RDB+AOF 的混合方式
结论:RDB 镜像做全量持久化,AOF 做增量持久化
先使用 RDB 进行快照存储,然后使用 AOF 持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的 RDB 记录。这样的话,重启服务的时候会从 RDB 和 AOF 两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是 RDB 格式,一部分是 AOF 格式。
3. Redis 事务
本质就是一个队列中,一次性、顺序性、排他性的执行一系列 Redis 命令。通过 3 个步骤完成
1 开启:以 MULTI 开始一个事务
2 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
3 执行:由 EXEC 命令触发事务
3.1. 与数据库事务区别
4. Redis 管道
4.1. 背景
Redis 是一种基于客户端 - 服务端模型以及请求/响应协议的 TCP 服务。一个请求会遵循以下步骤:
1 客户端向服务端发送命令分四步 (发送命令→命令排队→命令执行→返回结果),并监听 Socket 返回,通常以阻塞模式等待服务端响应。
2 服务端处理命令,并将结果返回给客户端。
上述两步称为:Round Trip Time(简称 RTT, 数据包往返于两端的时间),问题笔记最下方
如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了 RTT(Round Time Trip),而且还频繁调用系统 IO,发送网络请求,同时需要 redis 调用多次 read() 和 write() 系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响了,性能不太好
4.2. 定义
4.3. 演示
4.4. 总结
频繁的上下文切换很可能导致 CPU 占比增高。 性能调优-进阶-2、系统调优案例♨️
5. Redis 发布订阅
有这种功能
6. SpringBoot 集成 Redis
7. 原子性、Redis 事务、lua
7.1. Redis 的操作的原子性
因为 redis 是单线程的!Redis 的 API 是原子性的操作
7.2. Redis + Lua 原子性
Redis 从 2.6.0 版本开始提供了 eval 命令,通过内置的 Lua 解释器,可以让用户执行一段 Lua 脚本并返回数据。因为 Redis 单线程模型的特点,可以保证多个命令的原子性; Redis 的 API 是原子性的操作 eval 是 redis 的一个 Api
7.3. Redis 集群 +Lua 注意
Redis cluster 对多 key 操作有限,要求命令中所有的key 都属于一个 slot,才可以被执行 如何将 key 放到同一个 slot 中呢: 你需要将把 key 中的一部分使用 {} 包起来,redis 将通过 {} 中间的内容作为计算 slot 的 key,类似 key1{mykey}、key2{mykey} 这样的都会存放到同一个 slot 中
[[rediscluster lua使用_家中老九的博客-CSDN博客_redis lua cluster]]
7.4. Redis 事务、lua、管道使用场景
[[redis中的事务、lua脚本和管道的使用场景_fangjian1204的博客-CSDN博客]]
8. 实战经验
8.1. Redis 的 Java 客户端
8.2. 应用场景
8.3. RedisTemplate
8.3.1. 自动序列化反序列化
9. 参考与感谢
❕ ^2sb6jv
9.1. 尚硅谷
https://www.bilibili.com/video/BV13R4y1v7sP?p=38&vd_source=c5b2d0d7bc377c0c35dbc251d95cf204
视频下载:/Users/Enterprise/0003-Architecture/011-Java/尚硅谷/尚硅谷 Redis6 视频课程/视频
[[Redis6笔记.xmind]]
[[Redis6笔记.docx]]
file:///Users/taylor/Nutstore%20Files/Obsidian_data/pages/002-schdule/001-Arch/001-Subject/002-%E6%A1%86%E6%9E%B6%E6%BA%90%E7%A0%81%E4%B8%93%E9%A2%98/002-DB/001-Redis/%E5%B0%9A%E7%A1%85%E8%B0%B7Redis7/%E8%84%91%E5%9B%BE/Redis%E8%84%91%E5%9B%BE%EF%BC%88%E5%9F%BA%E7%A1%80%E7%AF%87+%E9%AB%98%E7%BA%A7%E7%AF%87%EF%BC%89.html
9.2. 黑马
9.2.1. 视频
https://www.bilibili.com/video/BV1cr4y1671t?p=108&vd_source=c5b2d0d7bc377c0c35dbc251d95cf204
9.2.2. 资料
已存百度网盘:框架源码专题 -DB-Redis
1 |
|