想象一下以下情景:
一切正常。让我们在4到5之间添加另一个客户端:
数据库返回对象A
现在,对象A在数据库中是最新的,但在Redis中已过时。是否有任何模式可以防止此类行为?显然,在等待Redis存储其副本时锁定数据库并不是一个解决方案。
我还应该注意到我使用的NodeJS维护一个固定大小的连接池到Redis并且请求是异步处理的,所以我们不能假设来自不同客户端的查询顺序不胜一筹混合在一起。
答案 0 :(得分:1)
如果您的数据经常不变(非易失性),就像昨天或一个月前的历史数据一样,您可以安全地忽略竞争条件,因为无论谁最后提交,客户的数据仍然相同。
对于时间敏感数据,尤其是交易数据,您可以使用用户ID(客户端#1,客户端#2)将基于用户ID 的缓存分开额外的钥匙。这将消除客户端之间的竞争条件,而无需使用锁定和事务同步以及更高内存使用率的缺点。
此方法可以与第一种方法组合,例如如果数据是关于用户特定数据的,则可以使用用户ID密钥,另一方面,如果数据包含基于角色的菜单访问等共享/分组信息,则可以使用组ID。
答案 1 :(得分:0)
您正在寻找Redis transactions。关键是WATCH
命令。在初始读取之前在对象A上调用WATCH
,并将对象设置在MULTI
内。现在你的两个场景看起来像:
和
数据库返回对象A
失败后,客户端#1可以重试,但最好忽略失败,因为看起来你只是将它用作缓存。
客户端#2当然也应该完成WATCH / MULTI / EXEC模式。
答案 2 :(得分:0)
如果对象没有更新操作(第5步),您应该使用SETNX来存储它。所以你不要存放过时的物品。