Redis创建字符串SET集合读取时返回整数异常排查
问题现象
使用Redis存储SET类型数据时,预期存入'Fred'、'Emmanuel'、'Marcus Aurelius'这类字符串成员,执行SMEMBERS pairs命令读取时,未返回预期的字符串列表,仅返回如下数字字符串:
1) "32" 2) "39" 3) "44" 4) "65" 5) "69" 6) "70" 7) "77" 8) "91" 9) "93" 10) "97" 11) "99" 12) "100" 13) "101" 14) "105" 15) "108" 16) "109" 17) "110" 18) "114" 19) "115" 20) "117"
涉及的业务代码如下(基于Django DRF实现):
@api_view(['GET', 'POST']) def manage_items(request, *args, **kwargs): if request.method == 'GET': items = [] count = 0 for elem in redis_instance.smembers("pairs"): items.append(elem.decode("utf-8")) count += 1 response = { 'count': count, 'msg': f"Found {count} items.", 'items': items } return Response(response, status=200) elif request.method == 'POST': new_users = request.body for i in range(0, len(new_users)): redis_instance.sadd('pairs', bytes(str(new_users[i]), "utf-8")) response = { 'msg': f'set contains: {new_users}' } return Response(response, 201)
问题根因
写入逻辑存在根本性错误:
request.body拿到的是HTTP请求的原始二进制字节串,不是解析后的用户列表。你通过索引new_users[i]遍历字节串时,取到的是每个单独字节对应的ASCII十进制整数值,根本不是完整的用户名。- 返回值里的32(空格)、39(单引号)、44(逗号)、65(大写A)、70(大写F)等,正好是传入请求体原始文本每个字符对应的ASCII码,和存错的内容完全匹配。
- 代码全程没有对请求体做结构化解析,相当于把请求报文里每个字符的ASCII码挨个存进了SET,自然读不到预期的用户名。
修复方案
按以下步骤调整即可:
- 不要直接操作原始
request.body字节串,DRF框架会自动解析请求体,直接通过request.data拿到解析后的结构化用户列表即可。 - 遍历解析后的完整用户列表,将每个用户名字符串直接传入
sadd方法,redis-py客户端会自动处理编码转换,不需要手动转bytes。 - 修复前先执行
redis_instance.delete('pairs')清除之前写入的脏数据,避免旧的错误值残留。
修复后的完整代码如下:
@api_view(['GET', 'POST']) def manage_items(request, *args, **kwargs): if request.method == 'GET': items = [] count = 0 for elem in redis_instance.smembers("pairs"): items.append(elem.decode("utf-8")) count += 1 response = { 'count': count, 'msg': f"Found {count} items.", 'items': items } return Response(response, status=200) elif request.method == 'POST': # 直接取DRF解析后的结构化数据,适配请求实际传参格式即可 new_users = request.data # 遍历用户名字符串列表直接存入 for username in new_users: redis_instance.sadd('pairs', username) response = { 'msg': f'set contains: {new_users}' } return Response(response, 201)
注意:如果POST请求传参格式不是JSON,对应调整
request.data的取值逻辑即可,核心是不要遍历原始请求字节串。
内容的提问来源于stack exchange,提问作者Emm
相关产品推荐
相关产品推荐

