用于实时库存应用的Redis关键设计

yuy*_*007 5 real-time redis node.js

我正在尝试构建一个实时库存应用程序。 每秒钟我都可以从Web服务获取一些数据,如下所示:

[{“金额”:“ 20”,“日期”:1386832664,“价格”:“ 183.8”,“标价”:5354831,“类型”:“出售”},{“金额”:“ 22”,“日期“:1386832664,” price“:” 183.61“,” tid“:5354833,” type“:” buy“}]

tid是用于买卖股票的票证ID;日期是从1970.1.1开始的第二个;价格/金额是按什么价格交易多少股票。

招募

我的要求是实时显示用户每分钟5分钟/小时/天的最高/最低价格;向用户实时显示每分钟/ 5分钟/小时/天的金额总和。

我的问题是如何将数据存储到Redis,以便我可以轻松快速地从DB获得不同时期的最高/最低交易。

我的设计如下所示:

[date]:[tid]:amount
[date]:[tid]:price
[date]:[tid]:type
Run Code Online (Sandbox Code Playgroud)

我是Redis的新手。如果设计是这样,则意味着我需要使用排序集,是否会出现性能问题?还是有其他方法可以获取不同时期的最高/最低价格。

期待您的建议和设计。

rkh*_*rov 4

我的建议是存储您感兴趣的所有间隔的最小/最大/总计,并在每个到达的数据点时更新当前间隔。为了避免读取以前的数据进行比较时出现网络延迟,您可以使用 Lua 脚本完全在 Redis 服务器内完成此操作。

\n\n

每个数据点(或者更糟糕的是,每个数据点字段)一个键将消耗太多内存。为了获得最佳结果,您应该将其分组为小列表/散列(请参阅http://redis.io/topics/memory-optimization)。Redis 只允许在其数据结构中进行一级嵌套:如果您的数据有多个字段,并且您希望每个键存储多个项目,则需要以某种方式自行对其进行编码。幸运的是,标准 Redis Lua 环境包括msgpack支持,这是一种非常高效的类似 JSON 的二进制格式。示例中使用 msgpack“按原样”编码的 JSON 条目的长度为 52-53 字节。我建议按时间分组,以便每个键有 100-1000 个条目。假设一分钟的间隔符合此要求。那么键控方案将是这样的:

\n\n

YYmmddHHMMSStid\xe2\x80\x94给定分钟内 msgpack 编码的数据点的哈希值。\n 5m:YYmmddHHMM, 1h:YYmmddHH, 1d:YYmmdd\xe2\x80\x94 窗口数据哈希值,其中包含min, max,sum字段。

\n\n

让我们看一个示例 Lua 脚本,它将接受一个数据点并根据需要更新所有键。由于 Redis 脚本的工作方式,我们需要显式传递脚本将访问的所有键的名称,即实时数据和所有三个窗口键。Redis Lua 也有可用的 JSON 解析库,因此为了简单起见,我们假设我们只传递 JSON 字典。这意味着我们必须解析两次数据:在应用程序端和Redis端,但其性能影响尚不清楚。

\n\n
local function update_window(winkey, price, amount)\n    local windata = redis.call(\'HGETALL\', winkey)\n    if price > tonumber(windata.max or 0) then\n        redis.call(\'HSET\', winkey, \'max\', price)\n    end\n    if price < tonumber(windata.min or 1e12) then\n        redis.call(\'HSET\', winkey, \'min\', price)\n    end\n    redis.call(\'HSET\', winkey, \'sum\', (windata.sum or 0) + amount)\nend\n\nlocal currkey, fiveminkey, hourkey, daykey = unpack(KEYS)\nlocal data = cjson.decode(ARGV[1])\nlocal packed = cmsgpack.pack(data)\nlocal tid = data.tid\nredis.call(\'HSET\', currkey, tid, packed)\nlocal price = tonumber(data.price)\nlocal amount = tonumber(data.amount)\nupdate_window(fiveminkey, price, amount)\nupdate_window(hourkey, price, amount)\nupdate_window(daykey, price, amount)\n
Run Code Online (Sandbox Code Playgroud)\n\n

此设置每秒可以执行数千次更新,对内存的消耗不是很大,并且可以立即检索窗口数据。

\n\n

更新:在内存部分,如果您想存储更多数百万个字节,则每个点 50-60 字节仍然很多。对于这种数据,我认为您可以使用自定义二进制格式、增量编码以及使用snappy之类的后续块压缩来获得低至 2-3 个字节的每个点。这取决于您的要求,是否值得这样做。

\n