你的Redis集群撑得住吗?

文章系转载,方便整理和归纳,源文地址 https://cloud.tencent.com/developer/article/1803937

1 前言

一大早有个同事过来问我,今天xxx系统需要增加6个pod。我们当前的Redis是否能够撑得住呢?

2 场景介绍

2.1 Redis和Jedis版本以及重要参数介绍

类型版本其他
Redis4.0.12三主三从(分布6台虚拟机4c32gb/台)
Jedis2.9关键参数详解

2.2 Jedis 关键参数详解

首先我们先介绍几个关键的Jedis参数,方便我们后续的资源评估。

参数说明默认值建议值
maxTotal资源池中的最大连接数8详见《2.2.1 关键参数建议》
maxIdle资源池允许的最大空闲连接数8详见《2.2.1 关键参数建议》
minIdle资源池确保的最少空闲连接数0详见《2.2.1 关键参数建议》
blockWhenExhausted当资源耗尽的时候,调用者是否等待。只有当值为true时,下面的maxWaitMillis才会生效。true建议使用默认值。
maxWaitMillis当资源池连接用尽后,调用者的最大等待时间(单位为毫秒)。-1(表示永不超时)不建议使用默认值。
testOnBorrow向资源池借用连接时是否做连接有效性检测(ping)。检测到的无效连接将会被移除。false业务量很大时候建议设置为false,减少一次ping的开销。
testOnReturn向资源池归还连接时是否做连接有效性检测(ping)。检测到无效连接将会被移除。false业务量很大时候建议设置为false,减少一次ping的开销。
jmxEnabled是否开启JMX监控true建议开启,请注意应用本身也需要开启。

2.2.1 关键参数建议

maxTotal(资源池中的最大连接数),该参数主要从如下四点进行考虑:

  1. 业务希望Redis能达到的并发数;
  2. 客户端执行的时间;
  3. Redis资源,例如Redis cluster(三主三从)pod数 *maxTotal < 3 * 单个Redis 分片的最大连接数(默认是10000),也就是要小于30000,正常情况我们还会为改参数乘于一个预留系数 0.8 ,所以公式为: pod数 *maxTotal < 3 * 10000 * 0.8 < 24000;
  4. 资源开销,例如虽然希望控制空闲连接,但又不希望因为连接池中频繁地释放和创建连接造成不必要的开销。

举个简单的例子来计算,比如一个命令的时间(borrow|return resource+Jedis执行命令+网络开销的时间)为1ms,那么一个连接的QPS计算公式为:1s/1ms=1000。如果业务希望我们集群的QPS能达到100w,有10个应用pod, 那计算公式为1000000/1000/10=100。那么maxTotal配置为100。

当然这个值只是一个理论值,我们在预设这个值的时候,需要预留一些资源,所以这个实际值就要比理论值设置大一点,但是这个值不是越大越好,一方面连接太多会占用客户端和服务端资源,另一方面对于Redis这种高QPS的服务器,如果出现大命令的阻塞,即使设置再大的资源池也无济于事。

maxIdle与minIdle

maxIdle实际上才是业务需要的最大连接数,maxTotal 是为了给出余量,所以 maxIdle 不要设置得过小,否则会有new Jedis(新连接)开销,而minIdle是为了控制空闲资源检测。

连接池的最佳性能是maxTotal=maxIdle,这样就避免了连接池伸缩带来的性能干扰。如果您的业务存在突峰访问,建议设置这两个参数的值相等;如果并发量不大或者maxIdle设置过高,则会导致不必要的连接资源浪费。

minIdle为资源池确保的最少空闲连接数,这个参数很重要。我们经常会在Jedis pool预热这一块用到这个参数。由于一些原因(如超时时间设置较小等),项目在启动成功后可能会出现超时。JedisPool定义最大资源数、最小空闲资源数时,不会在连接池中创建Jedis连接。初次使用时,池中没有资源使用则会先new Jedis,使用后再放入资源池,该过程会有一定的时间开销,所以建议在定义JedisPool后,以最小空闲数量为基准对JedisPool进行预热。

综上,您可以根据实际总QPS和调用Redis的客户端规模整体评估每个节点所使用的连接池大小。

使用监控获取合理值

在实际环境中,比较可靠的方法是通过监控来尝试获取参数的最佳值。可以考虑通过JMX等方式实现监控,从而找到合理值。

2.3 最佳实践评估

参数参数值
maxTotal500
maxIdle500
minIdle100
pod20

如上列表为当前pod数量和关键参数配置,从普罗米修斯监控看,该集群内存使用率均整体资源达到30%左右,资源很空闲,所以我们只需要评估连接数是否足够,那就是500 * 26 是否小于 10000 * 3 * 80%,答案很明显,最大连接数符合要求。

3.其他

以上是一个最大连接数评估的一个过程,那资源不足的时候,程序会有哪些问题呢?下面将介绍两种资源不足的情况

A. blockWhenExhausted 为false,Jedis不会等待资源释放:

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
…
Caused by: java.util.NoSuchElementException: Pool exhausted
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

B.超时:

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
…
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)

4 总结

当遇到资源评估的时候,稳住。查看下相关的理论,再结合实际一对比,其实很多问题就解决了。本文其实有一些定理总结,具体如下:

  1. 应用端最大连接数估算公式: maxTotal * pod数 < max_clients(redis cluster 单个分片的max_clients)* 分片数 * 80% (预留百分比);
  2. 应用端最大空闲连接数设置: 0 < maxIdle <= maxTotal;
  3. 比较常见的配置推荐: maxIdle == maxTotal == Tomcat 线程数,此配置均满足以上公式。

5 参考文献

  1. https://github.com/redis/jedis/blob/master/src/main/java/redis/clients/jedis/JedisPoolConfig.java

  2. https://www.alibabacloud.com/help/doc-detail/145231.htm?spm=a2c63.p38356.b99.30.70386695h1A3OP

  3. https://www.alibabacloud.com/help/doc-detail/98726.html?spm=a2c5t.11065259.1996646101.searchclickresult.3b337b7aaLFVkZ

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值