使用lua脚本更改redis中的key的名称

Posted wen-pan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用lua脚本更改redis中的key的名称相关的知识,希望对你有一定的参考价值。

1、问题说明

该问题是在我司的某个项目中,由于前期上线的时候存入redis中的用户收藏的店铺信息的key没有做渠道区分,后面新增渠道区分,要求以后写入Redis的key都需要带有渠道号,并且要将原来没有渠道号的key统一修改(即修改原来的key名称,给原来的key名称上增加一个渠道号:比如,原来的key是:xxxui:pos_favorites:xxx-prd:10001,现在需要将该key修改为 xxxui:pos_favorites:xxx-prd:渠道号:10001)。

注意:这里只能修改符合修改条件的key,其他的key不能受到影响。比如:key必须是以 xxxui:pos_favorites:*开头的,并且按照 :拆分后长度为4,并且拆分后的最后的一个位置的字符串必须为数字。

2、lua脚本

-- 字符串按separator进行拆分
local function split(str, separator)
local startIndex = 1
local splitIndex = 1
-- 缓存拆分后的结果集
local result = {}
while true do
   -- 从 startIndex 起,寻找分隔符separator的下标位置,不存在则返回nil
   local nFindLastIndex = string.find(str, separator, startIndex)
   -- 当从startIndex开始向后找分隔符的索引位置,没有找到了则进入if,处理字符串最后一部分
   if not nFindLastIndex then
    -- 截取子串放入到结果集的对应位置上
    result[splitIndex] = string.sub(str, startIndex, string.len(str))
    break
   end
   -- 在结果集 result 的第 splitIndex 位置放置该子串
   result[splitIndex] = string.sub(str, startIndex, nFindLastIndex - 1)
   -- 重新赋值 startIndex ,进入下一次的循环
   startIndex = nFindLastIndex + string.len(separator)
   -- 下标自增1
   splitIndex = splitIndex + 1
end
return result
end

-- 获取用户输入参数
local prefix = KEYS[1]
local partition = KEYS[2]
local joinSymbol = KEYS[3]
local additional = KEYS[4]
-- 按用户给定的前缀查询keys
local ks = redis.call('KEYS', prefix)

-- 遍历获取到的每一个key
for i = 1, #ks do
   local res = split(ks[i],partition)
   local csgui = res[1]..joinSymbol
   local posFavorites = res[2]..joinSymbol
   local siteCode = res[3]..joinSymbol
   local customerId = joinSymbol..res[4]
   -- 必须长度为4,且切割后第四位上的数字必须是0才重命名,其他情况不做任何操作(防止误修改其他key)
   if tonumber(res[4]) and #res = 4 then
    	-- 拼接的方式:比如获取到要修改的key为 csgui:pos_favorites:dev:10001,现在需要在第三个字符串dev后增加
    	-- 一个渠道号(H5),所以需要先将csgui、pos_favorites、dev先使用 : 拼接起来,然后再拼接渠道号,然后再是后面的数字
       local val = redis.call('rename', ks[i], csgui..posFavorites..siteCode..additional..customerId)
   end
end
return true

3、执行该lua脚本示例

eval "local function split(str, separator)
local startIndex = 1
local splitIndex = 1
local result = {}
while true do
   local nFindLastIndex = string.find(str, separator, startIndex)
   if not nFindLastIndex then
    result[splitIndex] = string.sub(str, startIndex, string.len(str))
    break
   end
   result[splitIndex] = string.sub(str, startIndex, nFindLastIndex - 1)
   startIndex = nFindLastIndex + string.len(separator)
   splitIndex = splitIndex + 1
end
return result
end

local prefix = KEYS[1]
local partition = KEYS[2]
local joinSymbol = KEYS[3]
local additional = KEYS[4]
local ks = redis.call('KEYS', prefix)

for i = 1, #ks do
   local res = split(ks[i],partition)
   local csgui = res[1]..joinSymbol
   local posFavorites = res[2]..joinSymbol
   local siteCode = res[3]..joinSymbol
   local customerId = joinSymbol..res[4]
   print(#res)
   if tonumber(res[4]) and #res == 4 then
       local val = redis.call('rename', ks[i], csgui..posFavorites..siteCode..additional..customerId)
    end
end
return true" 4 csgui:pos_favorites:* : : H1

以上是关于使用lua脚本更改redis中的key的名称的主要内容,如果未能解决你的问题,请参考以下文章

lua在redis集群中的解决方案-- command keys must in same slot

redis使用String+lua实现分布式锁

Redis+Lua实现限流

redis中使用lua脚本及使用脚本完成限流

Redis:ioredis 与 lua 脚本

Redis进阶应用:Redis+Lua脚本实现复合操作