1、Redis基本介绍
Redis为什么快 1.1、 Redis内核架构
epoll介绍 1.2、 Redis原理 2、Redis的使用
2.1、Redis数据类型
高效的数据结构Redis的自定义协议高性能Redis协议分析器Redis中Value的类型 2.2、Redis的进阶使用
1、 Redis的发布订阅2、 Redis事务3、 布隆过滤器(Bloom)使用4、 Redis作为缓存/数据库的区别 3、Redis的持久化(RDB/AOF)
3.1、Redis-RDB(RedisDB)
RDB的弊端 3.2、Redis-AOF(APPEND onLY FILE)
场景复现!! 4、Redis的主从,集群,哨兵(配置)
4.1、Redis主从模式4.2、Redis集群模式4.3、Redis哨兵模式 4、Redis缓存问题/分布式锁
4.1、缓存击穿,穿透,雪崩4.2、分布式锁 5、Spring结合Redis 1、Redis基本介绍
Redis是开源的,位于内存中的数据结构存储系统。主要用于数据缓存、消息中间件。内置LUA脚本(支持原子性操作)、LRU驱动事件、事务和不同级别的磁盘持久化,Redis也可以通过哨兵和自动化分区提供高可用性。
Redis为什么快 首先,Redis给我们的第一印象就是快,非常快,位于内存的IO操作可以达到秒级十万的操作,从内存上的寻址速度可以达到ns级别,带宽很大,而一般sql型数据库则是从磁盘上寻址,速度则是ms级别,所以磁盘相比内存在寻址上慢了10万倍。
磁盘数据库如Mysql,数据和索引都是持久化保存在磁盘上的,当我们使用SQL语句查询命令时,若该数据的索引还没加载到内存,首先要把索引加载到内存,然后通过寻址定位和IO,将数据对应的磁盘块加载到内存中,最后读取数据。
Redis在内存中读取数据,是电信号的传递。
epoll作为Linux下高性能网络服务器必备技术至关重要。nginx、Redis、skynet 以及大部分的游戏服务器都使用这一多路复用技术。对Redis的IO起到了关键作用。
众所周知,Redis是单进程,单线程,单实例的(Redis6之前),那么当高并发的请求发送过来时,Redis如何快速响应?这里面主要用到了epoll多路复用技术,可以理解为多个输入通过一条高速线路,n个信道,分配到多个输出(分为频分,时分,波分),大大提高速度。并且是非阻塞的多路复用。
Redis底层数据结构一共有6种:简单动态字符串(StringBuffer), 双向链表, 压缩列表, 哈希表, 跳表和整数数组,与之对应的数据类型关系图如下:
不同的数据结构对应了不同的应用场景:
String: 缓存, 分布式锁, 在线人数计算等List: 队列, 微博, Instagram关注人时间轴队列等Hash: 收藏,加购物车等Set: 去重,点赞(不可重复点赞),踩一踩,共同好友等ZSet: 排行榜排名、热搜榜等 Redis的自定义协议
Redis客户端使用RESP(Redis的序列化协议)协议与Redis服务器端进行通信,实现简单、解析快速且人可读。
RESP支持一下数据类型: 简单字符串、错误、整数、批量字符串和数组。
RESP在Redis中运作的方式为:
在RESP中,某些的数据类型取决于第一个字节:
对于简单字符串, 响应的第一个字节为"+"对于整数, 响应的第一个字节为":"对于批量字符串, 响应的第一个字节为"$"对于错误, 响应的第一个字节为"-"对于数组, 响应的第一个字节为"*"此外,RESP使用特殊变体表示null值。在RESP中, 协议的不同部分总是以"rn"(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)
Redis事务的使用帮助 -> help@transactions
Redis事务的和Mysql类似,即将一组命令放在同一事务中,MULTI开启一个事务,这些事务会放在一个队列中,不会立即执行。只有当EXEC命令被调用时,改命令才会被执行。
注意: Redis不支持回滚,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)**时并不发生复制。
通过指针,父进程增删改查数据(写), 子进程读数据。
不支持拉链结构因为父子进程同步的问题, 丢失数据相对多一些相对于Java中的序列化,恢复速度相对没有那么快 3.2、Redis-AOF(APPEND onLY FILE)
AOF是以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。
AOF优点:
丢失数据少Redis中, RDB和AOF可以同时开启, 若开启了AOF, 则只会用AOF恢复
AOF弊端:
相对于RDB,慢, 体量无限地变大 场景复现!!
解决设计思路:
设计方案让日志(AOF)足够小
未完待续