redis主从复制 - 从属

时间:2016-09-30 15:17:39

标签: redis replication database-replication master-slave node-redis

问题

我遇到的情况是,我在主服务器上创建的数据似乎没有正确复制到我的从服务器。

掌握Redis数据库设置信息

我有一个在10.1.1.1上运行的主服务器。配置设置为“保存”到磁盘。这是配置文件中的一个片段:

save 900 1
save 300 10
save 60 10000

当我针对相关哈希运行扫描命令时,结果如下(这是正确的):

127.0.0.1:6379> scan 0 match dep:*
1) "13"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_19:00_25:00"
   3) "dep:+19999999999_08:00_12:00"
127.0.0.1:6379> 

从属1设置

Slave 1已设置为仅在内存中运行。因此,在配置文件中,所有“保存”选项都已注释掉。

这是我在奴隶1中的数据:(缺少记录)

127.0.0.1:6379> scan 0 match dep:*
1) "15"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_19:00_25:00"
127.0.0.1:6379> 

当我在这个奴隶上运行“info”命令时,这就是我的回复:(只挑选了我认为可能与此问题有关的特定项目)

# Replication
role:slave
master_host:10.1.1.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:346292
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

#Stats
expired_keys:0

#Persistence
aof_enabled:0

从属2设置

Slave 2也应该只是一个内存数据存储。所以配置文件中的所有保存选项也都被注释掉了:

#save 900 1
#save 300 10
#save 60 10000

这是我在slave 2上的数据(注意它是丢失的数据,但来自slave 1的不同记录)

127.0.0.1:6379> scan 0 match dep:*
1) "3"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_08:00_12:00"
127.0.0.1:6379> 

info命令的一些结果:

# Replication
role:slave
master_host:10.1.1.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:346754
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

#Stats
expired_keys:0

#Persistence
aof_enabled:0

这是我第一次尝试使用REDIS,所以我确信这是我错过的一些简单的事情。 我还没有试过在奴隶身上重新启动REDIS,因为我不想丢失任何可能帮助我解决/理解我是如何让自己在这里的文物。

任何建议将不胜感激。

编辑1

在检查slave 2上的日志时,这就是我发现的:

4651:S 27 Sep 18:39:27.197 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4651:S 27 Sep 18:39:27.197 # Server started, Redis version 3.0.5
4651:S 27 Sep 18:39:27.197 * The server is now ready to accept connections on port 6379
4651:S 27 Sep 18:39:27.198 * Connecting to MASTER 10.1.1.1:6379
4651:S 27 Sep 18:39:27.198 * MASTER <-> SLAVE sync started
4651:S 27 Sep 18:40:28.284 # Timeout connecting to the MASTER...
4651:S 27 Sep 18:40:28.284 * Connecting to MASTER 10.1.1.1:6379
4651:S 27 Sep 18:40:28.284 * MASTER <-> SLAVE sync started
4651:S 27 Sep 18:41:29.369 # Timeout connecting to the MASTER...
4651:S 27 Sep 18:41:29.369 * Connecting to MASTER 10.1.1.1:6379
4651:S 27 Sep 18:41:29.369 * MASTER <-> SLAVE sync started
4651:S 27 Sep 18:42:00.452 * Non blocking connect for SYNC fired the event.
4651:S 27 Sep 18:42:00.453 * Master replied to PING, replication can continue...
4651:S 27 Sep 18:42:00.453 * Partial resynchronization not possible (no cached master)
4651:S 27 Sep 18:42:00.463 * Full resync from master: b46c3622e4ef4c5586ebd2ec23eabcb04c3fcf32:1
4651:S 27 Sep 18:42:00.592 * MASTER <-> SLAVE sync: receiving 173 bytes from master
4651:S 27 Sep 18:42:00.592 * MASTER <-> SLAVE sync: Flushing old data
4651:S 27 Sep 18:42:00.592 * MASTER <-> SLAVE sync: Loading DB in memory
4651:S 27 Sep 18:42:00.592 * MASTER <-> SLAVE sync: Finished with success

当超时连接到主设备时,redis从设备如何恢复?我也想知道这个错误意味着“部分重新同步不可能(没有缓存的主机)”。

目前谷歌搜索...但如果您有任何意见,请随意

编辑2

这是另一个非常有趣的发现(至少对我而言)。 我刚刚添加了一个新项目的主人,如下:

127.0.0.1:6379> HMSET dep:+19999999999_15:00_18:45:00 ext 2222 dd me.net days "fri"
OK
127.0.0.1:6379> scan 0 match dep:*
1) "13"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_19:00_25:00"
   3) "dep:+19999999999_15:00_18:45:00"
   4) "dep:+19999999999_08:00_12:00"
