Redis 配置优化
- 连接池参数调整
- 增大最大连接数:通过调整
maxclients
参数,根据服务器的硬件资源(如内存、CPU 等)合理增大 Redis 允许的最大客户端连接数。例如,如果服务器内存充足且 CPU 性能较好,可以将 maxclients
适当提高,比如从默认的 10000 提高到 20000。
- 优化连接超时时间:合理设置
timeout
参数,避免连接长时间闲置占用资源。对于一些长时间无操作的连接,在达到 timeout
时间后,Redis 会主动关闭连接,释放资源。比如设置为 60 秒,确保连接池中的连接资源能被有效利用。
- 缓存策略优化
- 调整过期策略:根据业务需求,合理选择过期策略。例如,如果业务对数据一致性要求不是特别高,可以采用
volatile - lru
(从已设置过期时间的数据集中挑选最近最少使用的数据淘汰)或 allkeys - lru
(从数据集中挑选最近最少使用的数据淘汰)策略,避免缓存数据过多导致内存溢出,间接减少因内存问题引发的命令执行错误。
- 热数据持久化:对于一些频繁访问的热数据,可以通过配置持久化策略,如
AOF
(Append - Only File)或 RDB
(Redis Database),确保在 Redis 重启后能快速恢复热数据,减少冷启动时对缓存的冲击。如果对数据完整性要求极高,优先选择 AOF
持久化方式,并定期进行 AOF
重写以优化文件大小。
应用代码层面调整
- 优化连接使用
- 连接复用:在应用代码中,确保每个业务逻辑尽可能复用已获取的 Redis 连接,而不是频繁创建和销毁连接。例如,在一个业务模块中,如果多次需要访问 Redis,可以将获取到的连接对象传递给不同的方法使用,而不是每次调用方法都重新获取连接。
- 异常处理:在获取连接和执行 Redis 命令时,增加全面的异常处理逻辑。当连接池耗尽获取不到连接时,捕获相应异常,如
JedisConnectionException
,可以在异常处理中进行适当的重试逻辑,或者给用户返回友好的提示信息,告知系统繁忙,请稍后重试。
- 解决竞争条件
- 使用 Redis 事务:将涉及竞争条件的多个 Redis 命令封装在一个事务中执行。例如,在涉及数据增减操作时,通过
MULTI
、EXEC
命令保证这些操作的原子性。如以下代码示例(以 Jedis 为例):
Jedis jedis = jedisPool.getResource();
try {
Transaction transaction = jedis.multi();
transaction.incr("counter");
List<Object> results = transaction.exec();
} catch (Exception e) {
// 处理事务执行异常
e.printStackTrace();
} finally {
jedis.close();
}
- **使用分布式锁**:对于一些需要全局互斥的操作,可以使用 Redis 实现分布式锁。例如,利用 `SETNX`(Set if Not eXists)命令来设置锁,当返回值为 1 时表示获取锁成功,否则获取失败。获取锁失败的线程可以等待一段时间后重试。示例代码如下(以 Jedis 为例):
Jedis jedis = jedisPool.getResource();
String lockKey = "myLock";
String requestId = UUID.randomUUID().toString();
try {
while (true) {
Long result = jedis.setnx(lockKey, requestId);
if (result == 1) {
// 获取锁成功,执行相关业务逻辑
try {
// 业务操作
} finally {
// 释放锁
if (requestId.equals(jedis.get(lockKey))) {
jedis.del(lockKey);
}
}
break;
} else {
// 获取锁失败,等待重试
Thread.sleep(100);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jedis.close();
}
- 限流与降级
- 限流:在应用入口处对请求进行限流,防止过多请求同时涌入 Redis。可以使用令牌桶算法或漏桶算法实现限流。例如,使用 Guava 库中的
RateLimiter
实现令牌桶限流,代码示例如下:
RateLimiter rateLimiter = RateLimiter.create(10); // 每秒生成10个令牌
if (rateLimiter.tryAcquire()) {
// 允许访问 Redis,执行相关操作
} else {
// 限流,返回提示信息给用户
}
- **降级**:当 Redis 出现大量错误,无法正常提供服务时,进行服务降级。例如,可以设置一个开关,当检测到 Redis 错误率达到一定阈值(如 80%)时,直接返回缓存的默认数据,而不再请求 Redis,确保系统的基本可用性。在代码中可以通过一个布尔变量控制降级逻辑:
boolean isRedisErrorHigh = checkRedisErrorRate();
if (isRedisErrorHigh) {
// 返回默认数据
return getDefaultData();
} else {
// 正常请求 Redis
return getFromRedis();
}