Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Redis 队列或其他方法来处理勾号数据?_Redis_Time Series_Queue - Fatal编程技术网

Redis 队列或其他方法来处理勾号数据?

Redis 队列或其他方法来处理勾号数据?,redis,time-series,queue,Redis,Time Series,Queue,在我们的电子交易系统中,我们需要根据100多份合约的勾号数据进行计算 未在一条消息中接收到合同的勾号数据。一条消息仅包含一份合同的勾号数据。合同的时间戳略有不同(有时差异很大,但我们忽略这种情况) 只有那些价格发生变化的公司才会有数据。所以我无法计算合同号,以了解我是否已收到此勾号的所有数据 但另一方面,我们不想等到收到所有滴答声的数据,因为有时数据可能会延迟很长时间,我们希望排除它们 需要低延迟。所以我认为我们将定义一个窗口,比如说50毫秒,然后根据我们在过去50毫秒内收到的任何数据开始计算

在我们的电子交易系统中,我们需要根据100多份合约的勾号数据进行计算

未在一条消息中接收到合同的勾号数据。一条消息仅包含一份合同的勾号数据。合同的时间戳略有不同(有时差异很大,但我们忽略这种情况)

只有那些价格发生变化的公司才会有数据。所以我无法计算合同号,以了解我是否已收到此勾号的所有数据

但另一方面,我们不想等到收到所有滴答声的数据,因为有时数据可能会延迟很长时间,我们希望排除它们

需要低延迟。所以我认为我们将定义一个窗口,比如说50毫秒,然后根据我们在过去50毫秒内收到的任何数据开始计算

处理此类用例的最佳方式是什么

最初我想使用redis stream来维护一个小队列,即每当接收到合同的数据时,我都会将其推送到redis stream。但我不知道什么是在特定时间(比如50毫秒)过去后立即提取数据的最佳方式

我在考虑也许我应该使用其他技术?
任何建议都将不胜感激。

使用
XRANGE myStream-+COUNT 1
获取第一个条目

使用
XREVRANGE myStream+-COUNT 1
获取最后一个条目

XINFO STREAM myStream
也会带来第一个和最后一个条目,但要说它是
O(logn)

假设将时间戳用作ID或字段,则可以计算时间差

如果您使用的是Redis Streams自动ID(
XADD myStream*…
),则ID的第一部分是UNIX时间戳(以毫秒为单位)

假设存在上述情况,您可以使用Lua脚本以原子方式执行检查:

EVAL "local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1') local firstTime = {} if next(first) == nil then     return redis.error_reply('Stream is empty or key doesn`t exist') end for str in string.gmatch(first[1][1], '([^-]+)') do     table.insert(firstTime, tonumber(str)) end local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1') local lastTime = {} for str in string.gmatch(last[1][1], '([^-]+)') do     table.insert(lastTime, tonumber(str)) end local ms = lastTime[1] - firstTime[1] if ms >= tonumber(ARGV[1]) then     return redis.call('XRANGE', KEYS[1], '-', '+') else     return redis.error_reply('Only '..ms..' ms') end" 1 myStream 50
local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1')
local firstTime = {}
if next(first) == nil then
    return redis.error_reply('Stream is empty or key doesn`t exist')
end
for str in string.gmatch(first[1][1], '([^-]+)') do
    table.insert(firstTime, tonumber(str))
end
local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1')
local lastTime = {}
for str in string.gmatch(last[1][1], '([^-]+)') do
    table.insert(lastTime, tonumber(str))
end
local ms = lastTime[1] - firstTime[1]
if ms >= tonumber(ARGV[1]) then
    return redis.call('XRANGE', KEYS[1], '-', '+')
else
    return redis.error_reply('Only '..ms..' ms')
end
参数是
numKeys(这里1个)streamKey timeInMs(这里50个)
1 myStream 50

下面是Lua脚本的友好视图:

EVAL "local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1') local firstTime = {} if next(first) == nil then     return redis.error_reply('Stream is empty or key doesn`t exist') end for str in string.gmatch(first[1][1], '([^-]+)') do     table.insert(firstTime, tonumber(str)) end local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1') local lastTime = {} for str in string.gmatch(last[1][1], '([^-]+)') do     table.insert(lastTime, tonumber(str)) end local ms = lastTime[1] - firstTime[1] if ms >= tonumber(ARGV[1]) then     return redis.call('XRANGE', KEYS[1], '-', '+') else     return redis.error_reply('Only '..ms..' ms') end" 1 myStream 50
local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1')
local firstTime = {}
if next(first) == nil then
    return redis.error_reply('Stream is empty or key doesn`t exist')
end
for str in string.gmatch(first[1][1], '([^-]+)') do
    table.insert(firstTime, tonumber(str))
end
local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1')
local lastTime = {}
for str in string.gmatch(last[1][1], '([^-]+)') do
    table.insert(lastTime, tonumber(str))
