目录
集群运维
集群倾斜
集群读写分离
手动故障转移
数据迁移
缓存更新策略
穿透优化
无底洞优化
雪崩优化
热点key优化
Linux配置优化
flushall/flushdb误操作
安全的redis
处理bigkey
寻找热点key
之前这本书看了大概二分之一,后面就没有再坚持下去,这次在我球管理redis-manager的机会,重新捡起这本书,深度的阅读,以防止自己记忆碎片,整理文档。Redis开发与运维这本书的内容太多,网上没有找到检索,记录下来自己认为重要的信息片段,供检所使用。
书籍地址:https://github.com/singgel/Study-Floder
集群完整性:
默认当16384中任何一个槽没有指派时集群不可用
持有槽的主节点下线时,从故障发现到自动切换转移,整个集群状态为不可用,大多数场景无法接受将cluster-require-full-coverage设置为no
带宽消耗:
消息发送频率:cluster-node-timeout/2
消息数据量:slots槽数组(2kb)+1/10集群的状态数据
节点部署规模:部署的节点要划分均匀
Pub/Sub广播问题:
集群模式下的public广播问题,频繁的应用Pub/Sub避免在大量节点的集群使用,建议使用sentinel结构专门用于Pub/Sub
数据倾斜:
节点和槽不均匀 使用redis-trib.rb rebalance
不同槽对应键数据量差异过大 大量使用hash_tag导致,
使用cluster countkeysinslot {slot}获取槽对应键的数量发现最多建的槽,
再通过cluster getkeysinslot {slot} {count}迭代出所有键找出过度使用的hash_tag
集合对象包含大量元素 使用redis-cli --bigkey识别,找出后根据业务场景拆分(过大会造成migrate失败)
内存相关配置不一致 例如hash-max-ziplist-value、set-max-intset-entitres等压缩数据结构配置
请求倾斜:
热点key的场景,简单的getset不会造成负载不均匀,一般是hgetall、smembers等搞复杂度算法命令
1.大集合键拆分,hmget代替hgetall
2.不使用热key做hash_tag
3.一致性要求不高的,客户端使用本地缓存减少热键调用
只读连接:
集群模式下从节点不接受任何读写请求,被转发到对应的master上
分担读压力,使用readonly打开只读状态
只读流程:如果槽属于正在复制的主节点,直接执行命令,负责重定向
readonly命令时连接级别,每次新建命令都要
读写分离:
复制延迟,读取过期数据,从节点故障
集群提供cluster slave {nodeId}获取从节点
不提倡使用
从节点执行cluster failover执行切换流程
应用于:
主节点迁移(新旧机器迁移)
强制故障转移(主从节点同时故障)
从节点与主节点复制断线时间超过cluster-slave-validity-factor*cluster-node-timeout+repl-ping-slave-period
网络不稳定,无法在cluster-node-timeout*2时间内完成发现转移
集群超过一半以上主节点同时故障
cluster failover提供
force:不再请求master的偏移量,直接替换并广播
takeover:用于超一半主节点故障,会导致配置纪元冲突,会采用配置纪元大的(纪元冲突采用nodeId大的)
和雪球当前方案一样redis-migrate-tool
1.LRU/LFU/FIFO
maxmemory-policy缓存使用量超过预设最大值
一致性最差,由算法决定
2.超时剔除
给缓存数据添加过期时间
一致性由expire决定
3.主动更新
利用消息系统或者其他方式通知更新缓存
一致性最高,搭配expire更好
4.最佳实践
低一致性配置最大内存和淘汰策略
高一致性超时剔除+主动更新
缓存粒度:
业务代码或者数据问题,恶意攻击、爬虫导致
1.缓存空值
优点:保护后端数据源 数据压力
缺点:意味着更多的空间(如果是攻击,问题就严重了)、缓存和存储有一个时间窗口不一致
2.布隆过滤器拦截
在访问缓存和存储前,将存在的key用布隆过滤器提前保存起来做第一层拦截
https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
增加节点,性能不增加反而降低
命令优化,例如优化SQL语句
减少网络通信次数
降低接入成本(长连接、连接池、NIO)
1.保证缓存层服务的高可用性
2.依赖隔离组件为后端限流并降级https://github.com/netflix/hystrix
3.故障演练,上线前就关闭缓存压测一下
问题:
热点key(例如热门的新闻事件)并发量贼大
重建缓存不能短时间内完成(复杂计算,sql、io、多依赖等)
在缓存失效期间大量线程重建缓存造成后端压力骤增
解决:
减少重建次数、数据尽可能一致、较少的潜在危险
互斥锁:等上一个把缓存整出来、先看看有没有
永不过期:缓存方面、功能方面(逻辑过期时间)
1.vm.overcommit_memory
设置为1(cat /proc/sys/vm/overcommit_memory),不然log会有提示
最佳实践
Redis合理设置maxmemory保证机器有20%~30%的空闲
集中化管理AOF和RDB的bgsave
设置vm.overcommit_memory=1,防止极端情况下fork失败
2.swappiness
百分比会决定操作系统使用swap的倾向程度,越大倾向越高(默认60,cat /proc/sys/vm/swappiness)
free -m、vmstat 1、cat /proc/{pid}/smaps |grep Swap
Linux>3.5 vm.swapniess=1 : vm.swapniess=0
3.THP
Linux2.6.38之后默认开启,内存页从4KB变为2MB,建议禁用(echo never > /sys/kernel/mm/transparent_hugepage/enabled)
4.OOM killer
会在可用内存不足时杀掉用户进程,根据每个进程的权值(越高越被杀,cat /proc/{pid}/oom_score)
这个值受(cat /proc/{pid}/oom_adj)控制,当oom_adj为最小值时该进程不会被杀掉
5.NTP
网络时间协议,保证不同机器时钟一致性
6.ulimit
查看和设置当前用户进程的资源数,open files是单个用户打开的最大文件个数
maxclient+32是redis的进程数(ulimit -Sn {max-open-files})
7.TCP backlog
在linux系统内核中维护了两个队列:syns queue和accept queue,https://www.jianshu.com/p/e6f2036621f4
redis默认值511(cat /proc/sys/net/core/somaxconn)
这个值不能小于redis的默认值,这个是Linux半连接请求(syns queue)
被误flush后,根据缓存还是存储策略不同
缓存:就是个简单的缓存穿透
存储:影响巨大
AOF:
auto-aof-rewrite-percentage、auto-aof-rewrite-min-size看看aof是不是重写了(调大这个参数),拒绝手动bgrewriteaof
删除掉flush这个命令,用redis-check-aof修复AOF文件
RDB:
save {time} {times}配置文件,防止手动bgsave
flush涉及的key较多,RDB会被清除,取决于RDB是什么时候备份的
最佳实践:
使用shell脚本
伪装危险命令:keys、flushall/flushdb、save、debug、config、shutdown
AOF和RDB不要,不然redis无法重启
主从节点要配置一致
使用防火墙限制ip port只开放80
bind绑定的是网卡,可以设置多个
定期备份数据
不使用默认端口
不使用root作为管理员
字符串一般超过10kb都是大key了,和ops相关
集合类型一般是元素个数过多
危害:
内存空间不均匀
超时阻塞
网络拥塞
处理:
redis-cli --bigkeys统计(debug object key可以查看key的字节数)
被动收集:抛异常时打印所有的key
主动检测:scan+debug object(推荐,键过多可以使用pipeline,从节点上执行,避免阻塞)
删除:
string直接del
集合类型先scan,再pipeline逐个del filed
1.客户端,每次调用redis命令时使用字典记录
缺点:
无法预知keygeshu,存在内存泄漏
对代码侵入,多个语言维护困难
只能了解客户端热点key,无法规模化运维
2.代理端(Twemproxy、Codis)
3.redis服务端
使用monitor命令
Facebook的redis-faina(尽可能在本机执行,存在单点,影响线上性能问题)
4.机器
对TCP抓包,采用ELK体系下的packetbeat插件(也可以对MySQL检测)
处理热点key:
拆分复杂数据结构
迁移热点key,将热点slot单独迁到一个节点上
本地缓存加通知机制(发布订阅解决不一致问题)