问题描述
我正在尝试将实体保存到 redis 中。每个实体都是一个 JSON(我不对该 json 进行任何操作,所以我认为 (?) redis-json 不会在这里帮助我)。
我的服务接收(通过 kafka 主题)很多实体。其中一些是其他实体的更新。
每个实体都有一个“eventId”(类似于“category”)、“bms”(类似于“entity-id”)。具有相同 eventId
的多个实体可能具有不同的 bms
。
为了能够支持消费者组(多个 kafka 消费者),所有这些消费者组都将实体保存在 Redis 中:每个实体都有一个版本(整数 >=0)。
逻辑
仅当 new
(来自 kafka)实体的版本 > current
(redis 内部)实体的版本时才保存实体。
数据
我的服务每秒从 kafka 消耗多达 1k 个实体。这意味着我每秒最多需要 SET
1k 次。
解决方案
1.每个实体的 Lua 调用
local event_id = KEYS[1]
local bms = ARGV[1]
local new_version = tonumber(ARGV[2])
local new_offer = ARGV[3]
local bms_offer_hm_key = 'bms-offers--' .. event_id
local bms_version_hm_key = 'bms-version--' .. event_id
local current_version = tonumber(redis.call('HMGET',bms_version_hm_key,bms))
if current_version == nil or current_version < new_version then
redis.call('HMSET',bms,new_version)
redis.call('HMSET',bms_offer_hm_key,new_offer)
return 1
else
return 0
end
性能:
2.所有实体的 Lua 调用
local j=1
for i=1,#KEYS do
local event_id = KEYS[i]
local bms = ARGV[j]
local new_version = tonumber(ARGV[j+1])
local new_offer = ARGV[j+2]
local bms_offer_hm_key = 'bms-offers--' .. event_id
local bms_version_hm_key = 'bms-version--' .. event_id
local current_version = tonumber(redis.call('HMGET',bms))
if current_version == nil or current_version < new_version then
redis.call('HMSET',new_version)
redis.call('HMSET',new_offer)
end
j=j+3
end
性能:
- redis 1k 插入 -> 0.200s
3.每个实体的 Lua 调用 - 单个 HM
- 现在我使用
HSET
而不是HMSET
。感谢@raina77ow。
local molly_event_id = KEYS[1]
local bms = ARGV[1]
local new_version = tonumber(ARGV[2])
local new_offer = ARGV[3]
local key = 'molly-offers::' .. molly_event_id
local bms_sub_key = "bms::" .. bms
local version_sub_key = "version::" .. bms
local current_version = tonumber(redis.call('HMGET',key,version_sub_key))
if current_version == nil or current_version < new_version then
redis.call('HSET',version_sub_key,new_offer,bms_sub_key,new_version)
return 1
else
return 0
end
性能
更多性能和信息
我的上述指标基于 macbook pro 上的 docker-redis:
macos catalina 10.15.1 (19B2093)
2.6 GHz 6-Core Intel Core i7
16 GB 2667 MHz DDR4
当尝试运行 1k 个随机集(具有相同的实体)(没有 lua 脚本)时:
- 1k 插入 -> 0.025s
- 2k 插入 -> 0.050 秒
- 10k 插入 -> 0.211s
- 45k 插入 -> 1.000s
我还没有投入生产,但是当我投入生产时,redis 将在 k8s pod 上运行。
- 单个redis实例
- AOF + 每次写入后
- 我仍在调查Redis Labs - Your Cloud Can’t Do That: 0.5M ops + ACID @<1ms Latency!
问题
- 有没有办法让 lua 脚本更快?我愿意接受任何更改!
- 我可能会在 lua 脚本阻止 redis 时阻止其他客户端读取实体。多节点会产生额外的分布式逻辑复杂性,如果可能,我想避免这种复杂性。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)