代码规范 —— Redis 开发规范

优质博文:IT-BLOG-CN

一、开发规范

【1】弱依赖检查与线下确认:Redis必须是弱依赖,即Redis宕机不影响业务。包括超时检查。

【2】是否当存储使用检查:Redis不能作为存储设备来使用,只能作为缓存或状态等场景来使用。存储优先使用本地缓存。

【3】超时时间检查与线下确认:Redis使用需要设置超时时间。如果超时,对应的策略和方案是什么。

【4】无状态检查:Redis同一个Key不能被不同的应用,不同的场景使用。谁生产,谁消费的原则。

【5】同步锁检查:优先使用集团框架提供的分布式锁。

【6】Key检查:Key的唯一性是否存在明显问题,与其他场景和应用的重名的可能。Key的长度,尽可能的小于128字节,禁止超过1024简洁性

保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id不要包含特殊字符,反例:包含空格、换行、单双引号以及其他转义字符需要规范(car+应用名+业务名+具体id

【7】审批记录检查:是否已经在审批记录conf完整记录,包括审批人。

二、场景使用

合理使用数据结构: Redis支持的数据库结构类型较多:字符串String,哈希Hash,列表List,集合Set,有序集合Sorted Set, Bitmap, HyperLogLog和地理空间索引geospatial redis命令

需要根据业务场景选择合适的类型,常见的如:

【1】String可以用作普通的K-V、计数类;

【2】Hash可以用作对象如商品、经纪人等,包含较多属性的信息;

【3】List可以用作消息队列(不推荐)、粉丝/关注列表等;

【4】Set可以用于推荐;

【5】Sorted Set可以用于排行榜等;

三、键值设计

key设计:

【1】可读性和可管理性【建议】

☑️ 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔。

☑️ 应用名:表名:id

【2】简洁性,key长度适中【建议】

☑️ 保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视。

eg:user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}

【3】不要包含特殊字符【强制】

☑️ 禁止包含特殊字符如空格,换行,单双引号,其他转义字符。

【4】Key个数限制【强制】

☑️ 由于Redis Rehash机制,实例Key数量达到一定值rehash操作时,需要有一定量空闲内存资源,如key达到134217728rehash需要有2gb空闲内存资源,达到268435456时,rehash需要有4gb空闲内存资源。如果没有组够的内存资源rehash时会发生Key剔除(数据丢失/程序超时/甚至引起切换)。

单实例key个数达到134217728已经很大了,实例元素过大对于后续分析rdb遍历大key时会非常耗时。

四、value设计

【1】拒绝bigkey(防止网卡流量、慢查询)

☑️ 防止网卡流量、慢查询,string类型控制在10KB以内,hashlistsetzset元素个数不要超过5000

☑️ 非字符串的bigkey,不要使用del删除,使用hscansscanzscan方式渐进式删除,同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,而且该操作不会出现在慢查询中(latency可查))

☑️ credis页面,群集所有者可以通过unlink异步清理或小批量迭代清理(或提事件给DBA来处理)

【2】一定要设置过期时间,当实例写满,根据volatile-lru淘汰老的数据

☑️ redis只是缓存,不能当成数据库来用。不设置过期时间,redis实例大小会一直无限增长,会出现机器内存耗尽、故障恢复耗时特别长等问题。

☑️ 建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime(该命令返回的是当前键从上一次访问到现在经过的时间(单位,秒))

☑️ DBA会定期对redis集群中过期时间超过1年的数据做告警处理。

五、命令使用

【1】禁用KEYS正则匹配,可用SCAN代替

☑️ 禁止线上使用keysflushallflushdb等,通过redisrename机制禁掉命令,或者使用scan的方式渐进式处理。

【2】O(N)命令关注N,控制集合元素尽可能小

☑️ hgetall/lrange/smembers/zrange等在集合包含元素个数较少的情况下使用。

☑️ 若规模较大,有遍历需求,可用HSCAN/SSCAN/ZSCAN渐进式遍历。

【3】合理使用select

☑️ redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。

【4】Redis事务支持较弱,不建议过多使用

☑️ redis的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot上(可以使用hashtag功能解决)

【5】线上禁止使用monitor命令

☑️ 禁止生产环境使用monitor命令,monitor命令在高并发条件下,会存在内存暴增和影响Redis性能的隐患。

【6】使用批量操作提高效率

☑️ 原生命令:例如mgetmset

☑️ 非原生命令:可以使用pipeline提高效率。

☑️ 但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关)。
注意两者不同:

1、原生是原子操作,pipeline是非原子操作。

2、pipeline可以打包不同的命令,原生做不到。

3、pipeline需要客户端和服务端同时支持。

六、数据保存

【1】容量合理评估

☑️ 在系统设计阶段,需要考虑当前redis集群的容量是否足够,设置合理的大小和过期时间

1、内存使用率保持在[50%~85%]之间。

2、使用率<50%需要考虑缩容。

3、使用率>85%需要考虑扩容。

【2】冷热数据分离

☑️ 虽然Redis支持持久化,但是Redis的数据存储全部都是在内存中的,成本昂贵。

☑️ 建议根据业务只将高频热数据存储到Redis中【QPS大于5000】,对于低频冷数据可以使用MySQL/ElasticSearch/MongoDB等基于磁盘的存储方式,不仅节省内存成本,而且数据量小在操作时速度更快、效率更高。

【3】不同的业务数据要分开存储

☑️ 不要将不相关的业务数据都放到一个Redis实例中,建议新业务申请新的单独实例。

☑️ 因为Redis为单线程处理,独立存储会减少不同业务相互操作的影响,提高请求响应速度;同时也避免单个实例内存数据量膨胀过大,在出现异常情况时可以更快恢复服务。

【4】必须要存储的大文本数据一定要压缩后存储

☑️ 对于大文本【一般超过500字节】写入到Redis时,建议要压缩后存储。

☑️ 大文本数据存入Redis,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪

相关推荐
路在脚下@6 分钟前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
森屿Serien9 分钟前
Spring Boot常用注解
java·spring boot·后端
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader2 小时前
深入解析 Apache APISIX
java·apache
了一li2 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭2 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
码农君莫笑2 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程