这个坑值得记一笔。把 1024 维 float32 向量用 numpy tobytes 存进 Redis,读回来 reshape 报 ValueError: cannot reshape array of size 4096 into shape (1024,),写入时明明是 1024 维,redis-py 5.0,Python 3.11。

刚开始盯着「numpy 在某些平台默认 dtype 是 float64」,折腾了半个多小时,排掉了。

原因不止一个,得分开看。存的是 float16,读的时候按 float32 解;客户端开了 decode_responses,二进制被转成字符串;写入前做了截断,字节数和维度对不上。

先确认写入数组的 dtype 和 itemsize

python -c "import numpy as np;a=np.zeros(1024,dtype='float32');print(a.dtype,a.itemsize,a.nbytes)"

然后读回来先看字节长度再决定 dtype

python -c "import redis;r=redis.Redis(decode_responses=False);b=r.get('emb:1');print(len(b))"

接着用 np.frombuffer 按 float32 解析并校验形状

python -c "import numpy as np;b=b'\x00'*4096;a=np.frombuffer(b,dtype='float32');print(a.shape)"

剩下的就是把 dtype 和维度一起写进元数据

python -c "import json;print(json.dumps({'dtype':'float32','dim':1024}))"

手上没有现成的复现脚本,就照着线上请求手工拼了一个。

报错是间歇性的,我蹲守了半小时才抓到一次完整现场。

改完先别撤,确认这几项。读取后的数组 shape 是 (1024,),前三个值与写入时一致,余弦相似度自比为 1.0,不再抛 reshape 错误。

二进制缓存的坑几乎都在 dtype 上,float16 和 float32 的字节数差一倍;把 dtype 和维度写进同一个 key 的元数据,比事后猜要省事。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189