簡體   English   中英

redis 主從復制 - 從屬上丟失數據

[英]redis master slave replication - missing data on the slave

問題

我有一種情況,我在主站上創建的數據似乎沒有正確復制到我的從站。

主 Redis 數據庫設置信息

我有一個運行在 10.1.1.1 上的主人。 配置設置為“SAVE”到磁盤。 這是配置文件中的一個片段:

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 設置

從站 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> 

當我在這個奴隸上運行“信息”命令時,這就是我得到的:(只選擇了我認為可能與這個問題有關的特定項目)

# 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

這是我在從站 2 上的數據(注意它缺少數據,但記錄與從站 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

在檢查從站 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

當連接到 master 超時時,redis slaves 如何恢復? 我也想知道這個錯誤是什么意思“部分重新同步不可能(沒有緩存的主)”。

目前正在谷歌搜索...但如果您有任何意見,請隨時

編輯 2

這是另一個非常有趣的發現(至少對我而言)。 我剛剛在 master 中添加了一個新項目,如下所示:

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> 

現在,當我再次檢查 slave 時,它​​仍然只有 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 條記錄? 在我看來,我最多應該運行這個掃描命令 2 次。 你能解釋一下這里發生了什么嗎?

另外,也許我不應該在我的節點 js REST API 中使用 scan 命令? 想象一下,用戶將請求小部件信息……我需要查詢此哈希以找到密鑰。 感覺這種類型的迭代會非常低效。 KEYS 命令也可以使用,但根據文檔,我不應該在生產中使用它,因為它會影響性能。 任何評論/見解將不勝感激。

您尚未迭代 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"

編輯

SCAN命令的count number只是一個提示 無法保證 Redis 應該准確返回count number結果(有關更多詳細信息,請參閱文檔)。

為了一次性獲得所有關鍵點,您可以使用KEYS命令。 但是,正如您所提到的,這不是一個好主意(它可能會長時間阻塞 Redis),這就是為什么 Redis 具有此SCAN命令來獲取迭代中的所有鍵的原因。

SCANKEYS命令都遍歷整個密鑰空間以找到匹配項。 因此,如果數據集非常大,它們都需要很長時間來獲取/迭代所有鍵。

根據您的問題描述,我認為您應該將數據存儲在 Redis 的HASH結構中,並使用HKEYSHGETALLHSCAN獲取數據:

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可以HGETALL獲取所有鍵/數據,而且速度非常快。 但是,如果hash中的字段太多,仍然需要使用HSCAN進行迭代。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM