資料庫同步 Elasticsearch 後資料不一致,怎麼辦?

大資料技術前線發表於2023-04-18

1、實戰線上問題

  • Q1:Logstash 同步 postgreSQL 到 Elasticsearch 資料不一致。

在使用 Logstash 從 pg 庫中將一張表匯入到 ES 中時,發現 ES 中的資料量和 PG 庫中的這張表的資料量存在較大差距。如何快速比對哪些資料沒有插入?匯入過程中,Logstash 日誌沒有異常。PG 中這張表有 7600W。

  • Q2:mq 非同步雙寫資料庫、es 的方案中,如何保證資料庫資料和 es 資料的一致性?

2、推薦解決方案之一——ID 比較法

如下示例,僅拿問題1舉例驗證,問題2原理一致。

2.1 方案探討

要找出哪些資料沒有插入到 Elasticsearch 中,可以採用以下方法:

  • 確保 Logstash 配置檔案中的 input 外掛的 JDBC 驅動程式正確配置,以便從 PostgreSQL 資料庫中提取所有資料。注意 statement 引數,確保它選擇了所有需要的資料。

  • 檢查 Logstash 配置檔案的 output 外掛,確保正確配置了 Elasticsearch 的連線引數。同時,檢查是否有過濾器在匯入過程中過濾掉了部分資料。

  • 在 Logstash 配置檔案中新增一個 stdout 外掛,將從 PostgreSQL 資料庫中讀取的資料記錄到檔案中。

例如,可以新增以下內容:

output {
  elasticsearch {
    ...Elasticsearch 配置...
  }
  stdout {
    codec => json_lines
    path => "/path/to/logstash_output.log"
  }
}

將 Logstash 輸出檔案與 PostgreSQL 資料庫中的原始資料進行比較,以找出未匯入的資料。可以使用 Python、Shell 指令碼或其他程式語言編寫一個簡單的指令碼來執行此操作。

如果 Logstash 輸出檔案中的記錄數與 PostgreSQL 資料庫中的記錄數一致,但 Elasticsearch 中的記錄數不一致,請檢查 Elasticsearch 叢集的健康狀況和日誌。確認叢集是否在接收和索引資料時遇到問題。

如果問題仍然存在,嘗試將批次操作的大小減小,以減輕 Elasticsearch 和 Logstash 的負擔。可以透過在 Logstash 配置檔案的 output 外掛中設定 flush_size 和 idle_flush_time 引數來實現。

處理大量資料時,可能需要調整 Logstash 和 Elasticsearch 的效能和資源配置。根據硬體和網路條件,可能需要最佳化批次操作、JVM 設定、執行緒池大小等方面的設定。

2.2 比較指令碼的實現

以下是一個簡單的 Shell 指令碼示例,用於比較 Logstash 輸出檔案(JSON 格式)和 PostgreSQL 資料庫中的資料。該指令碼將比較特定欄位(如 id)以確定哪些資料可能未匯入到 Elasticsearch。

資料庫同步 Elasticsearch 後資料不一致,怎麼辦?

首先,從 PostgreSQL 資料庫中匯出資料,將其儲存為 CSV 檔案:

COPY (SELECT id FROM your_table) TO '/path/to/postgres_data.csv' WITH

接下來,建立一個名為 compare.sh 的 Shell 指令碼:

#!/bin/bash
# 將 JSON 檔案中的 ID 提取到一個檔案中
jq '.id' /path/to/logstash_output.log > logstash_ids.txt

# 刪除 JSON 中的雙引號
sed -i 's/"//g' logstash_ids.txt

# 對 Logstash 和 PostgreSQL 的 ID 檔案進行排序
sort -n logstash_ids.txt > logstash_ids_sorted.txt
sort -n /path/to/postgres_data.csv > postgres_ids_sorted.txt

# 使用 comm 比較兩個已排序的 ID 檔案
comm -23 postgres_ids_sorted.txt logstash_ids_sorted.txt > missing_ids.txt

