文档中心>云数据库 Redis®>开发准则>客户端程序设计准则

客户端程序设计准则

最近更新时间:2024-09-14 15:17:12

我的收藏

避免 DB 重用

避免多个应用使用同一个 Redis 实例。
原因:Key 淘汰规则的存在,多个应用的 Key 会相互影响,导致缓存命中率的下降。同时,若多个应用中有部分存在大量访问,也会影响其他应用的正常使用。
建议:将不相干的业务进行拆分,公共数据做服务化。

使用连接池

Redis 整个访问的时间包含几个部分:网络连接时间、命令解析时间、命令实行时间。使用带有连接池的数据库,可节约网络连接时间,加快访问 Redis 的效率,并且可高效控制连接数量。连接资源池关键配置参数包括:连接池最大连接数、最大空间连接数、最小空闲连接数,这三个参数建议配置为相同的数值。具体大小,请业务侧根据实际情况进行评估。
连接池最大连接数:即控制业务并发量。当连接池中的连接数达到最大连接数时,连接池将不再创建新的连接。这有助于确保连接池不会占用过多的系统资源。
连接池最大空闲连接数:是指连接池中允许保持空闲的最大连接数。当连接池中的连接数超过最大空闲连接数时,多余的连接将被关闭并从连接池中移除,从而释放系统资源。这有助于确保连接池不会占用过多的系统资源,同时也有助于提高应用程序的性能和可伸缩性。
连接池最小空闲连接数:指连接池中必须保持的最小空闲连接数。如果连接池中的空闲连接数低于此值,连接池将创建新的连接以满足此要求。这有助于确保在高负载情况下,连接池中始终有足够的可用连接,
除了以上所描述的参数配置之外,不同语言连接池的队列连接方式采用了热连接的方式,需要对应修改代码。具体信息,请参见下表:
多语言类型
问题及建议
代码示例
golang go-redis 连接池
连接池库,建议连接用完放入队尾,而获取连接从队头拿取,避免总是获取热连接。
队列连接方式相关代码,如下所示:
func (p *ConnPool) popIdle() *Conn {
if len(p.idleConns) == 0 {
return nil
}

// fix get connection from head,default is back
cn = nil
// Lifo 为true从队头拿,为false从队尾拿
if p.opt.Lifo == true {
cn = p.idleConns[0]
p.idleConns = p.idleConns[1:]
} else {
idx := len(p.idleConns) - 1
cn = p.idleConns[idx]
p.idleConns = p.idleConns[:idx]
}

p.idleConnsLen--
p.checkMinIdleConns()
return cn
}
更多信息,请参见 go-redis 连接池官网示例。v8.11.5版本及之后的版本已经修复队列的连接方式,请确认版本及代码逻辑,避免使用热连接方式。
golang redigo
连接池配置
redigo 官网提供的连接池只支持从队头拿连接,从队头放回已用连接。导致最热连接一直被使用,不轮询每一个连接,无法实现负载均衡,导致 Proxy 连接或是负载总是不均衡的现象。需修改源代码中的pool.go 文件,增加 pushBack 方法和 Lifo 成员变量。
代码示例,如下所示:
// idle connection in the pool method, True: pushBack, False: pushFront, default False
Lifo bool

// fix add pushBack
if p.Lifo == true {
p.idle.pushBack(pc)
} else {
p.idle.pushFront(pc)
}
更多信息,请参见 Redigo 连接池使用建议
java_jedis_pool
设置连接池连接队列方式。
false:后进后出即从队头拿连接,从队尾放连接。推荐使用该方式。
true:后进先出即从队头拿连接,从头放连接,永远为最热连接,默认为该方式。
指定连接池定期检查时间,避免连接可能会被长时间占用而不释放。建议配置为3000ms,表示每3秒检测一次。 time-between-eviction-runs: 3000ms
关键代码示例,请参见 Jedis 连接池代码示例
完整代码示例,请参见 spring-boot-jedis-demo
java_lettuce_pool
设置连接池队列方式与java_jedis_pool 一致。
请关闭连接复用,避免出现 PipeLine。

配置参数,建议如下所示。完整代码示例,请参见 java_jedis_lettuce_pool。核心代码,请关注 RedisConfig.java 与 RedisProperties.java。
server:
port: 8989
spring:
redis:
database: 0
host: 172.17.0.43
port: 6379
# 密码 没有则可以不填
password: ######
# 连接超时时间,单位毫秒
timeout: 1000
# 如果使用的jedis 则将lettuce改成jedis即可
lettuce:
pool:
# 获取连接池中的连接,最大等待时间 ms
max-wait: 1000ms
# 最大活跃链接数 默认8
max-active: 2000
# 最大空闲连接数 默认8
max-idle: 1000
# 最小空闲连接数 默认0
min-idle: 500
time-between-eviction-runs: 3000ms
# 设置连接池连接队列方式,false:后进后出即从队头拿连接,从队尾放连接;true:后进先出即从队头拿连接,从头放连接,永远拿的是最热连接不推存
lifo: false

#shutdown-timeout: 1000
spring_boot_redisson 连接池
请将连接池最大连接数、最大空间连接数、最小空闲连接数,三个参数配置为相同的值。
队列连接方式相关代码,如下所示:
# 单主节点配置(clusterServersConfig:集群模式)
singleServerConfig
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 连接超时,单位:毫秒
connectTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 命令失败重试次数,如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。
# 如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryAttempts: 3
# 命令重试发送时间间隔,单位:毫秒
retryInterval: 1500
# # 重新连接时间间隔,单位:毫秒
# reconnectionTimeout: 3000
# # 执行失败最大次数
# failedAttempts: 3
# 密码
password: 111
# 单个连接最大订阅数量
subscriptionsPerConnection: 5
# 客户端名称
clientName: cdkey
# # 节点地址
address: redis://172.20.1.20:6379
# 发布和订阅连接的最小空闲连接数
subscriptionConnectionMinimumIdleSize: 1
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
# 最小空闲连接数
connectionMinimumIdleSize: 1000
# 连接池大小
connectionPoolSize: 10000
# 数据库编号
database: 0
# DNS监测时间间隔,单位:毫秒
dnsMonitoringInterval: 5000
# 线程池数量,默认值: 当前处理核数量 * 2
threads: 64
# Netty线程池数量,默认值: 当前处理核数量 * 2
nettyThreads: 64
# 编码
codec: !<org.redisson.codec.JsonJacksonCodec> {}
# 传输模式
transportMode : "NIO"
更多信息,请参见 spring_boot_redisson 连接池官网链接

增加熔断功能

高并发场景,建议客户端添加熔断逻辑功能,例如:netflix、hystrix。Redis 客户端的熔断器实时检测集群节点,当某一个 Redis 节点出现异常,便不再请求有异常的 Redis 节点,从而避免单个节点的故障导致整体系统的雪崩。

配置合理密码

数据库访问密码可以保障数据的安全性。密码复杂度要求:
字符个数为[8,30]。
至少包含小写字母、大写字母、数字和字符 ()`~!@#$%^&*-+=_|{}[]:;<>,.?/ 中的2种。
不能以"/"开头。
腾讯云支持 SSL(Secure Sockets Layer)加密认证访问,具体操作,请参见 SSL 加密