Skip to content

使用 filters 做数据清洗

suxb201 edited this page Sep 22, 2022 · 2 revisions

redis-shake 3.x 支持用户传入 lua 脚本来做数据清洗使用。

具有较高的灵活度,可以轻松实现按命令过滤、按 key 过滤等功能。

filter 脚本书写说明

filter 脚本使用 lua 语言编写,在启动 redis-shake 的时候通过命令行传入:

./redis-shake sync.toml ../filters/print.lua  

filter 脚本内需要实现一个名为 filter 的 lua 函数:

function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms)
    -- write something
    return 0, db_id
end

参数说明:

  • id:number 类型,redis-shake 会对所有数据进行编号,无意义
  • is_base:boolean 类型,代表这条数据是否是 dump.rdb 中的,可用于跳过存量数据,只同步增量数据。
  • group:string 类型,代表这条数据是什么类型的,大写,比如 STRING、HASH、LIST、SET 等
  • cmd_name:string 类型,代表 Redis 命令,大写,比如:HSET、XADD、LPOP 等
  • keys:table 类型,代表命令中的 key,这里使用 table 类型是因为有多个 key 的命令,比如 MSET
  • slots:table 类型,对应 key 所属于的 slot。
  • db_id:number 类型,databse id。
  • timestamp_ms:时间戳,目前不可用。

返回值说明:

  • code:可选值 0,1,2
    • 0:允许此条数据发送至对端
    • 1:跳过此条数据
    • 2:不应该出现此数据,立即终止 redis-shake
  • db_id:代表这条命令会发送到哪个 database,只在 swap.db 中使用。一般情况下与传入 db_id 保持一致即可。

已有脚本

内置脚本均在:https://github.com/alibaba/RedisShake/tree/v3/filters

👏 欢迎提 PR 贡献更多的脚本。

print.lua 打印所有数据

将 redis-shake 发送的所有命令打印出来,供学习调试使用:

image

swap_db.lua 交换 db

function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms)
    if db_id == 0 then
        return 0, 1
    elseif db_id == 1 then
        return 0, 0
    else
        return 1, db_id
    end
end

将 database 1 的数据发送到 databse 0,将 database 0 的数据发送到 database 1,其余 database 的数据均丢弃。

skip_scripts.lua 跳过所有 SCRIPTING 命令

有时候备库不支持 SCRIPT LOAD 命令,可以使用 skip_scripts.lua 过滤掉所有 LUA 脚本。

-- skip all scripts included LUA scripts and Redis Functions.
function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms)
    if group == "SCRIPTING" then
        return 1, db_id -- disallow
    else
        return 0, db_id -- allow
    end
end

key_prefix.lua 按前缀过滤

举例过滤掉前缀为 ABC 的数据:

-- skip keys prefixed with ABC
function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms)
    if #keys ~= 1 then
        return 0, db_id -- allow
    end

    if string.sub(keys[1], 0, 3) == "ABC" then
    return 1, db_id -- disallow
    end

    return 0, db_id -- allow
end
  • 可以修改返回值,控制是过滤掉指定前缀的数据,还是仅通过制定前缀的数据。
  • 注意对于增量的 MSET ABC1 value ABC2 value 这种命令,需要在 lua 中额外判断。