1、Redis基本介绍
Redis是开源的,位于内存中的数据结构存储系统。主要用于数据缓存、消息中间件。内置LUA脚本(支持原子性操作)、LRU驱动事件、事务和不同级别的磁盘持久化,Redis也可以通过哨兵和自动化分区提供高可用性。
Redis为什么快
首先,Redis给我们的第一印象就是快,非常快,位于内存的IO操作可以达到秒级十万的操作,从内存上的寻址速度可以达到ns级别,带宽很大,而一般sql型数据库则是从磁盘上寻址,速度则是ms级别,所以磁盘相比内存在寻址上慢了10万倍。 磁盘数据库如Mysql,数据和索引都是持久化保存在磁盘上的,当我们使用SQL语句查询命令时,若该数据的索引还没加载到内存,首先要把索引加载到内存,然后通过寻址定位和IO,将数据对应的磁盘块加载到内存中,最后读取数据。 Redis在内存中读取数据,是电信号的传递。
1.1、 Redis内核架构
epoll介绍
epoll作为Linux下高性能网络服务器必备技术至关重要。nginx、Redis、skynet 以及大部分的游戏服务器都使用这一多路复用技术。对Redis的IO起到了关键作用。
1.2、 Redis原理
众所周知,Redis是单进程,单线程,单实例的(Redis6之前),那么当高并发的请求发送过来时,Redis如何快速响应?这里面主要用到了epoll多路复用技术,可以理解为多个输入通过一条高速线路,n个信道,分配到多个输出(分为频分,时分,波分),大大提高速度。并且是非阻塞的多路复用。
2、Redis的使用
2.1、Redis数据类型
高效的数据结构
Redis底层数据结构一共有6种:简单动态字符串(StringBuffer), 双向链表, 压缩列表, 哈希表, 跳表和整数数组,与之对应的数据类型关系图如下:
不同的数据结构对应了不同的应用场景:
- String: 缓存, 分布式锁, 在线人数计算等
- List: 队列, 微博, Instagram关注人时间轴队列等
- Hash: 收藏,加购物车等
- Set: 去重,点赞(不可重复点赞),踩一踩,共同好友等
- ZSet: 排行榜排名、热搜榜等
Redis的自定义协议
Redis客户端使用RESP(Redis的序列化协议)协议与Redis服务器端进行通信,实现简单、解析快速且人可读。 RESP支持一下数据类型: 简单字符串、错误、整数、批量字符串和数组。 RESP在Redis中运作的方式为:
- 客户端将命令作为批量字符串的RESP数组发送到Redis服务器
- 服务器根据命令实现其中一种RESP类型并进行回复
在RESP中,某些的数据类型取决于第一个字节:
- 对于简单字符串, 响应的第一个字节为"+"
- 对于整数, 响应的第一个字节为":"
- 对于批量字符串, 响应的第一个字节为"$"
- 对于错误, 响应的第一个字节为"-"
- 对于数组, 响应的第一个字节为"*"
此外,RESP使用特殊变体表示null值。在RESP中, 协议的不同部分总是以"\r\n"(CRLF)终止。
高性能Redis协议分析器
快速,高效的解析协议利于阅读,使得该协议的实现性能变得和二进制协议一样快的主要原因是Redis协议将数据的长度定义在了数据正文之前,无需因为寻找特殊字符而进行全文扫描(JSON的payload),也无需像JSON一样对发送到服务器的payload进行转义。
Redis中Value的类型
- 字符串
set k1 xxxx nx. set k2 Hello xxxx. nx => 只能新建 xx => 只能更新
2.2、Redis的进阶使用
1、 Redis的发布订阅
有这样一个应用场景,聊天室里发布的消息可以让(不管在不在该聊天室窗口)所有人都可以看到,这里就可以用到Redis的发布订阅功能。 PUBLISH xxxx hello SUBSCRIBE xxxx (监听改Key)
2、 Redis事务
Redis事务的使用帮助 -> help@transactions Redis事务的和Mysql类似,即将一组命令放在同一事务中,MULTI开启一个事务,这些事务会放在一个队列中,不会立即执行。只有当EXEC命令被调用时,改命令才会被执行。 注意: Redis不支持回滚,Redis命令只会因为错误语法失效
3、 布隆过滤器(Bloom)使用
4、 Redis作为缓存/数据库的区别
- 缓存不是全量数据。缓存应该随着访问而变化 => 热数据
- Redis里的数据怎么随着业务的变化而只保留热数据(内存大小的瓶颈)
业务逻辑 -> key的有效期(过期时间) 业务运行 -> 淘汰冷数据 LFU 碰到了多少次 LRU 多长时间没碰到 ttl k1 如果发生了写命令(SET XXX) 会直接剔除expiretime Redis每秒10次做一件事 => 随机测试20个keys相关过期检测 => 删除已过期keys => 若有超过1/4的key过期,则重复操作。 - 过期的判定原理
- 被动访问时判定
- 周期轮询时判定(增量)
3、Redis的持久化(RDB/AOF)
3.1、Redis-RDB(RedisDB)
RDB即Redis的持久化机制,Redis父进程会单独fork(创建)一个子进程(和自己一模一样)来进行持久化。该子进程的所有数据(变量。环境变量,程序程序计数器等)都和父进程一模一样,将数据写入一个快照,等持久化结束后,数据库的快照(snapshot)以二进制的方式保存到磁盘中。用这个快照替换上次持久化好的文件。整个过程中,主进程没有任何IO操作,这就确保了极高的性能。 RDB的主要特征是写时复制(copy on write) 创建紫禁城**(子进程 谐音梗 O(∩_∩)O)**时并不发生复制。 通过指针,父进程增删改查数据(写), 子进程读数据。
RDB的弊端
- 不支持拉链结构
- 因为父子进程同步的问题, 丢失数据相对多一些
- 相对于Java中的序列化,恢复速度相对没有那么快
3.2、Redis-AOF(APPEND ONLY FILE)
AOF是以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。 AOF优点:
- 丢失数据少
- Redis中, RDB和AOF可以同时开启, 若开启了AOF, 则只会用AOF恢复
AOF弊端: 相对于RDB,慢, 体量无限地变大
场景复现!!
解决设计思路: 设计方案让日志(AOF)足够小
4、Redis的主从,集群,哨兵(配置)
4.1、Redis主从模式
4.2、Redis集群模式
4.3、Redis哨兵模式
4、Redis缓存问题/分布式锁
4.1、缓存击穿,穿透,雪崩
4.2、分布式锁
5、Spring结合Redis
未完待续
|