我见过这个pass results to another command in redis 并使用via命令行,这个命令效果很好:
src/redis-cli keys '*' | xargs src/redis-cli mget
然而,我们如何通过Lettuce实现相同的效果(我开始尝试4.0.2.Final)
在以下情况中,解决此问题尤为重要:
假设我们正在使用地理定位功能,并且我们添加了一组位置" my-location-category" 使用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获取位于10公里半径范围内的位置8.6582361 49.5285495,用于"类别-1"
现在我们得到" location-id:1" &安培; "位置-ID:3"
鉴于我已经为上面的键设置了值" location-id:1" &安培; "位置-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
现在我们需要知道如何通过Lettuce
来做到这一点答案 0 :(得分:2)
重要:永远不要使用KEYS
,如果必须,请始终使用SCAN
。
这不是关于Lettuce和Java的问题所以我实际上可以回答它:)
您要做的是使用读取操作(GEORADIUS
)的结果作为另一个读取操作(MGET
)的输入(键名)。这种类型的流程不能流水线化,好吧,正因为如此 - 流水线操作意味着您不需要立即处理操作的答案,但在您的情况下这样做。
然而
由于您正在使用MGET
读取字符串键,因此您可能只是对所有内容进行非规范化(记住,我们是NoSQL)并将这些键的内容存储在Sorted Set的成员中,例如:
GEOADD "category-1" 8.6638775 49.5282537 "location-id:1:moredata:evenmoredata:{maybe a JSON document here}:orperhapsmsgpack"
这样您就可以通过一次GEORADIUS
来获取位置及其“数据”。当然,location:1
数据的任何更新都需要在所有类别中完成。
关于Lua脚本的说明:虽然在这种情况下Lua脚本肯定可以来回保存,但任何此类脚本都将违反最佳做法/非集群安全。
答案 1 :(得分: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摘要将丢失。然后再次执行 SCRIPT LOAD 。如果脚本中没有任何变化,则sha1-digest代码将是相同的。
理想情况下,当通过客户端api使用时,我们应首先尝试evalsha,如果它返回一个"没有匹配的脚本"错误,然后作为回退做脚本加载,再次获取sha1代码,并创建一个内部映射,并使用该sha1代码进行进一步调用。
这可以通过生菜完成。我可以找到那些方法。希望这能够很好地洞察问题的解决方案。