一,缓存雪崩
1.缓存击穿
我们使用缓存一般的思路是:先查缓存,没有就查数据库,然后数据库结果放入缓存,如果查不到就返回。当有人恶心大量查询不存在数据时,就会导致每次都查数据库。
解决:查不到数据时,构建一个空对象放入redis,后台设置定时删除策略。这样就不会导致数据库崩溃。
2.缓存失效
对缓存数据设置相同的过期时间,导致某段时间内缓存失效,请求全部走数据库。
解决:在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
3.redis宕机
- 尽量采用redis高可用架构搭建集群。
- 设置本地缓存(ehcache)+限流(hystrix),尽量避免不会导致数据库被查崩溃。
二,热点key
概念: 缓存中的某些Key(可能对应用与某个促销商品)对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,该问题的挑战在于它无法通过增加机器容量来解决。这就是热点key。
解决: 将热点key对应value并缓存在客户端本地,并且设置一个失效时间。对于每次读请求,将首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器。
查找热点key: hotkeys参数,redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可。但是该参数在执行的时候,如果key比较多,执行起来比较慢。
$./redis-cli --hotkeys
Sampled 22 keys in the keyspace!
hot key found with counter: 254 keyname: key:000000000001
hot key found with counter: 254 keyname: key:000000000000
hot key found with counter: 254 keyname: key:000000000002
hot key found with counter: 107 keyname: mylist
hot key found with counter: 93 keyname: counter:000000000000
hot key found with counter: 87 keyname: counter:000000000002
hot key found with counter: 87 keyname: counter:000000000001
hot key found with counter: 64 keyname: myset
可以看到,排在前几位的即是热点key。
三,Redis Sentinel 哨兵机制
作用:
1.哨兵(sentinel) 会不断地检查你的 Master 和 Slave 是否运作正常。
2.自动故障转化,当主节点宕机时,哨兵从原主节点下的所有可用从节点中选举出一个作为主节点,原主节点降为从节点,并将其他从节点的主节点配置改为指定新主节点。
四,redis 持久化
Redis为持久化提供了两种方式:
- RDB:在指定的时间间隔能对你的数据进行快照存储。
- AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据。
RDB详解
原理: 将Redis在内存中的数据定时dump到磁盘上,实际操作过程是fork一个子进程,先将数据写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
配置文件:
# 表示900s内如果有1条是写入命令,就触发产生一次快照,可以理解为就进行一次备份
save 900 1
# 表示300s内有10条写入,就产生快照
save 300 10
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩 建议没有必要开启,毕竟Redis本身就属于CPU密集型服务器,再开启压缩会带来更多的CPU消耗,相比硬盘成本,CPU更值钱。
rdbcompression no
# 导入时是否检查
rdbchecksum yes
当然如果你想要禁用RDB配置,也是非常容易的,只需要在save的最后一行写上:save “”
AOF详解
原理: 将Redis的操作日志以文件追加的方式写入文件,只记录写、删除操作,查询操作不会记录(类似于MySQL的Binlog日志)
配置文件:
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
恢复数据
将备份的RDB文件,放在指定目录,重启Redis即可恢复数据。
五,Redis单点吞吐量
单点TPS达到8万/秒,QPS达到10万/秒
- QPS: 应用系统每秒钟最大能接受的用户访问量。
每秒钟处理完请求的次数,注意这里是处理完,具体是指发出请求到服务器处理完成功返回结果。、 - TPS:即服务器每秒处理的事务数。
TPS包括一条消息入和一条消息出,加上一次用户数据库访问。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。
六,Redis优化
1.info命令
进入redis-cli 执行 info命令会显示以下重要信息(我筛选了重要的几条)
# Server
redis_version:3.0.7 ##redis版本
tcp_port:14159 ##占用端口
uptime_in_seconds:16237914 ##redis启动以来,经过的秒数
uptime_in_days:187 ##redis启动以来,经过的天数
config_file:/usr/local/yunji/redis/conf/redis_14159.conf ##配置文件
# Clients
connected_clients:537 ##已连接客户端的数量(不包括通过从属服务器连接的客户端)
client_longest_output_list:0 ##当前连接的客户端当中,最长的输出列表
client_biggest_input_buf:0 ##当前连接的客户端当中,最大输入缓存
blocked_clients:0 ##正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
# Memory
used_memory_human:99.62M ##实际缓存占用的内存和Redis自身运行所占用的内存(如元数据、lua),这个数据并没有把内存碎片浪费掉的内存给统计进去。
used_memory_rss:122916864 ##从操作系统上显示已经分配的内存总量。
used_memory_peak_human:144.54M ##历史占用内存的峰值
used_memory_lua:36864 ## lua引擎所占用的内存大小
mem_fragmentation_ratio:1.18 ## 内存碎片率
七,Redis实现分布式锁
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!