我正在将一些“实时”数据结构从MySQL移动到REDIS。使用StackExchange C#Redis Client,我正在编写(由于某些非常特定于项目的限制)我自己的microORM代码,以从Redis数据库存储和检索对象类实体。
我在Redis中将c#对象作为哈希键推送。
我的一般问题是关于除“主键”以外的其他字段的索引。
好吧,我已经阅读了所有关于集合和排序集合的理论,以及如何从集合中添加和删除成员,等等。
我添加了一些代码来正确创建包含实体哈希键的设置键,以便我可以通过简单索引或排序索引来查找那些对象。
但是我找不到或找到解决以下问题的好策略:
1。过期时维护索引
我想向某些对象(哈希)键添加到期时间,以便Redis自动清除旧实体。但是,除了定期运行后台任务,该任务会扫描索引集密钥中已过期的成员并将其删除(通知对我不利),我无法找到一种可靠的方式来更新/清除相关索引。
2。当某些对象字段更改时,索引更新
在某些情况下,我只需要更新一小部分哈希键值,而不是整个实体。如果要更新的字段是一个或多个索引设置键的一部分,则我无法找出正确更新设置键的最佳方法。
例如,假设我需要存储一个“会话”实体,其主键为其ID(简单数字整数),并且需要在“节点”字符串字段上添加一个索引(节点是对当前为该会话提供服务的服务器):
class Session {
[RedisKey]
public int ID { get; set; }
public string RemoteIP { get; set; }
[RedisSimpleIndex]
public string Node { get; set; }
}
RedisKey
和RedisSimpleIndex
是我用来通过反射提取哪些字段用作主键以及哪些字段用于索引的属性。
假设我有一个Session
的实例,如下所示:
{ ID = 2, RemoteIP = "1.2.3.4", Node = "Server10" }
我的例程在Redis中创建以下键:
哈希键:"obj:Session:2"
哈希值:"ID" = "1", "RemoteIP" = "1.2.3.4", "Node" = "Server10"
设置键"idx:Session:Node:Server10"
设置成员:"obj:Session:2"
这非常适合在Server10上查找所有会话。
但是,如果需要将同一会话移至其他服务器(例如Server8
),而我只想更新哈希集中的Node
字段,那么我也如何更新索引?>
到目前为止,我发现的唯一方法是扫描模式为idx:Session:Node:*
的所有索引键,并从其中删除任何成员obj:Session:2
,然后为新节点创建/更新索引键({{1 }}。
此外,SCAN命令在IDatabase或ITransaction接口中不可用,在HA群集环境中,情况变得更糟,因为我需要确定哪个Redis服务器持有相关密钥才能使此过程正常工作。
在Redis中是否有更好的方法来构建/表示简单索引?我的方法不对吗?
答案 0 :(得分:1)
我想为某些对象(哈希)键添加过期时间,以便 Redis 自动清除旧实体。但是,除了定期运行后台任务来扫描过期成员的索引集键并删除它们之外,我找不到更新/清除相关索引的可靠方法(通知对我不利)
expire.c
中。代码看起来相当简单。相比之下,C 模块 API 似乎没有提供任何方式来挂钩驱逐逻辑。另一种选择是在处理过期逻辑时不依赖 Redis。所以......你仍然会有一个后台作业,但它实际上会为过期的 KV 对发出相应的 DEL
命令。这还可以让您通过交易使索引 100% 保持最新。
在某些情况下,我只需要更新一小部分哈希键值,而不是整个实体。如果正在更新的字段是一个或多个索引集键的一部分,我无法找出正确更新集键的最佳方法。
我不确定您使用的是哪个 Redis 客户端,但我发现以下模式在过去非常有用:
setFirstName
、setLastName
等)的设置器。到目前为止我发现的唯一方法是使用模式 idx:Session:Node:* 扫描所有索引键并从中删除任何成员 obj:Session:2,然后创建/更新新节点的索引键 (idx :Session:Node:Server8).
这很麻烦,但似乎是要走的路。可悲的是,我认为没有更好的解决方案。您可能需要考虑维护一个单独的集合,其中包含必须更新的索引 KV 对的键,这样您就可以避免遍历一堆不相关的键。
您可能还想查看 an article 以了解如何维护这些索引。正如您已经提到的,基本上有两种选择:实时使用 MULTI
事务或使用批处理作业。一旦进入使用密钥过期的领域,您或多或少会被迫使用批处理方法。