動態

詳情 返回 返回

某訊一面,有點難度 - 動態 詳情

今天分享的是訓練營的朋友在某訊外包的面經,他在面完後跟我説:數據一致性策略好久沒問,有點忘了,所以這一塊答的不太好

我一直都會和大家強調複習的重要性,尤其是這種常見的問題。看看下面的問題你都能答得上來嗎?

基礎部分 - MYSQL和Redis

一、MySQL索引分類

  1. 普通索引(INDEX)

    • 這是最基本的索引類型,它沒有任何限制。它可以創建在任何數據類型的列上,主要目的是加快對數據的查詢速度。例如,在一個存儲用户信息的表中,對用户的姓名列創建普通索引。如果經常需要根據姓名來查找用户記錄,這個索引就能提高查詢效率。語法為CREATE INDEX index_name ON table_name (column_name);
  2. 唯一索引(UNIQUE)

    • 唯一索引要求索引列的值必須是唯一的,但是允許有空值。它主要用於保證數據的唯一性,同時也能提高查詢性能。比如在用户表中的手機號碼列,因為每個用户的手機號碼應該是唯一的,就可以創建唯一索引。語法是CREATE UNIQUE INDEX index_name ON table_name (column_name);
  3. 主鍵索引(PRIMARY KEY)

    • 主鍵索引是一種特殊的唯一索引,它要求列的值不能為空且唯一。一個表只能有一個主鍵,它用於唯一標識表中的每一行記錄。例如在訂單表中,訂單編號通常作為主鍵索引,因為每個訂單編號唯一且不能為空。在創建表時可以直接指定主鍵,如CREATE TABLE orders (order_id INT PRIMARY KEY,...);
  4. 組合索引(INDEX)

    • 組合索引是基於多個列創建的索引。例如,在一個員工表中,經常需要根據部門和職位來查詢員工信息,就可以創建一個包含部門和職位兩個列的組合索引。語法為CREATE INDEX index_name ON table_name (column1, column2);。在使用組合索引時,要注意遵循最左前綴原則,即查詢條件中必須包含組合索引的最左邊的列,才能有效利用組合索引。

二、聚簇與非聚簇的區別

  1. 聚簇索引(Clustered Index)

    • 數據存儲方式:在聚簇索引中,數據行的物理存儲順序與索引的順序相同。也就是説,索引葉子節點直接包含了數據行。例如在InnoDB存儲引擎中,主鍵索引就是聚簇索引。如果主鍵是一個自增的整數,那麼數據會按照主鍵值的大小順序物理存儲在磁盤上。
    • 查詢性能優勢:對於基於主鍵的範圍查詢非常高效。因為數據在物理上是按照主鍵順序存儲的,當進行範圍查詢(如WHERE primary_key BETWEEN value1 AND value2)時,磁盤I/O相對連續,減少了隨機I/O的次數,從而提高了查詢效率。
  2. 非聚簇索引(Non - Clustered Index)

    • 數據存儲方式:非聚簇索引的索引結構和數據存儲是分離的。索引葉子節點存儲的是指向數據行的指針(在不同存儲引擎中指針的形式可能不同)。例如在MyISAM存儲引擎中,索引和數據是分開存儲的,索引葉子節點存儲的是數據行在數據文件中的地址。
    • 查詢性能特點:非聚簇索引在進行查詢時,首先要通過索引找到數據行的指針,然後再根據指針去獲取數據行。對於頻繁修改數據的表,如果使用非聚簇索引,更新索引的成本相對較低,因為索引和數據是分開存儲的,修改數據時不需要大量地調整索引結構。

三、在InnoDB與MyISAM中支持聚簇與非聚簇情況及形式

  1. InnoDB

    • 支持情況:InnoDB支持聚簇索引。它默認會以主鍵作為聚簇索引,如果沒有定義主鍵,InnoDB會選擇一個唯一非空索引作為聚簇索引,如果沒有這樣的索引,InnoDB會隱式定義一個6字節的ROWID作為聚簇索引。
    • 形式特點:數據行存儲在聚簇索引的葉子節點。非聚簇索引的葉子節點存儲的是主鍵值,當通過非聚簇索引查詢數據時,需要先通過非聚簇索引找到主鍵值,再通過主鍵值在聚簇索引中找到數據行,這就是所謂的“回表”操作。
  2. MyISAM

    • 支持情況:MyISAM不支持聚簇索引,它只支持非聚簇索引。
    • 形式特點:數據和索引是分開存儲的。索引葉子節點存儲的是數據行在數據文件中的地址。當進行查詢時,通過索引找到數據行的地址,再去數據文件中獲取數據行。

