缓存在咱们平常开发中占据着举足轻重的地位,经过缓存组件可让咱们的系统有着多方位的提高空间。而Redis就一个表明性的缓存组件。正巧最近使用Redis比较频繁,因此打算经过文章记录一下在Redis开发中遇到的问题和一些开发规范。文章已发布在Github,将会持续保持更新,欢迎star和补充git
Key的设计
易于管理
即能经过名称大概知道所涉及业务。一般咱们会以service:characteristics来进行命名,如pubg_chat:uid:room_id的形式,这样能够尽量避免冲突(固然,不一样业务使用不一样的Redis是更好的)github
尽可能简洁
Redis本质上是一个内存数据库,而内存的大小是远小于硬盘的。若是Key过大的话,会致使Redis所能存储的内容变少。因此在平常中推荐Key可以尽量的简介明了,用缩写来代替完整的单词redis
避免特殊字符
如逗号、换行、空格和引号等转义字符都是不该该使用的算法
设置生命周期
- Redis不该当成为一个永久存储的组件,为每个Key都设置他的过时时间
- 若是确实须要Redis永久存储某类内容,那么因当采用异步“续命”的方式来进行,而不该该在一开始就为其设置永久的生命周期,避免后续须要变动时带来的维护灾难
Value的使用
规避大Key!
- Redis单线程的,它会在执行完一个命令后才会执行其余命令
- 首先大Key在传输键值对时,会对网络形成压力(带宽问题),而且有的proxy会将大内容分片传输,进而再次增长了网络传输时间
- 其次,如list、hash这类结构,若是使用O(n)的指令或者使用del命令,那么会形成严重的阻塞
- 因此一般而言,string 类型控制在 10KB 之内,hash、list、set、zset 元素个数不要超过 5000
- ps:一般可采用hash的方式分割大key
value的压缩
可考虑使用protobuf、MessagePack等方式进行序列化,这样一能够提高redis的利用率,二提升了序列化的效率,三是能提供value跨语言的能力数据库
命令使用
避免频繁对string作append
能够考虑使用list进行替代数组
集合类操做
- O(n)指令应注意。对于set,zset,list,hash等集合类,应注意O(n)命令对于性能的影响。一般应该避免直接使用O(n)指令,可用HSCAN,SSCAN,ZSCAN进行渐进操做,防止命令的阻塞
- 渐进式删除。不该该直接使用del,而应该本身写脚本一点点的删除
禁用危险命令
keys、flushall、flushdb......这种不用多说,一来直接Redis就懵圈了,人也楞了缓存
合理利用Pipeline模式
- 在mget大量数据时,proxy会拆包和解包,会致使proxy层的压力增长,而pipeline模式会直接转发。因此在批量获取的状况下,pipeline的效率通常都会优于mget
- 同时应该注意两点:
- mget是原子操做,pipeline不是。因此业务上不可盲目采用
- pipeline是能够发送不一样命令的,固然使用lua也能够实现这一点
避免没必要要的指令
如部分Redis Client会有TestOnBorrow之类的探测指令,在没有特殊要求的状况下应当避免此类指令,以减少redis负载和网络压力安全
对Lua应当作特殊要求
- 全部key都应该由KEYS数组来传递
- 全部value都应该由ARGS数组来传递
- 全部key,必须在1个slot上
性能查询指令
- slowlog get,查询慢命令
- info commandstats,查询执行过的命令信息,包含用时和次数等
- client list,查询引发阻塞的命令
客户端使用
避免混用实例
不一样的业务线应该作到实例的拆分,避免混用致使的连锁问题:如key重合、命令阻塞等网络
使用链接池
每次使用都新建链接会有几个问题:app
- 形成redis的负担增长
- 浪费网络资源
- 影响执行效率
- 难以维护
熔断
Redis本质也是一个“服务”,因此熔断机制不可少
鉴权
避免无关服务的滥用或致使数据出错
避免做为消息队列
Redis其实还可以支持消息队列的应用,但其读写效率是不及其余MQ如Kafka、RabbitMQ等。且因为其结构的设置,不太可以支撑MQ的一些主要特性,因此应当避免使用。
其余
淘汰策略
根据⾃⾝业务类型,选好maxmemory-policy(最⼤内存淘汰策略),设置好过时时间 默认策略是volatile-lru,即超过最⼤内存后,在过时键中使⽤lru算法进⾏key的剔除,保证不过时数据不被 删除,可是可能会出现OOM问题
- allkeys-lru:根据LRU算法删除键,无论数据有没有设置超时属性,直到腾出⾜够空间为⽌
- allkeys-random:随机删除全部键,直到腾出⾜够空间为⽌。
- volatile-random:随机删除过时键,直到腾出⾜够空间为⽌
- volatile-ttl:根据键值对象的ttl属性,删除最近将要过时数据。若是没有,回退到noeviction策略
- noeviction:不会剔除任何数据,拒绝全部写⼊操做并返回客⼾端错误信息"(error) OOM command not allowed when used memory",此时Redis只响应读操做
- 4.0后推出的allkey-lfu和volatile-lfu
- 能够认为这是对于lru算法的进一步改进
- allkey-lfu:从全部键中驱逐使用频率最少的键
- volatile-lfu:从全部配置了过时时间的键中驱逐使用频率最少的键
不滥用Redis事务
Redis事务不像DB的事务这么“安全”,也不支持回滚,因此不该当过多的使用。由于这块我没怎么使用过,详见官方文档
参考资料