redis规范

1. 总体要求

Redis主要用于缓存处理,加快读取效率,但在使用过程中需要注意合理的使用,一般存储全局配置数据和一些访问非常频繁的较为静态的数据,另外注意过期时间控制,减少资源的不必要消耗。

Redis–不要触碰边界

Redis的边界

–红色区域代表危险

在这里插入图片描述

计算方面:Wildcard、Lua并发、1对N PUBSUB、全局配置/热点,会大量消耗计算资源(高计算消耗);

存储方面:Streaming慢消费、Bigkey等,造成高存储消耗。

网络方面:Keys等扫全表、Huge Batch mget/mset、大Value、Bigkey Range (如hgetall,smembers),造成高网

络消耗。

Redis的边界总结:

  • 高并发不等于高吞吐

大 Value 的问题:高速存储并不会有特别大的高吞吐收益,相反会很危险;

  • 数据倾斜和算力倾斜

bigKey 的问题:break掉存储的分配律;

热点的问题:本质上是cpu上的分配律不满足;

大 Range 的问题:对NoSQL的慢查询和导致的危害没有足够的重视。

  • 存储边界

Lua使用不当造成的成本直线上升;

数据倾斜带来的成本飙升,无法有效利用;

  • 对于 Latency 的理解问题(RT高)

存储引擎的 Latency 都是P99 Latency,如:99.99%在1ms以内,99.5%在3ms以内,等;

偶发性时延高是必然的。这个根因在于存储引擎内部的复杂性和熵。

Redis–阿里内部开发规约

每次 redis 操作设计前,请重点关注以下建议


推荐:

- 确定场景,是缓存(cache)还是存储型;

- Cache的使用原则是:“无它也可,有它更强”;

- 永远不要强依赖Cache,它会丢,也会被淘汰;

- 优先设计合理的数据结构和逻辑;

- 设计避免bigKey,就避免了80%的问题;

- Keyspace能分开,就多申请几个Redis实例;

- pubsub不适合做消息分发;

- 尽量避免用lua做事务。



不建议:

- 我的服务对RT很敏感。 >> 低RT能让我的服务运行的更好;

- 我把存储都公用在一个redis里。 >> 区分cache和内存数据库用法,区分应用;

- 我有一个大排行榜/大集合/大链表/消息队列;我觉得服务能力足够了。 >> 尽量拆散,服务能力不够可通过分布式集群版可以打散;

- 我有一个特别大的Value,存在redis里,访问能好些。 >> redis吞吐量有瓶颈。

2. Key名设计

  1. 【强制】Redis key 名前缀遵循可读性和可管理性,以项目缩写为前缀(防止key冲突),用冒号分隔,比如项目缩写:模块简码:功能简码

正例:

项目级固定段:项目缩写,例:ecp:

模块级固定段:项目缩写:模块简码,例:ecp:device

功能级固定段:项目缩写:模块简码:功能简码,例:ecp:device:heart

  1. 【推荐】Redis key 命名采用小写结构,不采用驼峰格式,中间利用下滑线 _ 做连接。

正例:缩写后 ecp:device:app_auth

  1. 【强制】Redis key 名前缀遵循简洁性,保证语义的前提下,控制key的长度,允许适当使用英文缩写。

反例:ecp:device:last_heartbeat_time

正例:缩写后 ecp:device:lht

  1. 【强制】不使用特殊字符(不包括冒号:,下划线_)。

反例:包含空格、换行、单双引号以及其他转义字符

3. Value设计

  1. 【强制】拒绝 BigKey(防止网卡流量、慢查询),string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000。

  2. 【强制】选择适合的数据类,合理控制和使用数据结构内存编码优化配置,但也要注意节省内存和性能之间的平衡。

反例:set ecp:device:deviceheart:{product_key}:{device_key} ONLINE

  1. 【推荐】控制 key 的生命周期,建议使用expire设置过期时间,条件允许可以打散过期时间,防止集中过期。

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

  3. 【推荐】不同的业务数据要分开存储。不要将不相关的业务数据都放到一个Redis实例中,建议新业务申请新的单独实例。因为Redis为单线程处理,独立存储会减少不同业务相互操作的影响,提高请求响应速度;同时也避免单个实例内存数据量膨胀过大,在出现异常情况时可以更快恢复服务。

4. 命令使用

  1. 【强制】禁止线上使用keys、flushall、flushdb等命令,通过 redis 的 rename 机制禁掉命令,或者使用scan的方式渐进式处理。

  2. 【推荐】O(N)命令关注N的数量,例如hgetall、lrange、smembers、zrange、sinter等并非不能使用,但是需要明确 N 的值。有遍历的需求可以使用hscan、sscan、zscan代替。

  3. 【推荐】使用批量操作提高效率,但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关)。

正例:

原生命令:例如mget、mset

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


注意:

a. 原生是原子操作,pipeline是非原子操作。

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

c. pipeline需要客户端和服务端同时支持。

  1. 【推荐】Redis事务功能较弱,不建议过多使用。Redis 的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个 slot 上(可以使用 hashtag 功能解决)

  2. 【推荐】必要情况下使用 monitor 命令时,要注意不要长时间使用。

  3. 【推荐】不建议使用 redis 发布订阅(PUB/SUB)功能,不稳定,不可靠