四、索引失效場景

  1. 使用函數或表達式對索引列進行操作

    • 例如,在一個存儲用户年齡的列上有索引,但是查詢語句是SELECT * FROM users WHERE YEAR(birth_date) = 1990;(假設birth_date列有索引),這種情況下索引會失效。因為數據庫在執行查詢時,需要對每一行數據的birth_date列應用YEAR函數,而不是直接使用索引來匹配。
  2. 隱式類型轉換

    • 如果索引列是整數類型,而查詢條件中傳入的是字符串類型,數據庫會進行隱式類型轉換。例如,索引列user_idINT類型,查詢語句是SELECT * FROM users WHERE user_id = '123';,這種情況下可能會導致索引失效。
  3. 在索引列上進行計算

    • 比如在一個價格列有索引,查詢語句是SELECT * FROM products WHERE price* 0.8 < 100;,對索引列price進行了乘法計算,這會導致索引失效。
  4. 使用OR連接條件,其中部分條件沒有索引

    • 假設在user_nameuser_email列上有索引,查詢語句是SELECT * FROM users WHERE user_name = 'John' OR user_age = 30;(假設user_age列沒有索引),這種情況下索引可能會失效。不過在一些數據庫版本中,對於這種情況會有優化,但還是要儘量避免這種寫法。
  5. LIKE操作以通配符開頭

    • 如果查詢語句是SELECT * FROM products WHERE product_name LIKE '%phone';,索引會失效。因為數據庫需要對每一行數據進行匹配,無法直接利用索引。但是如果是SELECT * FROM products WHERE product_name LIKE 'phone%';,索引是可以使用的。

五、哪些查詢操作會導致回表

  1. 非聚簇索引查詢非索引列數據

    • 當通過非聚簇索引查詢數據時,如果查詢的列不在非聚簇索引中,就需要回表。例如在InnoDB存儲引擎中,有一個用户表,在用户姓名列上有非聚簇索引,查詢語句是SELECT user_id, user_age, user_name FROM users WHERE user_name = 'John';,如果只在姓名列上有非聚簇索引,查詢user_iduser_age列時就需要通過姓名列的非聚簇索引找到主鍵值,再通過主鍵值在聚簇索引(數據行存儲位置)中獲取user_iduser_age列的數據,這就是回表操作。
  2. 組合索引部分使用不符合最左前綴原則後的查詢

    • 假設有一個組合索引(column1column2column3),查詢語句是SELECT * FROM table_name WHERE column2 = value2 AND column3 = value3;,由於沒有從組合索引的最左邊列(column1)開始查詢,數據庫可能會先通過索引找到部分匹配的行,然後再回表去檢查這些行是否滿足column2 = value2 AND column3 = value3的條件。

