行鎖死鎖的兩種場景和解決策略_redis的watch機制和setnx機制_實現分佈式鎖的三種實現_kafka和rabbitmq的區別_詳解java NIO之Channel(通道)

行鎖死鎖的兩種場景和解決策略

死鎖的第一種場景:獲取同一個記錄產生死鎖

由於在行鎖中,鎖是逐步得到的,主要分爲兩步:鎖住主鍵索引,鎖住非主鍵索引。如:當兩個事務同時執行時,一個鎖住了主鍵索引,在等待其餘索引;另外一個鎖住了非主鍵索引,在等待主鍵索引。這樣便會發生死鎖。InnoDB通常均可以檢測到這種死鎖,並使一個事務釋放鎖回退,另外一個獲取鎖完成事務。

5死鎖、死鎖檢測

當併發系統中不同線程出現循環資源依賴,涉及的線程都在等待別的線程釋放資源時,就會導致這幾個線程進入無限等待的狀態,稱爲死鎖

 

 

這時候,事務 A 在等待事務 B 釋放 id=2 的行鎖,而事務 B 在等待事務 A 釋放 id=1 的行鎖。事務 A 和事務 B 都在互相等待對方的資源釋放,這就進入了死鎖的狀態。當出現死鎖以後,有兩種策略:

  • 一種策略是,直接進入等待,直到超時。這個超時時間可以通過參數innodb_lock_wait_timeout
    來設置。
  • 第二種策略是,發起死鎖檢測,檢測到死鎖後,主動回滾死鎖鏈條中的某個事物,讓其他事物得以繼續執行。將參數innodb_deadlock_delect
    設置爲 on
    ,表示開啓這個邏輯。

在 innodb 中,innodb_lock_wait_timeout 的默認值是 50s,意味着如果採用第一個策略,當出現死鎖以後,第一個被鎖住的線程要過 50s 纔會超時退出,然後其他線程纔有可能繼續執行。對於一個在線服務來說,這個等待時間往往是無法接受的。

但如果把這個時間設置成一個很小的值,又會有誤傷。

所以正常情況下一般採用第二種策略 -- 主動死鎖檢測,而且 innodb_deadlock_detect
默認 on
。主動檢測發生死鎖時,是能夠快速發現並進行處理的,但它也有額外負擔。

按照上面第二種的話,每當一個事務被鎖的時候,就要看看它所依賴的線程有沒有被別人鎖住,如此循環,最後判斷是否出現了循環等待 -- 死鎖。

那麼每個新來的被堵住的線程,都要判斷會不會由於自己的加入導致了死鎖,這是一個時間複雜度是 O(n)的操作。

假設有 1000 個併發線程要同時更新同一行,那麼死鎖檢測操作就是 100 萬這個量級的。雖然最終檢測的結果是沒有死鎖,但是期間要消耗大量的 CPU 資源。因此,就會看到 CPU 利用率很高,但是每秒卻執行不了幾個事務。

這種熱點行更新導致的性能問題癥結在於,死鎖檢測要耗費大量的 CPU 資源,解決策略有以下幾種:

    1. 降低併發度
    2. 拆行,一行拆多行
    3. Server 層限流,即同一時間進入更新的線程數
    4. 關閉死鎖監測(關閉的弊端是可能超時較多)

 

 

 

 實現分佈式鎖的三種實現

 

 

 

 

 

 kafka和rabbitmq的區別

(1)開發語言不同

  1、RabbitMQ是高併發的erlanng語言開發。

  2、kafka是基於Scala和Java語言開發,主要用於處理活躍的流式數據,大數據量的數據處理上。

(2)結構不同

  1、RabbitMQ採用AMQP(Advanced Message Queuing Protocol,高級消息隊列協議)是一個進程間傳遞異步消息的網絡協議。RabbitMQ的broker由Exchange,Binding,queue組成

  2、kafka採用mq結構:broker 有part 分區的概念

(3)Brokerr與Consume交互方式不同

  1、RabbitMQ 採用push的方式

  2、kafka採用pull的方式

(4)集羣負載均衡的區別

  1、rabbitMQ的負載均衡需要單獨的loadbalancer進行支持。

  2、kafka採用zookeeper對集羣中的broker、consumer進行管理

(5)使用場景不同

  1、rabbitMQ支持對消息的可靠的傳遞,支持事務,不支持批量的操作;基於存儲的可靠性的要求存儲可以採用內存或者硬盤。

  2、kafka具有高的吞吐量,內部採用消息的批量處理,zero-copy機制,數據的存儲和獲取是本地磁盤順序批量操作

 

 

 (6條消息) 詳解java NIO之Channel(通道)_平凡的java夢的博客-CSDN博客_java 的channel

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章