缓存知识总结
为什么要使用缓存
缓存应用架构
通常在应用系统和数据库中间为了防止,大量的客户端数据直接访问数据库,不仅会导致数据库的压力过大,由于数据库的存取在文件中需要经过IO会消耗大量的时间,因此在大多数系统中都会使用缓存,使得客户端请求,先经过缓存处理,直到缓存穿透后在访问数据库 进行缓存的回种。缓存也当作处理熔断的一种机制,当数据库宕机后,不管缓存有没有穿透都从缓存中直接获取数据。·
缓存中间件
Memcache内存缓存
内存缓存代码层次类似于hash,支持简单的数据类型,但是不支持数据持久化存储,不支持主从也不支持分片。
Redis 关系型数据库缓存
缓存中间件有很多,Redis是最具代表性缓存中间件,其支持的数据类型丰富,可支持Hash Set List等多种数据结构,支持数据持久化到磁盘中,支持主从复制也可支持分片存储。
为什么Redis这么快
官网说明:100000+ QPS(QPS是每秒可以处理的请求数)
redis完全基于内存存储,绝大部分请求都是基于内存处理的执行效率高
数据结构简单,对数据的操作简单
Redis基于单线程,即Redis在处理客户端请求时候是单线程处理的,避免了上下文切换的线程之间的锁竞争。
Reids支持多路I/O复用模型,使得Redis在处理IO请求的时候不会阻塞其他客户端访问。
Redis的数据类型
- Sring 简单动态字符串
- hash 类似map hm
- list 类似一个栈
- set 无序的set集合 不可以重复
- zset 排序的set集合
Redis相关问题
怎么从海量的key中获取到固定前缀的key
使用keys pattern 过滤出来符合条件的key(keys x*)
优点一次可以返回出来所有匹配的key指
缺点:数据量大可能造成系统卡顿
使用scan cursor [match pattern] [Count count]
一次返回指定数量的key指(也不一定是指定数量,只是一个参考值)
分批查询出某一些key 可以重复scan 直到范围的邮标为0
缺点:总时间比keys要慢 但不会造成服务器卡顿。
实现简单的分布式锁
使用redis的 setnx指令实现分布式锁
setnx 一但设置就不可以被更改,一个线程占用后 其他线程不可以再次访问 即可实现独占锁的特性,实现中需要对setnx设置一些超时时间保证setnx不会长期有效。
long status = redisService.setnx(key,"lock");
if (status == 1) {
redisService.expire(key, expire);
//todo 独占逻辑
}
如何避免同一时间大量key过期(缓存雪崩)
过期时间可以设置一些随机数,避免问题
如何使用Redis做异步队列
list可以实现栈的功能 实现一个简单的消费者生产者模式 lpush lpop 但之类消息并不事实,bpop 监控数据写入。 可以使用发布者订阅者模式。
Redis如何做到持久化
Redis使用RDB文件和AOF文件做到持久化
RDB和AOF对比:
RDB为全量的二进制备份文件,redis会在默认时间或者数据增长的频率下进行RDB文件的缓存,保存RDB文件过程中,redis会陷入卡顿等待的过程中,也可以使用BGSAVE,由主线程fork出一个子线程进行RDB文件的创建,父进程继续处理请求,这样可以保持父进程不会收阻塞进程,但可能会导致BGSAVE时间段的数据丢失,由服务器数据不断增加 RDB的数据量也会不断增大,导致文件大,恢复时间长。
AOF为增量的,通过写入redis的指令进行增量的数据备份。 AOF默认关闭可以通过配置 appendonly yes打开 打开后 reids默认恢复数据会从AOF文件中恢复,因为AOF为增量因此具备体积小,恢复时间短,但也因为是增量的导致数据可能丢失。
Pipeline管道
批量发送消息到reids的队列中,客户端不需要等待。
Redis同步机制
留言协议 Gossip
一致性hash算法 组成圆环,数据根据服务器hash保存在环上的某个节点,