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

Django代码逻辑异常:Redis故障时无法从PostgreSQL读取数据

问题排查:Redis故障时Django API未从数据库读取数据返回404

问题描述

编写的Django APIView预期通过inscode从Redis读取数据并返回;当Redis故障时,从PostgreSQL数据库读取数据。但实际Redis故障时,代码并未从数据库读取数据,而是返回404状态码。编写的测试用例验证读取数据时返回200,但测试未通过。

代码实现

class GetOrderBook(APIView):
    def get(self, request, format=None):
        # get parameters
        inscode = None
        if 'i' in request.GET:
            inscode = request.GET['i']

        if inscode != None:
            try:
                #raise ('disabling redis!')
                r_handle = redisconnection

                data = r_handle.get(inscode)

                if data != None:
                    return Response(200)
                else:
                    print('not found in cache')
            except BaseException as err:
                print(err)
            orderbook = OrderBook.objects.filter(
                symbol__inscode=inscode).order_by('rownum')
            if len(orderbook) > 0:
                data = OrderBookSer(orderbook, many=True).data
                data_formatted = {'buynum': [0]*5, 'buyvol': [0]*5, 'buyprice': [
                    0]*5, 'sellnum': [0]*5, 'sellvol': [0]*5, 'sellprice': [0]*5}
                

                return Response(data_formatted, status=status.HTTP_200_OK)
            else:
                return Response({'Bad Request'}, status.HTTP_404_NOT_FOUND)
        return Response({'Bad Request'}, status.HTTP_400_BAD_REQUEST)

测试用例

def test_redis_function(self, api_client, test_user):
    url = self.url
    api_client.force_authenticate(user=test_user)  
    
    response = api_client.get(url, {'i': '2400322364771558'}) 
    assert response.status_code == status.HTTP_200_OK

问题排查与修复

核心问题点

  1. Redis命中时的响应逻辑错误
    原代码中return Response(200)是将数字200作为响应体返回,而非设置HTTP状态码为200,属于参数传递错误。

  2. 异常捕获范围过宽
    捕获BaseException会包含所有异常(如代码逻辑错误),可能掩盖其他问题,应仅捕获Redis相关异常。

  3. 数据库查询效率低下
    使用len(orderbook)判断查询结果是否存在,会触发全表扫描,更高效的方式是使用exists()方法。

  4. 错误响应消息不准确
    404状态码对应的响应消息应为资源不存在,而非"Bad Request"(对应400状态码)。

修复后的代码

from redis.exceptions import RedisError

class GetOrderBook(APIView):
    def get(self, request, format=None):
        # 简化参数获取方式
        inscode = request.GET.get('i')

        if inscode:
            try:
                r_handle = redisconnection
                data = r_handle.get(inscode)

                if data is not None:
                    # 正确返回缓存数据与状态码
                    return Response({'data': data}, status=status.HTTP_200_OK)
                # Redis未命中,自动进入数据库查询逻辑
            except RedisError as err:
                print(f"Redis连接异常: {err}")
            
            # 数据库查询逻辑
            orderbook = OrderBook.objects.filter(
                symbol__inscode=inscode).order_by('rownum')
            
            if orderbook.exists():
                data = OrderBookSer(orderbook, many=True).data
                data_formatted = {
                    'buynum': [0]*5, 
                    'buyvol': [0]*5, 
                    'buyprice': [0]*5, 
                    'sellnum': [0]*5, 
                    'sellvol': [0]*5, 
                    'sellprice': [0]*5
                }
                # 可根据实际需求从data中填充data_formatted字段
                return Response(data_formatted, status=status.HTTP_200_OK)
            else:
                return Response({'error': '订单簿不存在'}, status=status.HTTP_404_NOT_FOUND)
        return Response({'error': '缺少inscode参数'}, status=status.HTTP_400_BAD_REQUEST)

测试用例优化(模拟Redis故障场景)

from unittest.mock import patch
from redis.exceptions import ConnectionError

def test_redis_fallback_to_database(self, api_client, test_user):
    url = self.url
    api_client.force_authenticate(user=test_user)  
    
    # 模拟Redis连接异常
    with patch('your_app.redisconnection.get') as mock_redis_get:
        mock_redis_get.side_effect = ConnectionError("Redis服务不可用")
        
        response = api_client.get(url, {'i': '2400322364771558'}) 
        assert response.status_code == status.HTTP_200_OK

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:53:11