全量检查-Redis

鹰眼

1 项目概述

1.1 背景介绍及目标

  • Redis 集群间数据检查

1.2 名词说明

1.2.1 数据一致率

  • 一致率 = (key_sum_num - key_diff_num)/key_sum_num * 100%

1.3 Roadmap

2 需求分析

需求分析重点是需求

2.1 功能需求

2.1.1 不一致类型

不一致的方式主要分为 2 类:key 不一致和 value 不一致。

2.1.2 key 不一致

key 不一致主要分为以下几种情况:

  • lack_target : key 存在于源库,但不存在于目的库。

  • type: key 存在于源库和目的库,但是类型不一致。

  • length: value 长度不一致

  • value: key 存在于源库和目的库,且类型一致,但是 value 不一致。

    • string: value 不同。

    • hash: 存在 field,满足下面 3 个条件之一:

      • field 存在于源端,但不存在与目的端。

      • field 存在于目的端,但不存在与源端。

      • field 同时存在于源和目的端,但是 value 不同。

    • set/zset:与 hash 类似。

    • list: 与 hash 类似。

  • other: 其他异常

field 冲突类型有以下几种情况(只存在于 hash,set,zset,list 类型 key 中):

  • lack_source: field 存在于源端 key,field 不存在与目的端 key。

  • lack_target: field 不存在与源端 key,field 存在于目的端 key。

  • value: field 存在于源端 key 和目的端 key,但是 field 对应的 value 不同。

2.1.3 对比模式

check_method

  • length: 对比 value 值的长度是否相等。

  • content: 对比 value 长度、value 值是否相等。

    • 对于 hash,set,zset,list 大 key 处理采用以下方式:

      • len <= 1000,直接取全量 field、value 进行比较,使用如下命令:hgetall,smembers,zrange 0 -1 withscores,lrange 0 -1。

      • len > 1000, 仅打印日志,不校验数据

2.2 非功能需求

2.3 调研

2.3.1 vipshop/redis-migrate-tool

https://github.com/vipshop/redis-migrate-tool

$src/redis-migrate-tool -c rmt.conf -o log -C redis_check
Check job is running...

Checked keys: 1000
Inconsistent value keys: 0
Inconsistent expire keys : 0
Other check error keys: 0
Checked OK keys: 1000

All keys checked OK!
Check job finished, used 1.041s

如果想检查更多的 key,可以使用下面命令:

$src/redis-migrate-tool -c rmt.conf -o log -C "redis_check 200000"
Check job is running...

Checked keys: 200000
Inconsistent value keys: 0
Inconsistent expire keys : 0
Other check error keys: 0
Checked OK keys: 200000

All keys checked OK!
Check job finished, used 11.962s

插入一些测试 key (redis_testinsert)

$src/redis-migrate-tool -c rmt.conf -o log -C "redis_testinsert"
Test insert job is running...

Insert string keys: 200
Insert list keys  : 200
Insert set keys   : 200
Insert zset keys  : 200
Insert hash keys  : 200
Insert total keys : 1000

Correct inserted keys: 1000
Test insert job finished, used 0.525s

$ 插入更多的 key
$src/redis-migrate-tool -c rmt.conf -o log -C "redis_testinsert 30000"

2.3.2 alibaba/RedisFullCheck

https://github.com/alibaba/RedisFullCheck

3 总体设计

总体设计重点是设计与折衷

3.1 系统架构

一般来说会有个简单的架构图,并配以文字对架构进行简要说明;

    +------------------------------------------------+
    | +--------------------------+ +---------------+ |
    | |       Source Redis       | | Target  Redis | |
    | + ------------^--------^-^-+ +-------------^-+ |
    +---------------|----------\-\---------------|---+
                    | redis       \ \ twemproxy  |
                    1(scan)    (type)2 3         3(length + content)
                    |                   \ \      |
                    |                      \ \   |
    +---------------|-------------------------+-\+---+
    |               |                            |   |
    | +yingyan------------------+  +yingyan_agent--+ |
    | |+----------+ +----------+|  | +-----------+ | |
    | ||scan_group| |scan_shard||  | | key_check | | |
    | |+--+-------+ +--+----+--+|  | +-----+-----+ | |
    | +---|------------|----|---+  +-------|-------+ |
    +-----|------------|----|--------------|---------+
          |            |    |              |
   (1)push|     (2)pull|    |(2)push       |(3)pull
          |            |    |              |
          |            |    |              |
          |            |    |              |
    +MQ---V------------V----V--------------V---------+
    |             +---------+                        |
    |             |Twemproxy| \                      |
    |             +--+---+--+  +----------+          |
    |                |   |     |Metaserver|          |
    |             +--V---V--+  +----------+          |
    |             |  Redis  | /                      |
    |             +---------+                        |
    +------------------------------------------------+

(1) scan_group(src_group, dst_group)
    获取源集群 redis shard 从库 ip port
(2) scan_shard(src_group, dst_group, src_ip, src_port)
    对从库进行 scan 获取 key,每 1000 个 key 进行打包发到队列(同时包含 src_ip, src_port, dst_ip, dst_port)
(3) key_check(src_ip, src_port, dst_ip, dst_port, key_list)
    从源集群获取集群 type
    根据 type 对集群的 key 的 value 进行检查长度,
        若长度不一则进行记录
            目标 value 长度为 0: 则记录为 lack_target
            目标 value 长度为其他 length: 则记录为 length
            目标 value 中含 "WRONGTYPE": 则记录为 type
            目标 value 异常:则记录为 "other"
        长度一致
            若检查内容,则对比内容的 md5 值
            

3.2 模块简介

架构图中如果有很多模块,需要对各个模块的功能进行简要介绍;

3.3 设计与折衷

设计与折衷是总体设计中最重要的部分;

3.4 潜在风险

4 详细设计

详细设计重点在“详细”

4.1 分发任务

(有了数据库 + 接口 + 流程,别的同学拿到详设文档,基本也能够搞定了)

4.1.1 交互流程

简要的交互可用文字说明,复杂的交互建议使用流程图,交互图或其他图形进行说明

4.1.2 数据库设计

4.1.3 接口形式

4.1.4 Redis key

python 中 repr 和 eval 可以用来在数据结构和字符串间互转 在这个功能上,repr 和 str 的作用一样,把一个数据结构转换成字符串,例如:

>>> repr([1,2,3,4])
'[1, 2, 3, 4]'

eval 是把字符串转换成数据结构,例如:
>>> eval('[1,2,3,4]')
[1, 2, 3, 4]

Redis 中很多 key name 是使用的中文,可以先通过 repr(key) 转为字符串,塞入队列,然后处理 worker 获取到时先 eval(key_str) 进行转换为原数据

5 数据统计

5.1 scan 耗时

  • 10G 数据,不限速

scan_count:256
cost:66s
counts:43676
key_num:8746171(874w)

avg_qps:661
cpu: 上涨 30%
  • 10G 数据(每次 scan 后,等待 10ms)

scan_count:256
cost:519s
counts:43752
key_num:8761618

avg_qps:84
cpu: 上涨 6%

5.2 scan 并发送任务耗时

  • 10G 数据 (900w key)

生产者:
    发送耗时:154s(3 分钟)
    开始时间:2021-09-01 12:23:29
    结束时间:2021-09-01 12:26:03

消费者:
    处理耗时:17 分钟
    开始时间:2021-09-01 12:23:30
    结束时间:2021-09-01 12:40:34

目标集群 CPU:
    上涨 5-10% 左右

Last updated