六、explain調優中的一些關鍵字段以及含義

  1. id

    • 含義:表示查詢中每個SELECT子句的唯一標識符。如果是一個簡單的查詢,只有一個SELECT語句,id通常為1。如果是複雜的查詢,包含子查詢或聯合查詢,id可以用來區分不同的SELECT語句。id的值越大,表示該SELECT語句越先執行。
    • 示例:在一個包含子查詢的查詢語句中,如SELECT * FROM table1 WHERE column1 IN (SELECT column2 FROM table2);,子查詢的id可能為2,外層查詢的id為1。
  2. select_type

    • 含義:表示查詢的類型。常見的類型有SIMPLE(簡單查詢,不包含子查詢或聯合查詢)、SUBQUERY(子查詢)、DERIVED(派生表查詢,在FROM子句中使用子查詢的情況)等。
    • 示例:對於查詢SELECT * FROM (SELECT column1 FROM table1) AS derived_table;select_type對於外層查詢是DERIVED,對於內層子查詢是SIMPLE
  3. type

    • 含義:表示MySQL在表中找到所需行的方式,從好到差依次為system(表只有一行記錄,是const類型的特例)、const(通過索引一次就找到了,用於主鍵或唯一索引查詢)、eq_ref(對於每個索引鍵,表中只有一條記錄與之匹配)、ref(使用非唯一索引進行查詢,返回匹配某個單獨值的所有行)、range(只檢索給定範圍的行,如使用BETWEENIN等操作)、index(全索引掃描)、ALL(全表掃描)。
    • 示例:如果查詢SELECT * FROM users WHERE user_id = 1;(假設user_id是主鍵),type可能是const;如果是SELECT * FROM products WHERE price BETWEEN 10 AND 20;type可能是range
  4. possible_keys

    • 含義:表示查詢可能使用的索引。這些索引是根據查詢條件和表結構分析出來的。
    • 示例:在一個包含多個列索引的表中,如CREATE TABLE table_name (column1 INT, column2 VARCHAR(100), INDEX(column1, column2));,對於查詢SELECT * FROM table_name WHERE column1 = 1 AND column2 = 'value';possible_keys可能包含剛才創建的組合索引。
  5. key

    • 含義:表示MySQL實際使用的索引。如果keyNULL,表示沒有使用索引,可能是因為沒有合適的索引或者索引失效等原因。
    • 示例:在上面的例子中,如果MySQL確定使用了組合索引來執行查詢,key的值就是創建的組合索引的名稱。
  6. key_len

    • 含義:表示MySQL使用的索引的長度。這個長度可以用來判斷索引的使用情況,特別是對於組合索引,可以知道實際使用了組合索引中的哪些列。
    • 示例:對於一個組合索引(column1column2),如果column1INT類型(4字節),column2VARCHAR(10)類型(假設字符集是UTF8,每個字符最多3字節,加上長度字節共31字節左右),如果查詢只用到了column1key_len可能是4字節左右;如果用到了column1column2key_len可能是35字節左右。
  7. rows

    • 含義:表示MySQL根據表統計信息和索引使用情況,估算的需要讀取的行數。這個數字越小,表示查詢可能越高效。
    • 示例:在一個有1000行數據的表中,如果是全表掃描,rows可能是1000;如果通過索引能夠快速定位到部分行,rows可能是10或者更少。
  8. Extra

    • 含義:包含一些額外的信息,用於解釋查詢的執行情況。例如Using index表示查詢只使用了索引中的信息,不需要回表;Using where表示查詢使用了WHERE條件來過濾數據;Using filesort表示需要進行文件排序,這可能會影響查詢性能。
    • 示例:對於查詢SELECT column1 FROM table_name WHERE column1 > 10 ORDER BY column1;,如果沒有合適的索引來支持排序,Extra可能會出現Using filesort

七、Redis一個值,數據庫一個值,你怎麼保證數據一致性

  1. 使用事務

    • 在應用程序中,可以將對Redis和數據庫的操作封裝在一個事務中。例如,在支持分佈式事務的環境中(如使用Seata框架),可以開啓一個全局事務。當需要更新數據時,先更新數據庫,然後在事務的同一個階段更新Redis。如果在更新數據庫或者Redis過程中出現錯誤,事務可以進行回滾,保證數據的一致性。
  2. 消息隊列

    • 可以使用消息隊列來協調Redis和數據庫的更新。當有數據更新請求時,將更新操作作為一個消息發送到消息隊列。有專門的消費者來處理這個消息,先更新數據庫,然後更新Redis。如果更新過程中出現故障,消息隊列可以保證消息不會丟失,在系統恢復後可以重新處理消息,從而保證數據一致性。
  3. 緩存更新策略 - 先更新數據庫,再刪除Redis緩存

    • 這種策略被稱為“Cache - Aside Pattern”。當數據需要更新時,先更新數據庫,然後刪除Redis中的對應緩存。下一次查詢數據時,如果Redis中沒有緩存,就會從數據庫中讀取最新的數據並更新到Redis中。這樣可以避免數據不一致的情況,因為只有在數據庫更新成功後才會去操作Redis緩存。

