您好,登錄后才能下訂單哦!
Java 原生 API 雖然有并發鎖,但并沒有提供分布式鎖的能力,所以針對分布式場景中的鎖需要解決的方案。
分布式鎖的解決方案大致有以下幾種:
1. 創建表
CREATE TABLE `methodLock` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵', `method_name` varchar(64) NOT NULL DEFAULT '' COMMENT '鎖定的方法名', `desc` varchar(1024) NOT NULL DEFAULT '備注信息', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '保存數據時間,自動生成', PRIMARY KEY (`id`), UNIQUE KEY `uidx_method_name` (`method_name `) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='鎖定中的方法';
2. 獲取鎖
想要鎖住某個方法時,執行以下 SQL:
insert into methodLock(method_name,desc) values (‘method_name’,‘desc’)
因為我們對
method_name
做了唯一性約束,這里如果有多個請求同時提交到數據庫的話,數據庫會保證只有一個操作可以成功,那么我們就可以認為操作成功的那個線程獲得了該方法的鎖,可以執行方法體內容。
成功插入則獲取鎖。
3. 釋放鎖
當方法執行完畢之后,想要釋放鎖的話,需要執行以下 Sql:
delete from methodLock where method_name ='method_name'
相比于用數據庫來實現分布式鎖,基于緩存實現的分布式鎖的性能會更好一些。目前有很多成熟的分布式產品,包括 Redis、memcache、Tair 等。這里以 Redis 舉例。
單點實現步驟:
可以考慮使用 redisson 的解決方案。
這也是 ZooKeeper 客戶端 curator 的分布式鎖實現。
ZooKeeper 版本的分布式鎖問題相對比較來說少。
總體上來說 ZooKeeper 實現分布式鎖更加的簡單,可靠性更高。但 ZooKeeper 因為需要頻繁的創建和刪除節點,性能上不如 Redis 方式。
在分布式場景下,一個用戶的 Session 如果只存儲在一個服務器上,那么當負載均衡器把用戶的下一個請求轉發到另一個服務器上,該服務器沒有用戶的 Session,就可能導致用戶需要重新進行登錄等操作。
分布式 Session 的幾種實現策略:
需要配置負載均衡器,使得一個用戶的所有請求都路由到一個服務器節點上,這樣就可以把用戶的 Session 存放在該服務器節點中。
缺點:當服務器節點宕機時,將丟失該服務器節點上的所有 Session。
在服務器節點之間進行 Session 同步操作,這樣的話用戶可以訪問任何一個服務器節點。
缺點:占用過多內存;同步過程占用網絡帶寬以及服務器處理器時間。
使用一個單獨的服務器存儲 Session 數據,可以存在 MySQL 數據庫上,也可以存在 Redis 或者 Memcached 這種內存型數據庫。
缺點:需要去實現存取 Session 的代碼。
通常有兩種解決方案:
使用緩存的好處:
根據業務場景,通常緩存有以下幾種使用方式
緩存分類:
輪詢算法把每個請求輪流發送到每個服務器上。下圖中,一共有 6 個客戶端產生了 6 個請求,這 6 個請求按 (1, 2, 3, 4, 5, 6) 的順序發送。最后,(1, 3, 5) 的請求會被發送到服務器 1,(2, 4, 6) 的請求會被發送到服務器 2。
該算法比較適合每個服務器的性能差不多的場景,如果有性能存在差異的情況下,那么性能較差的服務器可能無法承擔過大的負載(下圖的 Server 2)。
加權輪詢是在輪詢的基礎上,根據服務器的性能差異,為服務器賦予一定的權值。例如下圖中,服務器 1 被賦予的權值為 5,服務器 2 被賦予的權值為 1,那么 (1, 2, 3, 4, 5) 請求會被發送到服務器 1,(6) 請求會被發送到服務器 2。
由于每個請求的連接時間不一樣,使用輪詢或者加權輪詢算法的話,可能會讓一臺服務器當前連接數過大,而另一臺服務器的連接過小,造成負載不均衡。例如下圖中,(1, 3, 5) 請求會被發送到服務器 1,但是 (1, 3) 很快就斷開連接,此時只有 (5) 請求連接服務器 1;(2, 4, 6) 請求被發送到服務器 2,只有 (2) 的連接斷開。該系統繼續運行時,服務器 2 會承擔過大的負載。
最少連接算法就是將請求發送給當前最少連接數的服務器上。例如下圖中,服務器 1 當前連接數最小,那么新到來的請求 6 就會被發送到服務器 1 上。
在最少連接的基礎上,根據服務器的性能為每臺服務器分配權重,再根據權重計算出每臺服務器能處理的連接數。
把請求隨機發送到服務器上。和輪詢算法類似,該算法比較適合服務器性能差不多的場景。
源地址哈希通過對客戶端 IP 哈希計算得到的一個數值,用該數值對服務器數量進行取模運算,取模結果便是目標服務器的序號。
HTTP 重定向負載均衡服務器收到 HTTP 請求之后會返回服務器的地址,并將該地址寫入 HTTP 重定向響應中返回給瀏覽器,瀏覽器收到后需要再次發送請求。
缺點:
使用 DNS 作為負載均衡器,根據負載情況返回不同服務器的 IP 地址。大型網站基本使用了這種方式做為第一級負載均衡手段,然后在內部使用其它方式做第二級負載均衡。
缺點:
使用 LVS(Linux Virtual Server)這種鏈路層負載均衡器,根據負載情況修改請求的 MAC 地址。
在網絡層修改請求的目的 IP 地址。
正向代理與反向代理的區別:
PAC 服務器是用來判斷一個請求是否要經過代理。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。