127.0.0.1:6379> 

现在,当我再次检查奴隶时,它仍然只有2条记录,但是它丢弃了曾经存在的记录,并将其替换为我刚添加的新记录:

127.0.0.1:6379> scan 0 match dep:*
1) "7"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_15:00_18:45:00"
127.0.0.1:6379> 

编辑3

从下面的答案中,看起来SCAN命令返回的第一个数字是光标中的位置......在阅读文档时,我可以指定一个指示要返回的记录数的计数。 但这仍然为我提出了一些问题。例如,根据下面的答案,我在奴隶上尝试了以下SCAN命令:

127.0.0.1:6379> scan 0 match dep:*
1) "7"
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_15:00_18:45:00"
127.0.0.1:6379> scan 7 match dep:*
1) "0"
2) 1) "dep:+19999999999_19:00_25:00"
   2) "dep:+19999999999_08:00_12:00"
127.0.0.1:6379> 

这对我有意义......它似乎一次返回2条记录(仍需要弄清楚如何更改此默认值)

根据这篇文章 - Redis scan count: How to force SCAN to return all keys matching a pattern? - ,我可以使用“count”关键字来指示要返回的记录数。

但是为了获得我拥有的所有4条记录,我必须在光标值返回为零之前运行几个查询...而且我不知道为什么。例如:

127.0.0.1:6379> scan 0 match dep:* count 3
1) "10"
2) 1) "dep:+19999999999_00:00_00:00"
127.0.0.1:6379> scan 10 match dep:* count 3
1) "3"
2) (empty list or set)
127.0.0.1:6379> scan 3 match dep:* count 3
1) "7"
2) 1) "dep:+19999999999_15:00_18:45:00"
127.0.0.1:6379> scan 7 match dep:* count 3
1) "0"
2) 1) "dep:+19999999999_19:00_25:00"
   2) "dep:+19999999999_08:00_12:00"
127.0.0.1:6379> 

为什么第一个请求没有返回3条记录?在我看来,最多,我应该不得不两次运行这个扫描命令。 你能解释一下这里发生了什么吗?

另外,也许我不应该在我的节点js REST API中使用scan命令?想象一下,用户将请求窗口小部件信息......我需要查询此哈希以找到密钥。 感觉就像这种类型的迭代效率非常低。 KEYS命令也可以工作,但根据文档,我不应该在生产中使用它,因为它会影响性能。 任何意见/见解将不胜感激。

1 个答案:

答案 0 :(得分:1)

您没有迭代Redis实例中的所有密钥。

为了进行完整的迭代,您应该继续使用返回的游标向Redis发送SCAN命令,直到返回的游标为0

在你的上一个例子中:

127.0.0.1:6379> scan 0 match dep:*
1) "7"    <---- returned cursor
2) 1) "dep:+19999999999_00:00_00:00"
   2) "dep:+19999999999_15:00_18:45:00"
127.0.0.1:6379> 
// here, you need continue sending scan command with the returned cursor, i.e. 7
127.0.0.1:6379> scan 7 match dep:*
// then you can get more results from Redis
// If the full iteration is finished, it should return something like this:
1) "0"    <----- this means the full iteration is finished
2) 1) "dep:more result"
   2) "dep:last result"

修改

count number SCAN命令只是一个提示。无法保证Redis应准确返回count number个结果(有关详情,请参阅the doc)。

为了一次性获取所有键,您可以使用KEYS命令。但是,就像你提到的那样,它不是一个好主意(它可能会长时间阻止Redis),这就是为什么Redis有这个SCAN命令来获取迭代中的所有键。

SCANKEYS命令都遍历整个密钥空间以查找匹配项。因此,如果数据集非常大,它们都需要很长时间来获取/迭代所有键。

从您的问题描述中,我认为您应该将数据存储在Redis的HASH结构中,并使用HKEYSHGETALLHSCAN来获取数据:< / p>

hset dep:+19999999999 00:00_00:00:00 value
hset dep:+19999999999 15:00_18:45:00 value
hkeys dep:+19999999999    <----- get all fields in this hash
hgetall dep:+19999999999  <----- get all fields and values in this hash
hscan dep:+19999999999 0  <----- scan the hash to key fields

这比遍历整个密钥空间要有效得多。特别是,如果哈希中没有太多字段,HKEYSHGETALL可以一次性获取所有键/数据,并且非常快。但是,如果哈希中的字段太多,您仍需要使用HSCAN进行迭代。