八、你先更新Redis或者更新數據庫的理由是什麼?

  1. 先更新數據庫的理由

    • 數據完整性:數據庫是數據的最終存儲位置,具有持久化和事務等特性。先更新數據庫可以確保數據在存儲層面首先得到更新,減少數據丟失的風險。例如在金融系統中,賬户餘額的更新必須先在數據庫中完成,這樣即使後續Redis更新出現問題,數據的最終狀態在數據庫中是正確的。
    • 適合複雜業務邏輯:對於涉及多個表關聯或者複雜的業務驗證的情況,數據庫的更新操作可以利用數據庫的事務機制和存儲過程等功能。這些功能可以保證在複雜的業務邏輯下數據的一致性。例如在電商系統的訂單處理中,需要更新訂單表、庫存表等多個表,先在數據庫中完成這些操作可以利用數據庫的事務來保證數據的完整性。
  2. 先更新Redis的理由

    • 性能優化:如果對性能要求極高,並且數據的一致性要求在一定時間內允許有小的偏差,先更新Redis可以立即返回響應給客户端。例如在一些對響應速度要求極高的讀多寫少的場景,如熱點新聞系統,先更新Redis可以讓後續的讀請求快速獲取到更新後的內容,然後再異步更新數據庫。
    • 緩存預熱:在系統啓動或者新數據加入時,先更新Redis可以提前將數據緩存起來,提高系統的初始響應速度。例如在一個推薦系統中,新的推薦內容加入後,先將其放入Redis緩存,這樣當用户請求推薦內容時,可以快速從Redis中獲取,同時後台再慢慢更新數據庫來保證數據的最終一致性。

Kafka部分

一、Kafka各部分的組成(比如生產者、消費者)

  1. 生產者(Producer)

    • 生產者是消息的產生者,負責將消息發送到Kafka集羣。它可以從各種數據源(如日誌文件、數據庫等)讀取數據,然後將數據封裝成消息發送到Kafka的主題(Topic)中。生產者在發送消息時,可以指定消息所屬的主題、分區(如果需要)等信息。例如,在一個日誌收集系統中,日誌收集器作為生產者,將收集到的日誌消息發送到Kafka的日誌主題中。
  2. 消費者(Consumer)

    • 消費者是消息的接收者,它從Kafka集羣中訂閲主題,並從主題的分區中拉取消息進行消費。消費者可以是單個應用程序,也可以是一個消費者組(Consumer Group)。消費者組內的消費者可以共同分擔對主題消息的消費任務,實現消息的負載均衡和高可用性。例如,在一個數據處理系統中,數據處理應用程序作為消費者,從Kafka的主題中獲取消息,然後進行數據清洗、分析等操作。
  3. 主題(Topic)

    • 主題是Kafka對消息進行分類的一種方式,類似於數據庫中的表。生產者將消息發送到特定的主題,消費者從特定的主題中訂閲和消費消息。一個主題可以有多個分區,用於實現數據的並行處理和存儲。例如,在一個電商系統中,可以有“訂單主題”“用户主題”等,分別用於處理訂單相關消息和用户相關消息。
  4. 分區(Partition)

    • 分區是主題的物理劃分,每個分區在存儲上是一個獨立的日誌文件。消息在分區中按照一定的順序存儲,分區的主要作用是提高Kafka的吞吐量和可擴展性。通過將主題劃分為多個分區,可以讓多個生產者和消費者同時對不同的分區進行操作,實現並行處理。例如,一個主題有3個分區,生產者可以同時向這3個分區發送消息,消費者也可以從這3個分區中同時拉取消息。
  5. Broker

    • Broker是Kafka集羣中的服務器節點,它負責存儲和轉發消息。一個Kafka集羣可以有多個Broker,每個Broker可以存儲多個主題的分區。當生產者發送消息時,消息會被髮送到一個或多個Broker上;當消費者請求消息時,也是從Broker上獲取消息。Broker之間可以相互通信,實現數據的複製和負載均衡等功能。例如,在一個有5個Broker的Kafka集羣中,主題的分區可以分佈在不同的Broker上,以提高集羣的可靠性和性能。