# 輸出結果
echo "以下 ID 在 Logstash 輸出檔案中未找到:"
cat missing_ids.txt

為指令碼新增可執行許可權並執行:

chmod +x compare.sh

./compare.sh

此指令碼會比較 logstash_output.log 和 postgres_data.csv 檔案中的 ID。如果發現缺失的 ID,它們將被儲存在 missing_ids.txt 檔案中,並輸出到控制檯。請注意,該指令碼假設已經安裝了 jq(一個命令列 JSON 處理器)。如果沒有,請先安裝 jq

3、推薦方案二——Redis 加速對比

在這種情況下,可以使用 Redis 的集合資料型別來儲存 PostgreSQL 資料庫和 Logstash 輸出檔案中的 ID。接下來,可以使用 Redis 提供的集合操作來找到缺失的 ID。

資料庫同步 Elasticsearch 後資料不一致,怎麼辦?

以下是一個使用 Redis 實現加速比對的示例:

首先,從 PostgreSQL 資料庫中匯出資料,將其儲存為 CSV 檔案:

COPY (SELECT id FROM your_table) TO '/path/to/postgres_data.csv' WITH CSV HEADER;

安裝並啟動 Redis。

使用 Python 指令碼將 ID 資料載入到 Redis:

import redis
import csv

# 連線到 Redis

r = redis.StrictRedis(host='localhost', port=6379, db=0)

# 從 PostgreSQL 匯出的 CSV 檔案中載入資料
with open('/path/to/postgres_data.csv', newline='') as csvfile:
    csv_reader = csv.reader(csvfile)
    next(csv_reader)  # 跳過表頭
    for row in csv_reader:
        r.sadd('postgres_ids', row[0])

# 從 Logstash 輸出檔案中載入資料
with open('/path/to/logstash_output.log', newline='') as logstash_file:
    for line in logstash_file:
        id = line.split('"id":')[1].split(',')[0].strip()
        r.sadd('logstash_ids', id)

# 計算差集
missing_ids = r.sdiff('postgres_ids''logstash_ids')

# 輸出缺失的 ID
print("以下 ID 在 Logstash 輸出檔案中未找到:")
for missing_id in missing_ids:
    print(missing_id)

這個 Python 指令碼使用 Redis 集合資料型別儲存 ID,然後計算它們之間的差集以找到缺失的 ID。需要先安裝 Python 的 Redis 庫。可以使用以下命令安裝:

pip install redis

這個指令碼是一個基本示例,可以根據需要修改和擴充套件它。使用 Redis 的優點是它能在記憶體中快速處理大量資料,而不需要在磁碟上讀取和寫入臨時檔案。

4、小結

方案一:使用 Shell 指令碼和 grep 命令

  • 優點:

(1)簡單,易於實現。

(2)不需要額外的庫或工具。

  • 缺點:

(1)速度較慢,因為它需要在磁碟上讀寫臨時檔案。

(2)對於大資料量的情況,可能會導致較高的磁碟 I/O 和記憶體消耗。

方案二:使用 Redis 實現加速比對

  • 優點:

(1)速度更快,因為 Redis 是基於記憶體的資料結構儲存。

(2)可擴充套件性較好,可以處理大量資料。

  • 缺點:

(1)實現相對複雜,需要編寫額外的指令碼。

(2)需要安裝和執行 Redis 伺服器。

根據需求和資料量,可以選擇合適的方案。如果處理的資料量較小,且對速度要求不高,可以選擇方案一,使用 Shell 指令碼和 grep 命令。這種方法簡單易用,但可能在大資料量下表現不佳。

如果需要處理大量資料,建議選擇方案二,使用 Redis 實現加速比對。這種方法速度更快,能夠有效地處理大資料量。然而,這種方法需要額外的設定和配置,例如安裝 Redis 伺服器和編寫 Python 指令碼。

在實際應用中,可能需要根據具體需求進行權衡,以選擇最適合的解決方案。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027827/viewspace-2946581/,如需轉載,請註明出處,否則將追究法律責任。

相關文章