Node.js REDIS-创建有意义的键以减少查询

Node.js REDIS-创建有意义的键以减少查询,node.js,express,redis,key,Node.js,Express,Redis,Key,我有一个应用程序(nodejs/express),需要根据一天中的时间和一周中的哪一天找到一个路由规则来应用 例如,我有以下业务规则: 在周一和周二09:00 GMT和12:00 GMT之间,我需要将对象ABC路由到“位置x” 在周二13:00到13:30之间,我需要将ABC路线发送到“y地点” (在本次讨论中,ABC的对象实际上并不重要。) 我在两种选择之间争论,关于我应该如何在我的REDIS数据库中设计我的密钥 选项1 将日信息作为对象数据的一部分,如下所示: HMSET routing

我有一个应用程序(nodejs/express),需要根据一天中的时间和一周中的哪一天找到一个路由规则来应用

例如,我有以下业务规则:

  • 在周一和周二09:00 GMT和12:00 GMT之间,我需要将对象ABC路由到“位置x”
  • 在周二13:00到13:30之间,我需要将ABC路线发送到“y地点”
(在本次讨论中,ABC的对象实际上并不重要。)

我在两种选择之间争论,关于我应该如何在我的REDIS数据库中设计我的密钥

选项1

将日信息作为对象数据的一部分,如下所示:

HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues' location X 
HMSET routing_rules:objectABC_13:00_13:30 days 'tues' location Y
  127.0.0.1:6379> HDEL routing_rules:objectABC_00:00_00:00 days 'mon tues' location x
 SET routing_rules:objectABC_09:00_12:00_m  X 
 SET routing_rules:objectABC_09:00_12:00_t  X 
 SET routing_rules:objectABC_13:00_13:30_t  Y
此方法的优点-当需要更新天数列表时,我可以简单地执行以下操作:

HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues thu'
这里的缺点是为了找到正确的规则,我必须进行两个查询。。。。首先执行扫描命令以找到正确的时间范围。。。如果有匹配的话。。。执行另一个查询以查找天数值

选项2

将星期几信息作为密钥的一部分

HMSET routing_rules:objectABC_09:00_12:00_mt location X 
HMSET routing_rules:objectABC_13:00_13:30_t location Y
我会使用一个命名约定,比如

m = monday
t = tuesday
w = wed
r = thursday 
etc.
选项2的优点是,为了根据当前时间和日期找到正确的路由规则,我只需要运行一个扫描命令(我们可以假设我的扫描命令将一次性返回所有结果)

但选项2的缺点是,当我需要为关键字添加新的一天时,我认为我需要删除关键字和值。。。然后重新创建它。这是正确的吗

到目前为止,我知道如何删除的唯一方法是对对象中的每个值进行HDEL,然后删除键。 例如,我一直在做这样的事情:

HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues' location X 
HMSET routing_rules:objectABC_13:00_13:30 days 'tues' location Y
  127.0.0.1:6379> HDEL routing_rules:objectABC_00:00_00:00 days 'mon tues' location x
 SET routing_rules:objectABC_09:00_12:00_m  X 
 SET routing_rules:objectABC_09:00_12:00_t  X 
 SET routing_rules:objectABC_13:00_13:30_t  Y
其中,我必须列出对象中的所有值才能删除整个键/值对。 在本例中,情况并没有那么糟,因为我只有两个键的值——location和days字段。但是如果有更多的数据,那就有点麻烦了。我不确定除了与此键相关的字段数量之外,是否还有其他因素需要考虑

如果您对如何设计这把钥匙以实现最佳性能和维护有任何建议,我洗耳恭听。在我看来,没有办法避免至少运行一次扫描。但这是我第一次尝试使用redis数据库,因此我为补救问题/noob错误提前道歉

编辑1

假设我有足够的内存,并且假设每个键只需保存一个字段/值,假设我创建的键如下所示:

HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues' location X 
HMSET routing_rules:objectABC_13:00_13:30 days 'tues' location Y
  127.0.0.1:6379> HDEL routing_rules:objectABC_00:00_00:00 days 'mon tues' location x
 SET routing_rules:objectABC_09:00_12:00_m  X 
 SET routing_rules:objectABC_09:00_12:00_t  X 
 SET routing_rules:objectABC_13:00_13:30_t  Y
现在有一个对象ABC的请求,时间是星期一UTC 11。因为我的键代表开始时间和结束时间(也就是一个范围),所以我不知道如何在不进行扫描的情况下找到正确的键/值对


我错过什么了吗

在这种情况下(以及在大多数情况下),我不会使用任何扫描命令。您可能需要多次调用它来扫描整个密钥空间,同时还有其他方法可以直接访问您要查找的数据,这就是K/V存储性能的原因

例如,在第一个解决方案中,将所有值放在一个散列中,并使用获取一个请求中的所有路由。然后,您必须迭代应用程序中的值以选择正确的值

另一种解决方案不需要在应用程序端进行任何迭代,即每天和每小时创建一条路线:


设置路由规则:对象ABC_09:00_12:00_m位置X
设置路由规则:对象ABC_13:00_13:30_t位置Y
...

然后,在一个请求中,您就拥有了您正在寻找的价值。 增加一天只需要一天的时间。 与您的解决方案相比,它的缺点是内存使用:它会增加条目数。您没有给出任何关于条目数量的线索,但如果条目数量非常高,则可能是个问题。为了减少所需的内存,可以从使用较短的键名开始,例如r:objectABC_09001200m,而不是路由规则:objectABC_09:00_12:00_m)

更新

鉴于时间范围似乎不是常数,并且假设没有算法从当前时间推断时间范围,第一个基于哈希的解决方案似乎比第二个基于GET/SET的解决方案要好。但我会根据时间范围命名字段:

HSET路由规则:对象ABC 09:00\U 12:00 X HSET路由规则:对象ABC 12:00\U 12:30 Y


然后,我将使用
HGETALL routing_rules:objectABC
获取给定对象的所有字段,并迭代成员键以找到正确的字段。

在这种情况下(以及大多数情况下),我不会使用任何扫描命令。您可能需要多次调用它来扫描整个密钥空间,同时还有其他方法可以直接访问您要查找的数据,这就是K/V存储性能的原因

例如,在第一个解决方案中,将所有值放在一个散列中,并使用获取一个请求中的所有路由。然后,您必须迭代应用程序中的值以选择正确的值

另一种解决方案不需要在应用程序端进行任何迭代,即每天和每小时创建一条路线:


设置路由规则:对象ABC_09:00_12:00_m位置X
设置路由规则:对象ABC_13:00_13:30_t位置Y
...

然后,在一个请求中,您就拥有了您正在寻找的价值。 增加一天只需要一天的时间。 与您的解决方案相比,它的缺点是内存使用:它会增加条目数。您没有给出任何关于条目数量的线索,但如果条目数量非常高,则可能是个问题。为了减少所需的内存,可以从使用较短的键名开始,例如r:objectABC_09001200m,而不是路由规则:objectABC_09:00_12:00_m)

更新

鉴于时间范围似乎不是恒定的,假设