**
就是說特別樂觀,比如說每次去吃飯的時候,都認為視窗沒有人,只有到了吃飯的視窗才看有沒有人,如果有人則去別的地方吃飯。就像系統認為資料的更新在大多數情況下是不會產生衝突的, 只在資料庫更新操作的提交的時候才對資料作衝突檢測。如果檢測的結果出現了與預期資料不一致的情況,則返回失敗的資訊。
樂觀鎖在大多數是基於資料版本(version)的記錄機制實現的。
為了更好的理解資料庫樂觀鎖在實際專案中的使用,下面舉乙個典型的電商庫存的例子。當使用者進行購買的時候就會對庫存進行操作(庫存減1代表已經賣出了一件)。我們將這個庫存模型用下面的一張表optimistic_lock來表述,參考如下:
create table `optimistic_lock` (
`id` bigint(20
) not null auto_increment,
`resource` int(11
) not null comment '鎖定的資源'
, `version` int(11
) not null comment '版本資訊'
, `created_time` datetime default null comment '建立時間'
, `updated_time` datetime default null comment '更新時間'
, `deleted_time` datetime default null comment '刪除時間'
, primary key (`id`)
, unique key `uiq_idx_resource` (`resource`)
) engine=innodb auto_increment=
2 default charset=utf8mb4 comment=
'資料庫分布式鎖表'
;
其中:id表示主鍵;resource表示具體操作的資源,在這裡也就是特指庫存;version表示版本號。
在使用樂觀鎖之前要確保表中有相應的資料,比如:
insert into `database1`.`optimistic_lock`(`id`, `resource`, `version`, `created_time`, `updated_time`, `deleted_time`) values (1,
100,1,
'2020-04-10 22:05:52'
,'2020-04-10 22:05:52'
,'2020-04-10 22:05:52'
);
如果是單執行緒進行操作,資料庫本身就能保證操作的正確性。主要步驟如下:
然而大多數情況下是不會單執行緒的,要是單執行緒的話 ,公司豈不是要涼涼。比如兩個以上的執行緒購買同一件商品,在資料庫層實際操作的時候應該是庫存(resource)減2,但是由於是高併發的情況,第乙個執行緒執行之後(執行了step1、step2但是還沒有完成step3),第二個執行緒在購買相同的商品(執行step1),此時查詢出的庫存並沒有完成減1的動作,那麼最終會導致2個執行緒購買的商品卻出現庫存只減1的情況。
在引入了version欄位之後,那麼具體的操作就會演變成下面的內容:
redis分布式鎖 樂觀鎖實現
基於參考文章自己敲了一遍,基本一樣。利用springboot搭建環境,基於redis實現樂觀鎖秒殺 配置檔案 redis spring.redis.host 127.0.0.1 spring.redis.port 6379 spring.redis.timeout 10000配置類 componen...
Redis分布式鎖 樂觀鎖的實現
樂觀鎖 大多數是基於資料版本 version 的記錄機制實現的。即為資料增加乙個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加乙個 version 欄位來實現讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加1。此時,將提交資料的版本號與資料庫表對應記錄的當前版本號進行比...
分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...