二、為什麼有分區的概念?分區的缺點與優點是什麼?

  1. 分區的優點

    • 提高吞吐量:通過將主題劃分為多個分區,Kafka可以同時處理多個分區的讀寫操作。多個生產者可以併發地向不同分區寫入消息,多個消費者也可以同時從不同分區讀取消息,從而大大提高了整個系統的消息處理吞吐量。例如,在一個大數據日誌收集系統中,有大量的日誌消息需要處理,將日誌主題劃分為多個分區後,可以讓多個日誌收集器(生產者)同時向不同分區發送消息,同時多個日誌處理程序(消費者)也能同時從不同分區獲取消息進行處理。
    • 實現負載均衡:分區可以在消費者組內實現負載均衡。消費者組中的每個消費者可以分配到一個或多個分區進行消費,這樣可以根據消費者的處理能力合理分配分區,避免某個消費者負載過重。例如,在一個有3個消費者的消費者組和一個包含6個分區的主題的情況下,每個消費者可以平均分配到2個分區進行消費,從而平衡了消費者之間的負載。
    • 存儲擴展性:分區在存儲上是獨立的日誌文件,這使得Kafka的存儲可以方便地進行擴展。當數據量不斷增加時,可以通過增加分區數量或者增加Broker數量來存儲更多的消息。例如,隨着業務的增長,日誌數據量越來越大,通過增加日誌主題的分區數量,可以將更多的日誌消息存儲在Kafka集羣中。
  2. 分區的缺點

    • 順序性問題:分區之間是無序的,這對於一些對消息順序有嚴格要求的應用場景會帶來挑戰。如果業務需要嚴格保證消息的全局順序,需要額外的處理來協調不同分區之間的順序,這增加了系統的複雜性。例如,在一個訂單處理系統中,如果訂單的創建、支付、發貨等消息分佈在不同分區,就需要採取特殊措施來保證這些消息按照正確的順序被消費。
    • 管理複雜性:分區數量的增加會導致系統管理的複雜性增加。例如,需要合理地分配分區到不同的Broker,考慮分區的備份策略,以及在分區出現故障或者進行調整時,需要進行更多的操作來維護系統的穩定性和數據的完整性。

三、分區之間是無序的,我如何保證我一個順序消費?

  1. 單分區處理

    • 如果對消息順序有嚴格要求,最直接的方法是將相關的消息都發送到同一個分區。可以通過自定義分區策略,根據消息的關鍵屬性(如業務流水號等)將相關消息都路由到同一個分區。例如,在一個金融交易系統中,對於同一筆交易的所有操作消息(如開户、存款、取款等),根據交易編號將這些消息都發送到同一個分區,然後消費者按照消息在該分區中的順序進行消費,這樣就能保證同一筆交易的消息順序。
  2. 全局有序與局部有序

    • 如果無法將所有消息都發送到同一個分區,可以考慮採用全局有序和局部有序相結合的方式。對於關鍵業務流程,保證這些流程相關的消息在局部(某個分區)內是有序的,然後在應用層通過邏輯來協調不同分區之間的順序。例如,在一個電商系統中,對於一個訂單的消息(下單、支付、發貨),可以將同一訂單的消息發送到同一個分區保證局部有序,對於不同訂單之間的消息順序,可以通過在應用程序中記錄訂單的創建時間等信息,在消費時按照時間順序或者業務優先級來協調不同訂單消息的消費順序。
  3. 使用額外的順序協調機制

    • 可以在應用程序中引入額外的順序協調機制,如分佈式鎖或者序列號管理系統。當消費者從不同分區獲取消息後,通過獲取分佈式鎖或者根據序列號來確定消息的消費順序。例如,在一個多線程消費多個分區消息的場景中,使用分佈式鎖來保證同一時間只有一個線程能夠處理關鍵順序消息,其他線程等待,從而保證消息的順序消費。

