前言:本文档根据约束力强弱及故障敏感性,规约依次分为强制、推荐、参考三大类。对于规约条目的延伸信息中,“说明”对内 容做了适当扩展和解释;“正例” 倡什么样的编码和实现方式;“反例”说明需要 防的雷区,以及真实的错误案例。
1.【强制】Redis的key定义为多个具有独立意义的字符串由冒号“:”拼接而成,在做MySQL数据表缓存时,“具有独立意义的字符串”强制定义为数据表的单个字段,并且将格式约定为:表名:字符串1:字符串2:·····。
说明:数据表的单个字段本身就是一个具有独立意义的字符串,在做Redis缓存时不再对该字符串做拆分、拼接。Redis在做其它存储用途时,可以通过拆分一个字符串、拼接多个字符串以及直接使用单个字符串等多种手段形成“具有独立意义的字符串”。
正例:话费黑名单存储在Redis中时,在功能上都可以的情况下,可以采用“configcache:fee:blacklist”作为key,也可以使用“configcache:feeblacklist”作为key,前者认为fee和blacklist分别是具有独立意义的字符串,后者认为feeblacklist是具有独立意义的字符串。
待讨论:使用何种机制保证key值的唯一性。
2.【强制】禁止使用Keys正则匹配操作,包括但不限于各种形式的模糊匹配操作。
说明:Redis是单线程处理,在线上KEY数量较多时,操作效率极低(时间复杂度为O(N)),该命令一旦执行会严重阻塞线上其它命令的正常请求,而且在高QPS情况下会直接造成Redis服务崩溃。
3.【强制】将对象写入Redis时使用fastToJson序列化方式。
说明:统一序列化方式。
4.【强制】避免多个应用使用同一个Redis实例
说明:redis是单线程作业,因此不要把多个应用放在一个redis实例,这样会降低每个业务的吞吐量,必要的时候一个应用我们也可以针对不用的功能点使用多个redis实例。
5.【推荐】程序需要处理如果redis数据丢失时的重新加载的过程。
6.【推荐】存储的Key尽可能设置超时时间。
说明:如果应用将Redis定位为缓存Cache使用,对于存放的Key要尽可能设置超时时间。因为若不设置,这些Key会一直占用内存不释放,造成极大的浪费,而且随着时间的推移会导致内存占用越来越大,直到达到服务器内存上限!另外Key的超时长短要根据业务综合评估,而不是越长越好。
待讨论1:什么样的时间比较合适。定义MySQL缓存的时间,其它场景按需设置。
7.【推荐】选择合适的数据类型,在不能确定其它复杂数据结构一定优于String类型时,避免使用Redis的复杂数据结构,复杂类型对象指的是hash,set之类的非string对象。
说明:每种数据结构都有相应的使用场景,String类型是Redis中最简单的数据类型,推荐使用String类型。但是考虑到具体的业务场景,综合评估性能、存储、网络等方面之后使用适当的数据结构。
8.【推荐】将一个Redis实例的所有操作集中封装在一个类中。
说明:Redis自由度非常大,key有各种各样的形式,将所有的操作集中在一个类中,便于管理。
9.【参考】尽可能使用不要超过1M大小的kv。
说明:如果将redis作为cache进行频繁读写和超时删除等,此时应该避免设置较大的k-v,因为这样会导致redis的 内存碎片增加,导致rss占用较大,最后被操作系统OOM killer干掉。参考值:flowsal中的order表,100条记录占用redis的内存为1.07M
10.【参考】如果出现频繁对string进行append操作,则请使用list进行push操作,取出时使用pop。这样避免string频繁分配内存导致的延时。