Redis快速复习
Redis是什么
- 非关系型数据库
- 内存数据库
基本数据类型
String
实现的数据结构:SDS(简单动态字符串),实现获取字符串长度为O(1) 、安全的、不会造成缓冲器溢出
常用命令:set 、get、strlen、exists、decr、incr、setex expire
应用场景:⼀般常⽤在需要计数的场景,比如⽤户的访问次数、热点⽂章的点赞转发数量等等
list
实现的数据结构:双向链表:支持反向查找和遍历,缺点带来了额外的内存开销
常用命令:rpush(右边即头部添加数据),lpush(左边即尾部添加数据),rpop(右弹),lpop(左弹),lrange(查看列表中的元素)、llen(查看链表长度)
应用场景: 发布与订阅或者说消息队列、慢查询。
hash
实现的数据结构:数组+链表
常用命令:hset、hmset、hexists(查看key中的value是否存在)、hget、hgetall、hkeys(获取key列表)、hvals(获取value列表)
应用场景:系统中对象数据的存储
set
实现的数据结构:intset+hashtable
常用命令:sadd、spop、smembers(查看set中的所有元素)、sismember(检查某个元素是否存在在set中)、scard(查看set的长度)、sinterstore(获取两个set的交集并放在第三个set)、sunion
应用场景:需要存放的数据不能重复以及需要获取多个数据源交集和并集等场景
sorted set
实现的数据结构:set + 权重参数score 使得集合中的元素按照score进行有序排序
常用命令:zadd、zcard、zscore(查看各个set的权重)、zrange、zrevrange(反向遍历)
应用场景: 需要对数据根据某个权重进⾏排序的场景。⽐如在直播系统中,实时排⾏信息包含直播间在线用户列表,各种礼物排⾏榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息。
Redis单线程模型
Redis 基于 Reactor 模式来设计开发了⾃⼰的⼀套⾼效的事件处理模型,该事件处理模型对应的是Redis中的文件事件处理模型,因为该模型是单线程方式运行的,所以一般都说Redis是单线程模型
虽然以单线程方式运行,但是通过I/O多路复用程序来监听多个套接字
为什么不引入多线程
易维护
影响性能的是网络和内存
多线程会存在死锁、线程上下文切换等问题、甚至会影响性能
Redis6.0之后引入多线程的原因(默认是禁用的,可以通过配置文件开启)
提高网络IO的读写性能
Redis 缓存过期时间
设置过期时间的作用
内存有限,避免Out of memory
expire:设置过期时间
persist:移除过期时间
ttl:查询剩余过期时间
Redis是如何判断数据过期的
有一个过期字典来保存数据过期的时间(redisDb)
过期数据的删除策略
- 惰性删除:取出数据的时候进行过期检查,缺点容易造成太多过期的key没有删除
- 定期删除:隔一段时间抽取一批key执行删除key的操作,Redis底层会限制删除操作的执行时间和频率来减少对CPU的影响
- Redis采用的是:定期删除+惰性删除
Redis的内存淘汰机制
volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使⽤的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru(least recently used):当内存不⾜以容纳新写⼊数据时,在键空间中,移除最近最少使⽤的 key(这个是最常⽤的)
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-eviction:禁⽌驱逐数据,也就是说当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错。这个应该没⼈使⽤吧!
4.0 版本后增加以下两种:
volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使⽤的数据淘汰
allkeys-lfu(least frequently used):当内存不⾜以容纳新写⼊数据时,在键空间中,移除最不经常使⽤的 key
Redis持久化机制(即,将数据写入到硬盘)
1、RDB(快照):Redis 可以通过创建快照来获得存储在内存⾥⾯的数据在某个时间点上的副本。是默认持久化的方式
2、AOF(追加文件):与快照持久化相⽐,AOF 持久化 的实时性更好,因此已成为主流的持久化⽅案。开启 AOF 持久化后每执⾏⼀条会更改 Redis 中的数据的命令,Redis 就会将该命令写⼊硬盘中的 AOF ⽂件。AOF ⽂件的保存位置和 RDB ⽂件的位置相同,都是通过 dir 参数设置的,默认的⽂件名是 appendonly.aof
AOF的三种持久化方式
- appendfsync always #每次有数据修改发⽣时都会写⼊AOF⽂件,这样会严重降低Redis的速度
- appendfsynceverysec #每秒钟同步⼀次,显示地将多个写命令同步到硬盘
- appendfsync no #让操作系统决定何时进⾏同步
3、AOF+RDB(混合):Redis 4.0 开始⽀持混合持久化(默认关闭)
- AOF 重写的时候就直接把 RDB 的内容写到 AOF ⽂件开头
- 好处:结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。
- 缺点:AOF ⾥⾯的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差
Redis事务
Redis 可以通过 MULTI,EXEC,DISCARD 和 WATCH 等命令来实现事务(transaction)功能。
Redis 是不⽀持 roll back 的,因⽽不满⾜原⼦性的(⽽且不满⾜持久性)。
Redis缓存穿透
什么是缓存穿透
即,大量请求的key不在缓存中,直接请求到数据库,穿透了缓存这一层
解决办法
1、缓存无效key
数据库和缓存都查不到就添加一个无效key到Redis并设置过期时间
缺点:如果是很多不同key会造成大量无效的key
2、布隆过滤器
一种数据结构:能够方便的判断一个给定数据是否存在于海量数据中(由一个固定大小的二进制向量或者位图和一系列映射函数组成的)
将需要所以可能存在的请求的值放入布隆过滤器,当请求过来如果判断存在则会去缓存中查找,如果不存在直接返回参数错误信息
Redis缓存雪崩
什么是缓存雪崩
缓存在同⼀时间⼤⾯积的失效,后⾯的请求都直接落到了数据库上,造成数据库短时间内承受⼤量请求
解决办法
1、采用Redis集群,避免单机出现问题整个缓存服务都无法使用
2、限流,避免同时处理大量的请求
热点缓存失效情况
1、设置不同的失效时间
2、缓存永不失效