四、分區策略KEY - BASE這個KEY是業務生成還是內置生成?

  1. 業務生成

    • 在大多數情況下,分區策略中的KEY是由業務生成的。業務可以根據消息的關鍵屬性來生成KEY,這個屬性通常與業務邏輯緊密相關。例如,在一個用户行為跟蹤系統中,消息是用户的各種行為(如登錄、瀏覽商品、購買等),可以以用户ID作為KEY。這樣,對於同一個用户的所有行為消息可以根據用户ID被路由到同一個分區,方便後續對單個用户行為的分析和處理。
  2. 內置生成(較少情況)

    • 雖然較少,但在一些簡單的場景下,Kafka也可以提供內置的KEY生成方式。例如,當消息沒有明顯的業務關鍵屬性可以作為KEY,或者業務對分區沒有特殊要求時,Kafka可能會根據消息的元數據(如消息的時間戳等)生成一個默認的KEY。不過這種情況相對較少,因為這樣生成的分區可能無法很好地滿足業務的實際需求。

五、KEY的分區算法怎麼做的?

  1. 取模算法

    • 最常見的分區算法是取模算法。假設主題有n個分區,對於給定的KEY,計算hash(key) % n,其中hash(key)是對KEY進行哈希計算(如使用Java中的hashCode方法等)。通過這種方式,將KEY對應的消息分配到不同的分區。例如,一個主題有5個分區,對於用户ID作為KEY的消息,計算用户ID的哈希值後對5取模,根據結果將消息發送到對應的分區。這種算法簡單有效,但可能會導致分區負載不均衡的情況,特別是當KEY的分佈不均勻時。
  2. 一致性哈希算法

    • 一致性哈希算法是一種改進的分區算法。它將整個哈希值空間組織成一個虛擬的圓環,將分區和KEY都映射到這個圓環上。當添加或刪除分區時,只會影響到圓環上相鄰的分區,而不是像取模算法那樣可能會導致大量消息的重新分配。例如,在一個動態擴展分區的Kafka集羣中,使用一致性哈希算法可以減少分區調整對消息分佈的影響,提高系統的穩定性。
  3. 自定義分區算法

    • 根據業務需求,也可以自定義分區算法。例如,業務可能有特殊的分區要求,如根據地域、業務類型等因素來分配消息到不同分區。自定義分區算法可以在生產者代碼中實現,通過實現Partitioner接口,根據業務規則來計算KEY對應的分區。例如,在一個跨國電商系統中,根據訂單的發貨地將訂單消息分配到不同的分區,以方便不同地區的訂單處理系統進行消費。

六、消息丟失的場景有哪些?

  1. 生產者丟失消息

    • 未收到ACK確認:在異步發送消息模式下,生產者發送消息後,如果沒有收到Kafka Broker的ACK確認就認為消息發送成功,可能會導致消息丟失。例如,由於網絡故障或者Broker故障,消息沒有真正到達Broker,但生產者卻以為發送成功了。
    • 緩衝區溢出:如果生產者的消息發送緩衝區已滿,並且配置為丟棄舊消息,當新消息不斷產生時,舊消息可能會被丟棄,從而導致消息丟失。例如,在一個高併發的消息產生場景中,生產者的緩衝區設置過小,無法及時將消息發送到Kafka,就可能會出現這種情況。
  2. 消費者丟失消息

    • 自動提交偏移量:如果消費者在沒有完全處理完消息的情況下就自動提交了偏移量,當消費者出現故障或者重新啓動後,會從已經提交的偏移量位置開始消費,導致未處理的消息丟失。例如,消費者在處理消息的過程中發生了異常,但偏移量已經自動提交,下次消費時就會跳過這些未處理的消息。
    • 消費邏輯錯誤:在消費者的處理邏輯中,如果出現錯誤導致消息沒有正確處理就被認為是處理完成,也會導致消息丟失。例如,在消息處理過程中,沒有正確地將消息存儲到數據庫或者其他存儲介質中,但消費者卻更新了偏移量,認為消息已經處理完成。
  3. Broker丟失消息

    • 副本未及時同步:在Kafka中,消息是通過多個副本進行存儲來保證可靠性。如果主副本(Leader)上的消息沒有及時同步到從副本(Follower),並且主副本出現故障,在沒有完全同步的情況下,這些未同步的消息可能會丟失。例如,在網絡擁塞或者Broker負載過高的情況下,副本之間的同步延遲較大,當主副本不可用時,未同步的消息就會丟失。

