REDIS_05redis缓存设计与性能优化
2023-04-26 23:44:45 14 举报
AI智能生成
redis缓存设计与性能优化
作者其他创作
大纲/内容
缓存设计
缓存穿透
查询一个根本不存在的数据, 缓存层和存储层都不会命中
原因
自身业务代码或者数据出现问题
一些恶意攻击、 爬虫等造成大量空命中
导致不存在的数据每次请求都要到存储层去查询, 失去了缓存保护后端存储的意
解决方案
缓存空对象
布隆过滤器
布隆过滤器就是一个大型的位数组和几个不一样的无偏 hash 函数
偏就是能够把元素的 hash 值算得比较均匀。
对于恶意攻击,向服务器请求大量不存在的数据造成的缓存穿透
对于不存在的数据布隆过滤器一般都能够过滤掉,不让请求再往后端发送
某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在
适用于数据命中不高、 数据相对固定、 实时性低(通常是数据集较大) 的应用场景, 代码维护较为复杂, 但是缓存空间占用很少
缓存失效
大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库
可能会造成数据库瞬间压力过大甚至挂掉,对于这种情况我们在批量增加缓存时最好将这一批数据的缓存过期时间设置为一个时间段内的不同时间
缓存雪崩
缓存层支撑不住或宕掉后, 流量会像奔逃的野牛一样, 打向后端存储层
原因
超大并发过来,缓存层支撑不住
造成存储层也会级联宕机
缓存设计不好,类似大量请求访问bigkey,导致缓存能支撑的并发急剧下
预防和解决缓存雪崩问题
保证缓存层服务高可用性,比如使用Redis Sentinel或Redis Cluster
依赖隔离组件为后端限流并降级。比如使用Hystrix限流降级组件
提前演练。 在项目上线前, 演练缓存层宕掉后, 应用以及后端的负载情况以及可能出现的问题, 在此基础上做一些预案设定
热点缓存key重建优化
应对问题
当前key是一个热点key(例如一个热门的娱乐新闻),并发量非常大
重建缓存不能在短时间完成, 可能是一个复杂计算, 例如复杂的SQL、 多次IO、 多个依赖等
解决方案
避免大量线程同时重建缓存
利用互斥锁来解决,此方法只允许一个线程重建缓存, 其他线程等待重建缓存的线程执行完, 重新从缓存获取数据即可
开发规范与性能优化
键值设计
key名设计
可读性和可管理性
以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id
简洁性
保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视
不要包含特殊字符
包含空格、换行、单双引号以及其他转义字符
value设计
拒绝bigkey(防止网卡流量、慢查询)
在Redis中,一个字符串最大512MB
二级数据结构(例如hash、list、set、zset)可以存储大约40亿个(2^32-1)个元素
字符串类型:它的big体现在单个value值很大,一般认为超过10KB就是bigkey
非字符串类型:哈希、列表、集合、有序集合,它们的big体现在元素个数太多
string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000
危害
导致redis阻塞
网络拥塞
假设一个bigkey为1MB,客户端每秒访问量为1000,那么每秒产生1000MB的流量
一般服务器会采用单机多实例的方式来部署,也就是说一个bigkey可能会对其他实例也造成影响
过期删
不要使用del删除,使用hscan、sscan、zscan方式渐进式删除
止bigkey过期时间自动删除问题,造成阻塞
使用Redis 4.0的过期异步删除(lazyfree-lazy-expire yes)
产生的场景
社交类
粉丝列表,如果某些明星或者大v不精心设计下,必是bigkey
统计类
例如按天存储某项功能或者网站的用户集合,除非没几个人用,否则必是bigkey
缓存类
命令使用
O(N)命令关注N的数量
hgetall、lrange、smembers、zrange、sinter等并非不能使用,但是需要明确N的
禁用命令
禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令
合理使用select
redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰
使用批量操作提高效率
原生命令:例如mget、mset。
非原生命令:可以使用pipeline提高效率。
但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关
Redis事务功能较弱,不建议过多使用,可以用lua替代
客户端使用
避免多个应用使用一个Redis实例
使用带有连接池的数据库,可以有效控制连接,同时提高效率
优化参数
maxTotal:最大连接数
考虑的因素
业务希望Redis并发量
客户端执行命令时间
Redis资源
nodes(例如应用个数) * maxTotal 是不能超过redis的最大连接数maxclients
资源开销
希望控制空闲连接(连接池此刻可马上使用的连接)
不希望因为连接池的频繁释放创建连接造成不必靠开销
maxIdle和minIdle
maxIdle实际上才是业务需要的最大连接数,maxTotal是为了给出余量,所以maxIdle不要设置过小,否则会有new Jedis(新连接)开销。
连接池的最佳性能是maxTotal = maxIdle,这样就避免连接池伸缩带来的性能干扰
高并发下建议客户端添加熔断功能
Redis对于过期键有三种清除策略
被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
当前已用内存超过maxmemory限定时,触发主动清理策略
0 条评论
下一页