5. 客户端配置

  1. 【推荐】客户端创建连接池时需要根据实际情况设置连接数大小,可以参考以下几个因素:

并发量:如果你的应用程序具有高并发的特点,可以增加连接数的值,以确保有足够的连接可供同时使用。例如,如果你预计同时可能有数百个并发请求,可以将连接数设置为几百。

系统负载:考虑到 Redis 服务器的负载情况,确保连接数不超过服务器可以承受的最大连接数。如果你的 Redis 服务器在高负载时响应变慢,可能是由于连接数过多导致的。

资源限制:请记住,每个连接都需要占用一定的内存和网络资源。确保你的系统有足够的资源来支持所设置的连接数值。

根据以上考虑因素,你可以尝试使用一些初始值,并通过基准测试和监控来调整连接数的值,以找到适合你应用程序需求的最佳设置。

需要注意的是,过大的连接数值可能会导致连接资源浪费和系统负担增加,而过小的值可能会导致连接瓶颈和性能下降。因此,根据实际情况进行测试和调整是很重要的。

5.1 Golang 相关

  1. 【推荐】建议使用 go-redis github.com/redis/go-redis

  2. 【推荐】若使用 redigo 创建连接池,请务必正确设置MaxIdle参数。如果不设置MaxIdle参数或将其设置为 0,连接池将不会保留任何空闲连接。这意味着每次需要使用 Redis 连接时,都会创建新的连接。这样可能导致频繁地创建和销毁连接,增加了连接的开销和延迟


func newPool(server, password string) *redis.Pool {

    return &redis.Pool{

        // 表示连接池中最大的空闲连接数

        MaxIdle:     10,

        // 表示同时可以从连接池中分配的最大连接数

        MaxActive:   100,

        // 表示连接在连接池中的空闲超时时间

        IdleTimeout: 240 * time.Second,

        // 用于创建 Redis 连接

        Dial: func() (redis.Conn, error) {

            // 未设置 DB,默认使用 DB0,根据实际情况选择 DB

            c, err := redis.Dial("tcp", server)

            if err != nil {

                return nil, err

            }

            if password != "" {

                if _, err := c.Do("AUTH", password); err != nil {

                    c.Close()

                    return nil, err

                }

            }

            return c, err

        },

        // 用于测试连接是否可用

        TestOnBorrow: func(c redis.Conn, t time.Time) error {

            _, err := c.Do("PING")

            return err

        },

    }

}

  1. 【推荐】go-redis 创建连接池示例

func NewRedisClient() *redis.Client {

    return redis.NewClient(&redis.Options{

        Addr:     "localhost:6379",

        Password: "", // 如果没有设置密码,可以留空

        DB:      0,

        PoolSize: 10, // 连接池中最大的连接数

    })

}

5.2 JAVA 相关

** 【推荐】 **使用jedis连接池,需要根据业务情况配置以下属性(单实例模式)

redis:
   # spring.redis.database: redis使用的数据库索引0-15。默认 0
   database: 0
   # spring.redis.timeout: redis连接超时时间 默认3000
   timeout: 3000
   redisTemplate:
     # spring.redis.redisTemplate.enableTransactionSupport: 配置redisTemplate事务模式。默认开
     enableTransactionSupport: true
   # spring.redis.host: reids地址
   host: ${REDIS_HOST}
   # spring.redis.port: reids端口
   port: ${REDIS_PORT}
   # spring.redis.password: redis登录密码
   password: ${REDIS_PASSWORD}

** 【推荐】 **使用lettuce连接池,需要根据业务情况配置以下属性(单实例模式)

redis:
   timeout: 5000
   host: ${REDIS_HOST}
   port: ${REDIS_PORT}
   password: ${REDIS_PASSWORD:}
   lettuce:
     pool:
       max-active: 8
       # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
       max-wait: -1
       # 连接池中的最大空闲连接 默认 8
       max-idle: 8
       # 连接池中的最小空闲连接 默认 0
       min-idle: 0   

** 【推荐】 **使用redisson连接池,需要根据业务情况配置以下属性(单实例模式)
redisson官方配置文档

redisson:
 # 连接超时时间
 timeout: 10000
 # 模式 com.hzsun.micp.cloud.redisson.enums.Model
 model: SINGLE
 # 密码
 password: ${REDIS_PASSWORD}
 # 客户端名称
 clientName: micp
 # 等待加锁超时时间 -1一直等待
 attemptTimeout: 10000
 singleServerConfig:
   database: ${REDIS_DATASOURCE}
   # 集群地址
   address: ${REDIS_PATH}
 # 这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。默认2
 threads: 4
 # 这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。默认2
 nettyThreads: 4
 # 传输模式
 transportMode: NIO

Redis 规范参考

阿里云-Redis最佳实践与实战指南.pdf

阿里云 Redis 开发规范:https://developer.aliyun.com/article/531067

HZERO Redis 使用规范:https://open.hand-china.com/hzero-docs/v1.3/zh/docs/development-specification/backent-development-specification/redis/

融合小组制定的 Redis 使用规范:https://tech.hzlinks.net/showdoc/web/#/304/16886

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值