至少有 3 种不同的方法可以做到这一点,每种方法都有自己的优点和缺点。
第一种方法是使用树的非原子临时扫描来识别树的第二层(第一组自定义)并使之无效(删除)。为此,请对哈希字段使用分层命名方案,并使用以下命令迭代它们HSCAN http://redis.io/commands/hscan。例如,假设您的哈希键名称是产品的 ID(例如 ProductA),您可以使用“0001:0001”之类的内容作为第一个自定义的第一个版本的字段名称,使用“0001:0002”作为其第二个版本的字段名称,等等。同样,“0002:0001”将是第二个自定义第一个版本,依此类推...然后,找到所有自定义 42 的版本,使用HSCAN ProductA 0 MATCH 0042:*
, HDEL http://redis.io/commands/hdel回复中的字段,然后重复,直到光标归零。
相反的方法是主动“索引”每个自定义的版本,以便您可以有效地获取它们,而不是执行哈希的完整扫描。解决这个问题的方法是使用 Redis 的集合 - 您保留一个包含给定产品版本的所有字段名称的集合。版本可以是连续的(如我的示例),也可以是其他任何版本,只要它们是唯一的即可。成本在于维护这些索引 - 无论何时添加或删除产品的自定义和/或版本,您都需要保持与这些集合的一致性。例如,版本的创建类似于:
HSET ProductA 0001:0001 "<customization 1 version 1 JSON payload"
SADD ProductA:0001 0001
请注意,这两个操作应该在单个事务中(即使用MULTI\EXEC http://redis.io/topics/transactions块或EVAL http://redis.io/commands/evalLua 脚本)。当您完成此设置后,只需调用即可使自定义无效SMEMBERS http://redis.io/commands/SMEMBERS相关集并从哈希中删除其中的版本(以及集本身)。然而,值得注意的是,读取大型 Set 中的所有成员可能会非常耗时 - 1K 个成员并不是那么糟糕,但对于较大的 Set 来说,SSCAN http://redis.io/commands/sscan.
最后,您可以考虑使用有序集而不是哈希。虽然在此用例中可能不太直观,但排序集将允许您执行所需的所有操作。然而,使用它的代价是与哈希的 O(1) 相比,添加/删除/读取的 O(logN) 复杂性增加,但考虑到数字,差异并不显着。
为了释放排序集的力量,您将使用字典顺序,因此排序集的所有成员都应具有相同的分数(例如使用 0)。每个产品都将由一个排序集表示,就像哈希一样。 Set 的成员相当于 Hash 字段,即定制版本。 “技巧”是以允许您执行范围搜索(或如果您愿意的话,可以进行 2 级失效)的方式构造成员。下面是它应该是什么样子的示例(请注意,这里的键 ProductA 不是哈希而是排序集):
ZADD ProductA 0 0001:0001:<JSON>
要读取自定义版本,请使用ZRANGEBYLEX ProductA [0001:0001: [0001:0001:\xff http://redis.io/commands/zrangebylex并从回复中分离 JSON 并删除整个自定义,请使用ZREMRANGEBYLEX http://redis.io/commands/zremrangebylex.