同步Redis后出现数据不一致

更新时间:
复制为 MD 格式

本文介绍判断或排查同步Redis出现数据不一致的方法。

问题描述

使用数据传输服务(DTS)同步Redis后,出现了源端和目标端数据不一致的现象。

问题示例

使用数据传输服务(DTS)同步完Redis后,使用Redisinfo keyspace命令查看源端和目标端的keys情况,出现源端和目标端数据不一致,且含过期时间的keys占很大比重。

xxx> info keyspace
# Keyspace
db0:keys=769509,expires=227386,avg_ttl=3426607441
db3:keys=254,expires=0,avg_ttl=0
db2:keys=17,expires=2,avg_ttl=837582
db1:keys=2,expires=0,avg_ttl=0
db15:keys=2,expires=0,avg_ttl=0
[work@rec01 bin]$ ./redis-cli -a 'xxx'
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=772864,expires=230736,avg_ttl=3380950183
db1:keys=2,expires=0,avg_ttl=0
db2:keys=17,expires=2,avg_ttl=868931
db3:keys=254,expires=0,avg_ttl=0
db15:keys=2,expires=0,avg_ttl=0
127.0.0.1:6379>

可能原因

单靠info keyspaceexpires来判断数据是否一致会出现偏差。其统计信息的统计值不是精确值,有一定的误差。

  • info keyspace的输出结果中:

    • keys表示所有keys的数据量。

    • expires表示带有过期keys的数据量,包含未过期和已过期的keys的数量。

因此,通过expires来判断数据量时,逻辑上已经过期但未被Redis删除的keys也会被统计进来,从而出现了源端和目标端的数据不一致的现象。

说明

Redis处理过期keys的时机主要为以下几种:

  • CPU空闲时清理过期keys。

  • 实际访问keys时会判断keys是否过期,并逐出过期keys。

  • Scan命令扫描时判断keys是否过期,并逐出过期keys。

关于Redis的详细清理策略,参考:Redis过期Key的处理

解决方法

建议可通过以下2种方法判断数据是否一致:

说明

同步Redis数据的任务,若想看同步之后数据是否有丢失,需要看源数据keys是否已经过期。已过期的数据也会被统计到expires中,因此,不能单靠expires去判断数据的一致性。

  1. 对比A(源库keys数量减去expires后得到的数量)与B(目标库keys数量减去expires后得到的数量),若AB的差值很小,则可判断数据一致。

  2. redis-full-check校验。具体方法可参考:redis-full-check工具的使用

说明

如何让Redis info keyspace统计的内存使用量、数据量看起来一致?

建议清除过期的Redis数据,云数据库和自建数据库的方法如下:

  • 云数据库 Tair(兼容 Redis):登录云数据库 Tair(兼容 Redis)控制台,执行清除数据操作。云数据库 Redis:在控制台打开清除数据对话框,选择过期数据页签,选择执行方式(立即执行可维护时间内执行),单击确定。该操作将执行 SCAN 批量清除实例的所有过期数据,清除后无法找回。

  • 自建Redis数据库:使用redis-full-check做校验,检验的过程中执行SCAN 等命令触发过期数据清理动作。