七、消息丟失的對策有哪些?

  1. 生產者對策

    • 配置ACK機制:將生產者的acks參數設置為合適的值。acks = 1表示只要Leader副本收到消息就返回ACK,acks = all表示所有副本(包括Follower)都收到消息後才返回ACK。通過設置acks = all可以提高消息發送的可靠性,但會降低消息發送的效率。同時,要設置合理的重試次數和重試間隔,當沒有收到ACK時進行重試。
    • 調整緩衝區大小:根據消息產生的速度和網絡情況,合理調整生產者的消息發送緩衝區大小,避免緩衝區溢出。可以通過性能測試來確定合適的緩衝區大小,並且設置緩衝區滿時的處理策略,如阻塞生產者而不是丟棄消息。
  2. 消費者對策

    • 手動提交偏移量:消費者手動控制偏移量的提交,在消息完全處理完成後再提交偏移量。可以通過在消息處理成功後,調用commitSynccommitAsync方法來提交偏移量。這樣可以避免在消息未處理完成時就提交偏移量導致消息丟失。
    • 消息處理重試機制:在消費者的處理邏輯中,對於處理失敗的消息,設置重試機制。可以將處理失敗的消息放入重試隊列,在一定次數內進行重試,直到消息處理成功。同時,要注意處理重試過程中的消息冪等性問題,避免重複處理消息導致數據不一致。
  3. Broker對策

    • 優化副本同步策略:調整Kafka的副本同步參數,如min.insync.replicas(最小同步副本數)和replica.lag.time.max.ms(副本同步延遲最大時間)等參數。增加最小同步副本數可以提高消息存儲的可靠性,但會降低消息寫入的效率。同時,要確保Broker之間的網絡暢通,減少副本同步延遲,保證消息能夠及時同步到所有副本。

八、生產者可靠性級別?

  1. 最多一次(At - Most - Once)

    • 這種可靠性級別是指消息最多被髮送一次,可能會有消息丟失的情況。在這種模式下,生產者發送消息後,不會等待任何確認就認為消息發送成功。例如,在一些對消息丟失不太敏感的場景,如日誌收集系統中,如果丟失一些不太重要的日誌消息是可以接受的,就可以採用最多一次的可靠性級別,以提高消息發送的效率。
  2. 至少一次(At - Least - Once)

    • 生產者會保證消息至少被髮送一次。這意味着消息可能會被重複發送,需要消費者來處理消息的重複問題。在這種模式下,生產者發送消息後,會等待Broker的ACK確認,如果沒有收到確認,會進行重試。例如,在金融交易系統中,為了保證交易消息不丟失,採用至少一次的可靠性級別,消費者需要處理可能出現的重複交易消息,通過冪等性設計來保證數據的一致性。
  3. 精確一次(Exactly - Once)

    • 這是最高的可靠性級別,生產者保證消息精確地被髮送一次,消費者也精確地接收和處理一次。要實現精確一次的可靠性,需要在生產者、消費者和Kafka集羣之間進行復雜的協調。例如,通過使用事務或者冪等性生產者等機制來保證消息的精確一次發送,在消費者端也需要通過合適的偏移量管理和消息處理邏輯來保證消息的精確一次處理。在一些對數據準確性和一致性要求極高的場景,如訂單處理系統,就需要採用精確一次的可靠性級別。

歡迎關注 ❤

我們搞了一個免費的面試真題共享羣,互通有無,一起刷題進步。

沒準能讓你能刷到自己意向公司的最新面試題呢。

感興趣的朋友們可以加我微信:wangzhongyang1993,備註:sf面試羣。

user avatar segmentfault 頭像 tongbo 頭像 ahahan 頭像 nixideshatanku 頭像 idiomeo 頭像 chenbimo 頭像 dreamlu 頭像 wuxiedekeben 頭像 syntaxerror 頭像 youyudetusi 頭像 aihejiudejiqiren_bjjawt 頭像 dalidezhuantou_bpc01t 頭像
點贊 21 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.