0

我已经看到这个传递结果到 redis 中的另一个命令, 并且通过命令行使用这个命令效果很好:

src/redis-cli keys '*' | xargs src/redis-cli mget

但是我们怎样才能通过生菜达到同样的效果(我开始尝试 4.0.2.Final)

在以下情况下,对此的解决方案也特别重要:

假设我们正在使用地理定位功能,我们使用 GEOADD 添加一组“我的位置类别”位置

GEOADD "category-1" 8.6638775 49.5282537 "location-id:1" 8.3796281 48.9978127 "location-id:2" 8.665351 49.553302 "location-id:3"

接下来,假设我们执行 GeoRadius 以获取“类别 1”的 8.6582361 49.5285495 10 公里半径范围内的位置

现在当我们得到 "location-id:1" & "location-id:3"

鉴于我已经为上述键“location-id:1”和“location-id:3”设置了值

我想通过管道命令执行 GEORADIUS 以及对所有匹配结果执行 mget。

Redis 是否提供功能来做到这一点?

和/或我们如何通过 Lettuce 客户端库实现这一点,而无需先手动迭代 GEORADIUS 的结果,然后手动进行 mget。

对于使用它的程序来说,这将是更有效的性能。

有谁知道我们该怎么做?

更新 这是我上面讨论的场景的管道命令:

src/redis-cli GEORADIUS "category-1" 8.6582361 49.5285495 10 km | xargs src/redis-cli mget

现在我们需要知道如何通过生菜做到这一点

4

2 回答 2

2

重要提示:永远不要使用,如果必须,请KEYS始终使用。SCAN

这不是关于生菜或 Java 的真正问题,所以我实际上可以回答它:)

您要做的是使用读取操作 ( ) 的结果GEORADIUS作为另一个读取操作 ( ) 的输入(键名MGET)。这种类型的流程不能流水线化,好吧,正因为如此 - 流水线意味着您不需要立即获得操作的答案,但在您的情况下您需要。

然而。

由于您正在使用 读取字符串键MGET,因此您不妨将所有内容非规范化(请记住,我们是 NoSQL)并将这些键的内容存储在排序集的成员中,例如:

GEOADD "category-1" 8.6638775 49.5282537 "location-id:1:moredata:evenmoredata:{maybe a JSON document here}:orperhapsmsgpack"

这将允许您一键获取位置及其“数据” GEORADIUS。当然,对location:1的数据的任何更新都需要在所有类别中完成。

关于 Lua 脚本的说明:虽然 Lua 脚本在这种情况下肯定可以来回保存,但任何此类脚本都将违反最佳实践/不是集群安全的。

于 2015-12-12T14:27:59.633 回答
1

在四处挖掘和研究 Lua 脚本之后,我的结论是,以这种方式删除往返只能按照Itamar Haber 的建议通过Lua 脚本来完成。

我最终创建了一个 lua 脚本文件(myscript.lua),如下所示

local locationKeys = redis.call('GEORADIUS', 'category-1', '8.6582361', '49.5285495', '10', 'km' ) 
if unpack(locationKeys) == nil then
    return nil
else
    return redis.call('MGET', unpack(locationKeys))
end

** 当然我们应该向它发送参数...这只是一个 poc :)

现在您可以通过命令执行它

src/redis-cli EVAL "$(cat myscript.lua)" 0

然后,为了减少将整个脚本发送到 Redis 执行的网络开销,我们可以选择将脚本注册到 Redis。

Redis 将为我们提供一个 sha1 消化的代码,以供将来对该脚本的引用,该代码可用于该脚本的下一次调用。

这可以如下完成:

src/redis-cli SCRIPT LOAD "$(cat myscript.lua)"

这应该返回一个类似这样的sha1代码:49730aa2ed3034ee48f818e486tpbdf1b500b19e

可以使用此代码完成下一个调用,例如

src/redis-cli evalsha 49730aa2ed3034ee48f818e486b2bdf1b500b19e 0

然而,这里可悲的是,只有当 redis 实例正在运行时,才会记住 sha1 摘要。如果重新启动,则 sha1 摘要丢失。然后你再次执行脚本加载。如果脚本中没有任何变化,那么 sha1-digest 代码将是相同的。

理想情况下,通过客户端 api 使用时,我们应该首先尝试 evalsha,如果返回“无匹配脚本”错误,然后作为后备执行脚本加载,并再次获取 sha1 代码,并创建其内部映射并使用它用于进一步调用的 sha1 代码。

这可以通过生菜很好地完成。我可以找到那些方法。希望这可以很好地了解问题的解决方案。

于 2015-12-16T23:47:52.457 回答