DCS使用规范
业务使用规范
原则 |
原则说明 |
备注 |
---|---|---|
就近部署业务,避免时延过大 |
如果部署位置过远(非同一个region)或者时延较大(例如业务服务器与Redis实例通过公网连接),网络延迟将极大影响读写性能。 |
如果对于时延较为敏感,请避免创建跨AZ Redis实例。 |
冷热数据区分 |
建议将热数据加载到 Redis 中。低频数据可存储在 Mysql或者ElasticSearch中。 |
Redis将低频数据存入内存中,并不会加速访问,且占用Redis空间。 |
业务数据分离 |
避免多个业务共用一个Redis。 |
一方面避免业务相互影响,另一方面避免单实例膨胀,并能在故障时降低影响面,快速恢复。 |
禁止使用select功能在单Redis实例做多db区分。 |
Redis单实例内多DB隔离性较差,Redis开源社区已经不再发展多DB特性,后续不建议依赖该特性。 |
|
设置合理的内存淘汰(逐出)策略 |
合理设置淘汰策略,可以在Redis内存意外写满的时候,仍然正常提供服务。 |
DCS默认的逐出策略为volatile-lru,请根据业务需求选择。Redis支持的数据逐出策略 |
以缓存方式使用Redis |
Redis事务功能较弱,不建议过多使用。 |
事务执行完后,不可回滚。 |
数据异常的情况下,支持清空缓存进行数据恢复。 |
Redis本身没有保障数据强一致的机制和协议,业务不能强依赖Redis数据的准确性。 |
|
以缓存方式使用Redis时,所有的key需设置过期时间,不可把Redis作为数据库使用。 |
失效时间并非越长越好,需要根据业务性质进行设置。 |
|
防止缓存击穿 |
推荐搭配本地缓存使用Redis,对于热点数据建立本地缓存。本地缓存数据使用异步方式进行刷新。 |
- |
防止缓存穿透 |
非关键路径透传数据库,建议对访问数据库进行限流。 |
- |
从Redis获取数据未命中时,访问只读数据库实例。可通过域名等方式对接多个只读实例。 |
核心是未命中的缓存数据不会打到主库上。 用域名对接多个只读数据库实例,一旦出现问题,可以增加只读实例应急。 |
|
不用作消息队列 |
发布订阅场景下,不建议作为消息队列使用。 |
|
合理选择规格 |
如果业务增长会带来Redis请求增长,请选择集群实例(Proxy集群和Cluster集群) |
单机和主备扩容只能实现内存、带宽的扩容,无法实现计算性能扩容。 |
生产实例需要选择主备或者集群实例,不能选用单机实例 |
- |
|
主备实例,不建议使用过大的规格。 |
Redis在执行RewriteAOF和BGSAVE的时候,会fork一个进程,过大的内存会导致卡顿 |
|
具备降级或容灾措施 |
缓存访问失败时,具备降级措施,从DB获取数据;或者具备容灾措施,自动切换到另一个Redis使用。 |
- |
数据设计规范
分类 |
原则 |
原则说明 |
备注 |
---|---|---|---|
Key相关规范 |
使用统一的命名规范。 |
一般使用业务名(或数据库名)为前缀,用冒号分隔。Key的名称保证语义清晰。 |
例如,业务名:子业务名:id |
控制Key名称的长度。 |
在保证语义清晰的情况下,尽量减少Key的长度。有些常用单词可使用缩写,例如,user缩写为u,messages缩写为msg。 |
建议不要超过128字节(越短越好)。 |
|
禁止包含特殊字符(大括号“{}”除外)。 |
禁止包含特殊字符,如空格、换行、单双引号以及其他转义字符。 |
由于大括号“{}”为Redis的hash tag语义,如果使用的是集群实例,Key名称需要正确地使用大括号避免分片不均的情况。 |
|
Value相关规范 |
设计合理的Value大小。 |
设计合理的Key中Value的大小,推荐小于10 KB。 |
过大的Value会引发分片不均、热点Key、实例流量或CPU使用率冲高等问题,还可能导致变更规格和迁移失败。应从设计源头上避免此类问题带来的影响。 |
设计合理的Key中元素的数量。 |
对于集合和列表类的数据结构(例如Hash,Set,List等),避免其中包含过多元素,建议单Key中的元素不要超过5000个。 |
由于某些命令(例如HGETALL)的时间复杂度直接与Key中的元素数量相关。如果频繁执行时间复杂度为O(N)及以上的命令,且Key中的子Key数量过多容易引发慢请求、分片流量不均或热点Key问题。 |
|
选择合适的数据类型。 |
合理地选择数据结构能够节省内存和带宽。 |
例如存储用户的信息,可用使用多个key,使用set u:1:name "X"、set u:1:age 20存储,也可以使用hash数据结构,存储成1个key,设置用户属性时使用hmset一次设置多个,同时这样存储也能节省内存。 |
|
设置合理的过期时间。 |
合理设置Key的过期时间,将过期时间打散,避免大量Key在同一时间点过期。 |
设置过期时间时,可以在基础值上增减一个随机偏移值,避免在同一个时间点大量Key过期。大量Key过期会导致CPU使用率冲高。 |
命令使用规范
原则 |
原则说明 |
备注 |
---|---|---|
谨慎使用O(N)复杂度的命令 |
时间复杂度为O(N)的命令,需要特别注意N的值。避免N过大,造成Redis阻塞以及CPU使用率冲高。 |
例如:hgetall、lrange、smembers、zrange、sinter这些命令都是做全集操作,如果元素很多,会消耗大量CPU资源。可使用hscan、sscan、zscan这些分批扫描的命令替代。 |
禁用高危命令 |
禁止使用flushall、keys、hgetall等命令,或对命令进行重命名限制使用。 |
请参考命令重命名的内容。 |
慎重使用select |
Redis多数据库支持较弱,多业务用多数据库实际还是单线程处理,会有干扰。最好是拆分使用多个Redis。 |
- |
使用批量操作提高效率 |
如果有批量操作,可使用mget、mset或pipeline,提高效率,但要注意控制一次批量操作的元素个数。 |
mget、mset和pipeline的区别如下:
|
避免在lua脚本中使用耗时代码 |
lua脚本的执行超时时间为5秒钟,建议不要在lua脚本中使用比较耗时的代码。 |
比如长时间的sleep、大的循环等语句。 |
避免在lua脚本中使用随机函数 |
调用lua脚本时,建议不要使用随机函数去指定key,否则在主备节点上执行结果不一致,从而导致主备节点数据不一致。 |
- |
遵循集群实例使用lua的限制 |
遵循集群实例使用lua的限制。 |
|
对mget,hmget等批量命令做并行和异步IO优化 |
某些客户端对于MGET,HMGET这些命令没有做特殊处理,串行执行再合并返回,效率较低,建议做并行优化。 |
例如Jedis对于MGET命令在集群中执行的场景就没有特殊优化,串行执行,比起lettuce中并行pipeline,异步IO的实现,性能差距可达到数十倍,该场景建议使用Jedis的客户端自行实现slot分组和pipeline的功能。 |
禁止使用del命令直接删除大Key |
使用del命令直接删除大Key(主要是集合类型)会导致节点阻塞,影响后续请求 |
Redis 4.0后的版本可以通过UNLINK命令安全地删除大Key,该命令是异步非阻塞的。 对于Redis 4.0之前的版本:
|
SDK使用规范
原则 |
原则说明 |
备注 |
---|---|---|
使用连接池和长连接 |
短连接性能差,推荐使用带有连接池的客户端。 |
连接的频繁创建和销毁,会浪费大量的系统资源,极限情况会造成宿主机宕机。请确保使用了正确的Redis客户端连接池配置。 |
客户端需要对可能的故障和慢请求做容错处理 |
由于Redis服务可能因网络波动或基础设置故障的影响,引发主备倒换,命令超时或慢请求等现象,需要在客户端内设计合理的容错重试机制。 |
参考Redis客户端重试指南。 |
合理设置重试时间和次数 |
合理设置容错处理的重试时间,根据业务要求设置,避免过短或者过长。 |
|
避免使用Lettuce客户端 |
Lettuce客户端在默认配置下有一定性能优势,并且是spring的默认客户端,但是Jedis客户端在面对连接异常,网络抖动等场景下的异常处理和检测能力明显强于Lettuce,可靠性更强,建议使用Jedis。 |
Lettuce存在几个方面的问题:
|
运维管理规范
原则 |
原则说明 |
备注 |
---|---|---|
生产开启密码保护 |
生产系统中需要开启Redis密码保护机制。 |
- |
现网操作安全 |
禁止开发人员私自连到线上Redis服务。 |
- |
验证业务的故障处理能力或容灾逻辑 |
在测试环境或者预生产环境中组织演练,验证在Redis主备倒换、宕机或者扩缩容场景下业务的可靠性。 |
主备倒换可以自行在页面上触发。强烈建议使用Lettuce客户端的应用进行相关的演练。 |
监控实践 |
关注Redis负载,在过载前提前扩容。 |
根据告警基线配置告警:配置节点cpu、内存、带宽等告警。 |
日常巡检 |
例行检查各个节点的内存使用率,查看主节点内存使用率是否有不均衡的状态。 |
内存使用率不均衡说明存在大Key问题,需要进行大Key拆分及优化。 |
开启热Key例行分析,并分析是否有Key频繁调用。 |
- |
|
例行诊断Redis实例的命令,分析O(N)类命令是否存在隐患。 |
针对O(N)命令,即使耗时很小,建议开发分析业务增长,N是否会增长。 |
|
例行巡检Redis慢日志命令。 |
针对慢日志分析隐患,并尽快从业务上进行修复。 |