redis优化,bigkey,hotkey,配置优化,缓存雪崩、缓存穿透、缓存击穿

CPU绑定

可以在redis启动的时候绑定固定的cpu,防止cpu切换引起的上线文切换:

taskset -c 1 ./redis/bin/redis-server ./reids/conf/redis.conf
redis6中开启多线程

redis.conf配置如下:

# 8核cpu可以并行6个
io-threads 6
内存碎片清理

所谓内存碎片,是指申请连续的一段内存空间,系统会找到一块符合申请大小的内存空间,但是如果开始申请了12KB的大小,然后回收,后续如果申请都大于12KB,那么这12KB空间无法被分配,相当于浪费了,redis中有自己的内存碎片整理机制,配置如下:

#内存碎片清理开关
activedefrag yes
#内存碎片达到多大的时候开始清理
active-defrag-ignore-bytes 100mb
#内存碎片占总内存达到多少百分比的时候开始清理
active-defrag-threshold-lower 10
#当内存碎片率达到多少时开启最大清理
active-defrag-threshold-upper 100
#清理内存碎片占用CPU时间的比例不低于此值开始清理
active-defrag-cycle-min 5
#清理内存碎片占用cpu时间比例不高于此值,如果超过,停止清理
active-defrag-cycle-max 75
系统swap

linux中swap类似虚拟内存,当物理内存不够的时候,会把内存中不活跃跌数据置换到硬盘上,释放一部分物理内存,swappiness表示swap的占比,如果是0表示积极的使用物理内存

#  cat /proc/sys/vm/swappiness    
60

可以设置为 1

echo 1 > /proc/sys/vm/swappiness 
echo vm.swappiness=1 >> /etc/sysctl.conf    
TCP backlog
#表示每个端口上半连接监听最大队列长度
$ cat /proc/sys/net/ipv4/tcp_max_syn_backlog
1024 
#表示每个端口上已经建立连接监听的最大监听队列长度
 $ cat /proc/sys/net/core/somaxconn 
128

在这里插入图片描述

redis中默认的tcp-backlog=511 ,表示最大TCP全连接队列为511。一般在Linux下,对于一个TCP的连接的最大数量有两个方面:

  • 一个是系统能够打开的最大句柄数
  • 另外一个就是上面说的backlog,redis这里是指已经建立连接的队列大小
内存分配控制
cat /proc/sys/vm/overcommit_memory 
0

vm.overcommit_memory设置overcommit的内存分配策略,它有三个可选值
0:内核将检查是否有足够的内存分配给程序。如果没有则申请失败,并把错误返回给应用进程。而在Redis中这个错误就会表现为“Cannot allocate memory”,然后触发OOM
1:表示内核允许超量使用内存直到用完为止
2:表示内核决不超量使用内存,即系统整个内存空间不能超过swap+50%的RAM值,50%是overcommit_ratio默认值,此参数支持修改
redis中建议将该值设置为1

echo 'vm.overcommit_memory=1' >> /etc/sysctl.conf
禁止内存大页
cat /sys/kernel/mm/transparent_hugepage/enabled 
[always] madvise never

一般情况下,分配内存页大小为4KB,开启大页之后能够达到2MB,能够降低fork子进程的速度,但是会大幅增加父进程重写期间的内存消耗

热键

热键,一般指摸个瞬间或者突然有大量请求同一个key。

redis提供了如下命令查找热key:

./redis-cli --hotkeys

hotkey可以有如下几种处理思路:

  • 对hotkey数据进行拆分,如果是hash,可以对拆分hash结构里面的数据
  • 增加本地缓存
大键,bigkey

何谓bigkey:

  • 如果是string类型,长度超过10KB
  • 非字符串类型,如hash,set,list,元素过多

redis提供了如下命令查找大键

./redis-cli --bigkeys

bigkey优化:

  • 如果是string,拆分成多个key-value
  • 如果是hash和list,考虑拆分成多个hash和list
  • 删除的时候不要直接使用delete,而是lazy delete
设置最大内存和过期策略

redis.conf中配置如下:

maxmemory 20gb
maxmemory-policy allkeys-lru

过期策略有如下几种:

  • volatile-lru -> Evict using approximated LRU among the keys with an expire set.
  • allkeys-lru -> Evict any key using approximated LRU.
  • volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
  • allkeys-lfu -> Evict any key using approximated LFU.
  • volatile-random -> Remove a random key among the ones with an expire set.
  • allkeys-random -> Remove a random key, any key.
  • volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
  • noeviction -> Don’t evict anything, just return an error on write operations.
混合持久化

我们知道redis中持久化有两种方式rdb和aof,但是两种模式存在不足:

  • rdb是某个时刻的快照,如果每秒都进行rbd备份,比较耗性能,rdb存在的问题是会丢失一部分数据
  • aof是将每个操作命令都写入aof文件中,会造成aof文件过大,恢复比较耗时
    redis中增加了混合持久化,利用rdb和aof的特性,aof不是记录所有的请求命令,而是在rdb生成之后记录,这样不会丢数据
# 前提是开启了aof
aof‐use‐rdb‐preamble yes

开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件,才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

缓存穿透

高并发情况下,缓存中没有数据,查询都去查询数据库,导致数据库压力陡增,解决方案:

  • 使用布隆过滤器,首先通过布隆过滤器判断缓存key是否存在,如果不存在直接返回,如果存在再去查询缓存、数据库
  • 可以针对不存在的数据,在缓存中缓存一个空标志,业务上在针对这种情况处理
缓存雪崩

大量的key缓存或者redis重启导致大量的访问在redis中查找不到数据,访问数据库,导致数据库压力陡增,甚至崩溃,解决方案:

  1. key的失效时间分散开来,可以在失效时间后再加一个随机时间
  2. 增加一个二级缓存
  3. 增加高可用结构
  4. 设置缓存不过期,后台一个服务进行更新
缓存击穿

类似hotkey,hotkey在某个时刻失效,大量请求过来查询数据库,解决方法

  1. 分布式锁控制访问线程,保证不会有大量线程同时查询数据库
  2. 不设置超时时间(有写一致性问题)
缓存和数据库不一致时

如果可以接收最终一致性,那么可以通过先删除缓存,然后更新数据库,或者一定间隔后更新数据库,或者通过binlog定时更新数据库

如果必须强一致性,那么可以如下解决:
在接入端,比如nginx 通过hash将通一个id路由到同一个服务中处理,在同一个处理中,在路由将一个id放在同一个队列中,通过队列串行处理

缓存并发竞争更新
  • 可以通过redis分布式锁+时间戳
  • 通过mq串行更新
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值