You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Redis缓存get方法耗时过高求助(约1700ms)

Django Redis缓存获取性能异常排查与优化方案

问题背景

在Django项目中使用Redis缓存货币兑换汇率,缓存有效期设为24小时,Redis与Django容器通过Docker Compose部署在同一环境。实现函数如下:

def getExchangeRate(currencyCode: str) -> float:
    # Define a cache key based on the currency code
    cache_key = f'exchange_rate_{currencyCode}'

    # Check the cache first for the exchange rate
    exchangeRate = cache.get(cache_key)

    if exchangeRate is None:
        try:
            # Fetch the exchange rate from the database
            exchangeRate = float(ExchangeRate.objects.get(currency__code=currencyCode).rate)

            # Cache the fetched value with an appropriate TTL (e.g., 24 hours)
            cache.set(cache_key, exchangeRate, 86400)  # 86400 seconds = 24 hours
        except (ExchangeRate.DoesNotExist, ValueError):
            # Handle the case where the currency code is not found in the database
            # or the rate cannot be converted to a float
            exchangeRate = None
    cache.close()
    return exchangeRate

目前cache.get()方法耗时约1700ms,远超预期。Atatus监控数据显示该查询在事务中占用大量时间,原本希望通过缓存减少数据库查询次数,但Redis缓存获取操作性能异常,暂未找到有效解决方案。

排查与优化步骤

1. 移除手动关闭缓存连接的操作

Django的Redis缓存后端默认使用连接池管理连接,手动调用cache.close()会强制关闭当前连接,后续请求需要重新建立TCP连接,这是导致性能飙升的核心原因。连接池会自动复用空闲连接,无需手动关闭。

修改后的函数:

def getExchangeRate(currencyCode: str) -> float:
    cache_key = f'exchange_rate_{currencyCode}'
    exchangeRate = cache.get(cache_key)

    if exchangeRate is None:
        try:
            exchangeRate = float(ExchangeRate.objects.get(currency__code=currencyCode).rate)
            cache.set(cache_key, exchangeRate, 86400)
        except (ExchangeRate.DoesNotExist, ValueError):
            exchangeRate = None
    return exchangeRate

2. 检查Docker网络配置

确保Redis与Django容器处于同一自定义Docker网络,使用容器名称作为Redis的连接地址(而非localhost),避免跨网络通信的DNS解析延迟或路由损耗。

示例Docker Compose配置片段:

services:
  redis:
    image: redis:alpine
    networks:
      - app-internal
  django:
    build: .
    networks:
      - app-internal
    environment:
      - REDIS_URL=redis://redis:6379/0
networks:
  app-internal:
    driver: bridge

3. 优化Redis客户端连接池参数

在Django的settings.py中调整Redis缓存的连接池配置,增加最大连接数、设置合理的超时时间,减少连接等待和超时概率:

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://redis:6379/0',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'CONNECTION_POOL_KWARGS': {
                'max_connections': 100,
                'socket_timeout': 2,
                'socket_connect_timeout': 2,
                'socket_keepalive': True,
            },
        }
    }
}

4. 验证Redis服务本身性能

进入Redis容器,检查服务响应速度和是否存在慢查询:

# 进入Redis容器
docker exec -it <redis-container-id> redis-cli
# 测试响应时间
ping
# 查看最近慢查询记录
slowlog get 10

正常情况下ping响应耗时应在1ms以内,若存在慢查询需针对性优化Redis配置或查询逻辑。

5. 分离事务与缓存操作

如果该函数在数据库事务上下文内被调用,事务的锁等待或提交延迟可能被误统计到Redis操作耗时中。尝试将缓存操作移出事务,或对相关视图使用@transaction.non_atomic_requests装饰器,避免事务对缓存性能的干扰。

预期效果

移除cache.close()后,Redis连接会被连接池复用,cache.get()耗时应降至10ms以内,大幅减少事务中的时间占用,同时实现缓存减少数据库查询的预期目标。

内容的提问来源于stack exchange,提问作者Saifullah Saeed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:13:10