end
local ms = lastTime[1] - firstTime[1]
if ms >= tonumber(ARGV[1]) then
    return redis.call('XRANGE', KEYS[1], '-', '+')
else
    return redis.error_reply('Only '..ms..' ms')
end
它返回:

  • (错误)流为空或密钥不存在
  • (错误)如果没有所需的时间,则仅34 ms
  • 如果第一条消息和最后一条消息之间的时间已过,则为实际条目列表

确保检查以熟悉Redis Streams,并了解Lua脚本。

使用
XRANGE myStream-+COUNT 1
获取第一个条目

使用
XREVRANGE myStream+-COUNT 1
获取最后一个条目

XINFO STREAM myStream
也会带来第一个和最后一个条目,但要说它是
O(logn)

假设将时间戳用作ID或字段,则可以计算时间差

如果您使用的是Redis Streams自动ID(
XADD myStream*…
),则ID的第一部分是UNIX时间戳(以毫秒为单位)

假设存在上述情况,您可以使用Lua脚本以原子方式执行检查:

EVAL "local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1') local firstTime = {} if next(first) == nil then     return redis.error_reply('Stream is empty or key doesn`t exist') end for str in string.gmatch(first[1][1], '([^-]+)') do     table.insert(firstTime, tonumber(str)) end local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1') local lastTime = {} for str in string.gmatch(last[1][1], '([^-]+)') do     table.insert(lastTime, tonumber(str)) end local ms = lastTime[1] - firstTime[1] if ms >= tonumber(ARGV[1]) then     return redis.call('XRANGE', KEYS[1], '-', '+') else     return redis.error_reply('Only '..ms..' ms') end" 1 myStream 50
local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1')
local firstTime = {}
if next(first) == nil then
    return redis.error_reply('Stream is empty or key doesn`t exist')
end
for str in string.gmatch(first[1][1], '([^-]+)') do
    table.insert(firstTime, tonumber(str))
end
local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1')
local lastTime = {}
for str in string.gmatch(last[1][1], '([^-]+)') do
    table.insert(lastTime, tonumber(str))
end
local ms = lastTime[1] - firstTime[1]
if ms >= tonumber(ARGV[1]) then
    return redis.call('XRANGE', KEYS[1], '-', '+')
else
    return redis.error_reply('Only '..ms..' ms')
end
参数是
numKeys(这里1个)streamKey timeInMs(这里50个)
1 myStream 50

下面是Lua脚本的友好视图:

EVAL "local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1') local firstTime = {} if next(first) == nil then     return redis.error_reply('Stream is empty or key doesn`t exist') end for str in string.gmatch(first[1][1], '([^-]+)') do     table.insert(firstTime, tonumber(str)) end local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1') local lastTime = {} for str in string.gmatch(last[1][1], '([^-]+)') do     table.insert(lastTime, tonumber(str)) end local ms = lastTime[1] - firstTime[1] if ms >= tonumber(ARGV[1]) then     return redis.call('XRANGE', KEYS[1], '-', '+') else     return redis.error_reply('Only '..ms..' ms') end" 1 myStream 50
local first = redis.call('XRANGE', KEYS[1], '-', '+', 'COUNT', '1')
local firstTime = {}
if next(first) == nil then
    return redis.error_reply('Stream is empty or key doesn`t exist')
end
for str in string.gmatch(first[1][1], '([^-]+)') do
    table.insert(firstTime, tonumber(str))
end
local last = redis.call('XREVRANGE', KEYS[1], '+', '-', 'COUNT', '1')
local lastTime = {}
for str in string.gmatch(last[1][1], '([^-]+)') do
    table.insert(lastTime, tonumber(str))
end
local ms = lastTime[1] - firstTime[1]
if ms >= tonumber(ARGV[1]) then
    return redis.call('XRANGE', KEYS[1], '-', '+')
else
    return redis.error_reply('Only '..ms..' ms')
end
它返回:

  • (错误)流为空或密钥不存在
  • (错误)如果没有所需的时间,则仅34 ms
  • 如果第一条消息和最后一条消息之间的时间已过,则为实际条目列表

请务必检查以熟悉Redis Streams,并了解Lua脚本。

我不确定是否遵循。听起来Redis streams应该可以做到这一点。你能详细说明一下你在使用Redis streams时遇到了什么问题吗?实际上我还不太熟悉Redis stream。我知道它的工作原理类似于队列,但我如何才能使它像这样工作:检查队列中的消息,如果(最新时间戳-最新时间戳)>阈值,读取所有这些消息?redis stream是否支持它?我不确定是否支持。听起来Redis streams应该可以做到这一点。你能详细说明一下你在使用Redis streams时遇到了什么问题吗?实际上我还不太熟悉Redis stream。我知道它的工作原理类似于队列,但我如何才能使它像这样工作:检查队列中的消息,如果(最新时间戳-最新时间戳)>阈值,读取所有这些消息?redis stream支持吗?非常感谢。我想这将能够满足我的要求!非常感谢你。我想这将能够满足我的要求!