Redis中1:n关联记录的高效存储方案咨询
针对玩家-游戏关联数据的Redis最优结构设计
先给结论:你之前的第二个方案在小体量场景下可行,但高并发/大数据量时不推荐,更优的设计分以下几种,按需选择:
1. 单玩家独立Hash(最推荐的基础方案)
给每个玩家单独创建一个Hash键,命名规则比如player:<player_id>:games,其中:
- 字段是具体的
game_id(比如1001) - 值是包含
start_date和last_played的JSON字符串(比如{"start_date":"2024-01-01","last_played":"2024-05-20"})
优势:
- 直接通过
HGETALL player:10:games就能拿到玩家10的所有游戏记录,无需模糊匹配 - 更新单个游戏数据时,直接执行
HSET player:10:games 1001 '{"start_date":"2024-01-01","last_played":"2024-05-21"}',不用取出整个玩家的游戏列表,性能损耗极低 - 可以单独获取某款游戏的记录:
HGET player:10:games 1001 - 天然避免并发更新冲突(仅修改单个字段,不会覆盖其他游戏的数据)
2. 双向关联Hash(多维度查询需求时用)
如果需要同时支持「按玩家查游戏」和「按游戏查玩家」,可以再加一层Hash结构:
- 玩家侧:保留
player:<player_id>:games,结构同上 - 游戏侧:创建
game:<game_id>:players,字段是具体的player_id,值同样是包含两个日期的JSON
优势:
- 满足双向查询需求,比如想知道游戏1001的所有玩家,直接执行
HGETALL game:1001:players - 数据更新时,同步操作两个Hash即可(比如玩家10加入游戏1001,同时对两个键执行HSET)
3. Sorted Set结合Hash(需按时间排序场景)
如果需要快速获取玩家最近玩的游戏,或者按开始时间排序,可以用Sorted Set配合Hash:
- Sorted Set键:
player:<player_id>:games:sort,成员是game_id,score设为last_played的时间戳 - Hash键:还是用
player:<player_id>:games存储日期详情
优势:
- 用
ZRANGE player:10:games:sort 0 -1 WITHSCORES可以按最近玩的顺序拿到游戏ID和对应时间戳 - 用
ZRANGEBYSCORE可以筛选出某段时间内玩家玩过的游戏
关于你之前的第二个方案的可行性:
如果你的应用玩家数量少、每个玩家参与的游戏不多、并发操作频率低,这个方案完全能用。但一旦数据量上来,每次更新都要取出整个JSON数组修改再存回去,一来会增加网络传输量,二来容易出现并发冲突(比如两个请求同时修改同个玩家的游戏列表,后存的会覆盖前一个的修改),所以不推荐在高负载场景使用。
内容的提问来源于stack exchange,提问作者GrfPT4
相关产品推荐
相关产品推荐

