mysql分布式安装可靠读写案列图解,高并发下的分布式锁-mysql篇
前言
不管是在面試中,還是在平時的工作中,高并發永遠是衡量一個web工作者能力的重要場景。本篇幅我們主要是來討論在高并發環境下我們應該如何實現分布式鎖。
實現分布式鎖的方式有比較多,這里主要考慮如何使用mysql實現分布式鎖。
Mysql實現鎖的方法
第一種,使用mysql唯一索引來實現:
針對這種實現,我們只需要新建一張表,專門用來處理分布式任務,比如新建一張 task的表,里面的唯一索引為 task_name 。
運行流程如下:當多個副本同時要搶占一個任務的鎖的時候,就執行一個插入語句(這幾個副本的task_name都是一致的),所以,當有一個副本之行插入成功后,后續的其他插入則會由于唯一索引的問題,導致插入失敗。我們可以根據插入的影響條數為0 或者是1 ,判斷是否搶鎖成功。最后搶鎖成功的副本,在任務執行結束之后,將該條記錄刪除,即把鎖刪除掉。
CREATE TABLE `tests`.`task` (
`task-name` varchar(255) NULL,
`id` int(0) NOT NULL AUTO_INCREMENT,
`ctime` timestamp(0) NULL,
`mtime` timestamp(0) NULL ON UPDATE CURRENT_TIMESTAMP(0),
PRIMARY KEY (`id`),
INDEX `uniq_idx_task_name`(`task-name`)
);
// 副本1執行:
INSERT INTO `tests`.`task`(`task-name`, `ctime`, `mtime`) VALUES ('demo1', 1, NULL, NULL);
// 副本2同時執行
INSERT INTO `tests`.`task`(`task-name`, `ctime`, `mtime`) VALUES ('demo1', 1, NULL, NULL);
// 以上只會有一個副本執行成功,另一個副本會直接失敗
第二種,使用mysql的悲觀鎖
for update 和 for udpate no wait :
使用的前提:基于Innodb,并且在支持事務的情況下可以使用
當某用戶執行了 for update 之后,該用戶可以在提交或者放棄事務之前,對該事務進行查詢和更新,其他用戶只能查詢但不能更新被加鎖的數據行。
** select XXXX for update 在執行過程中可能會鎖行,也可能會鎖表 。 **
當查詢中帶有主鍵的時候,會鎖行;
當明確帶有(即是使用的不包括模糊查詢之類的)主鍵,但是查詢沒有結果的,不會導致鎖表;
當查詢中無主鍵或者使用了like之類需要全表掃描的,會導致鎖住整個表;(即使查詢中沒有任何數據的時候也會導致鎖表)
另外,select XX for update nowait 與 只有 for update 的區別是for update ,當另一個連接嘗試獲取到鎖的時候,會阻塞在那里等待;如果加了 nowait 的話,當獲取不到鎖的時候會直接報錯。
// 為了方便這里借用上上面的task表
// 起一個終端,連接上數據庫,然后執行以下:
set autocommit = 0;
select * from task for update;
// 等待一段時間后再執行;
commit;
此時,另一個終端執行,可以發現,執行 select的話,可以直接返回,但是update的話會產生阻塞,直到之前的事務commit(看執行時間就可以知道)
image.png
// 如果使用for update nowait;
// 副本1執行成功:
select * from task for update nowait;
// 副本2執行:
mysql> select * from task for update nowait;
ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set
//值得注意的是,for update nowait 的話,如果你執行 update 操作的話,仍然會阻塞在那里。
第三種,使用樂觀鎖
(區分下第一種,第一種是針對單點定時任務的,這里延伸下成加鎖)
使用樂觀鎖的話,可以給表中加一個 version 字段,用于表示該行記錄的版本(如果你想要用 timestamp來做也可以,可以直接使用mysql的字段,那樣你就不用考慮該值的更新)
因此,每次更新的流程是,先 select 獲取到一個version(比如是3) 然后再進行 update ,查詢中在原來的基礎上多加一個 and version = 3, 如果在select 和 update 之間有個第三方操作了數據庫并且操作成功了,此刻version變成了4,那么你進行這次update的時候 update XXX where XXX and version = 3的時候,更新就會失敗,那么就不會影響。
結語
以上就是mysql鎖的三種方式,不過說實話,mysql的性能確實在高并發環境下,不值得期待,但是多了解下這種知識,也算是擴寬下自己的解決問題的思路吧。
共勉
總結
以上是生活随笔為你收集整理的mysql分布式安装可靠读写案列图解,高并发下的分布式锁-mysql篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab高级图形设计实训上机答案,M
- 下一篇: es ik分词热更新MySQL,Elas