為了賬號安全,請及時綁定郵箱和手機立即綁定

慕課網秒殺課程有感——該補充一下數據高并發下的安全和一致性的知識

2016.08.09 13:30 9596瀏覽

突然發現慕課網有秒殺課程,簡單的看了一下DAO層,基本都在整合ssm框架,教教新人是可以的,但是這里需要補充的是使用秒殺需要考慮性能和數據安全性一致性的問題,所以這里我會分析三種在保證數據安全一致性前提下的算法。
秒殺最困難的除了是性能問題,還有另外一個就是高并發下的數據安全和一致性的問題。比如搶紅包,線程1,2,3,極有可能剛開始都可以讀到余額為100元,但是扣減的時候也是有先后順序的,這些會引起數據并發安全和一致性的問題,這里互聯網高并發的核心問題,也是秒殺的核心問題,所以這里我有必要對這些知識進行一定的補充和描述。
1、悲觀鎖
講課老師談到的用數據庫行鎖:
select * from t_table where id =xx for update;
直至其提交,解鎖for update。對的這樣可以解決線程數據安全性的問題,然而這種在企業中基本不會用得到?為什么?因為這個是一個獨占鎖,當加入行鎖后,所有的線程都需要等待持鎖的線程。而秒殺是什么概念?一個時刻幾千個請求,也就是說如果用這樣的一個鎖,那么就是幾千個線程等待你一個線程,需要掛起,切換線程環境。這是一個多大的代價??所以很快這樣的方法被企業排除了。

2、樂觀鎖
對于我們而言,使用數據庫,我們更喜歡這么幾個步驟:
1、我們使用無鎖機制讀取數據:
select * from t_table where id =xx;
現在我們表里面加入一個version字段,一開始我們讀入這個version,假設我們讀取到3,
2、操作邏輯完成,更新的時候使用:
update t_table somefiled = xxx, version = version + 1
where id= xx and version = 3;
這里如果version還是等于3則代表沒有更其他線程更新過。
3、如果為上面update語句影響記錄為1,則更新成功,繼續插入秒殺業務數據;如果更新數為0,那么我們循環在從1到3步驟,直至這步返回為1。
這樣的好處在于我們不需要使用獨占鎖,不需要一個時刻多個線程去等待一個線程,而到最后的更新,我會去判斷新舊值是否被其他線程更新過(這里主要判斷version字段),如果被其他線程更新過就不做更新,繼續循環步驟直至成功;如果沒有則可以成功處理,這就是樂觀鎖。樂觀鎖可能會引起ABA問題,這個問題讀者可以自行度娘。

3、使用Redis
使用redis秒殺是我們目前最流行的方式,首先redis是一種nosql工具,數據和操作在內存上,速度快;而數據庫是磁盤,速度慢,所以redis的運行速度是數據庫的幾十到上百倍。
1、當請求達到,開啟Redis事務先watch Redis的某一個key,比如產品的總數量。
2、開始根用戶扣購買減產品數量。
3、保存用戶購買產品信息到redis的列表
4、提交Redis事務,如果成功修改數據,則繼續,如果失敗則重復第1步,直至成功。
5、檢測產品是否賣完?如果賣完,則將用戶購買信息,批量存入數據庫。完成持久化,否則什么都不做,等待下相應下一次的請求。
其實這也是一種變相的樂觀鎖。
這里我們在和用戶交互的過程中主要用到了redis工具,它是內存上的,讀寫的速度是數據庫的幾十倍到上百倍,所以企業更喜歡使用它進行秒殺業務。等產品賣光,或者我們搶紅包的紅包金額為0,我們就會觸發將業務數據批量刷入數據庫完成持久化的工作,而可以看到整個秒殺的過程基本在Redis完成,而數據庫的持久化只是一次性的批量問題。

這就是目前處理高并發數據一致性的三種,最常用的方式,目前最快,最流行的當然是Redis秒殺,它在保證數據安全和一致性的情況下,大大提高的互聯網秒殺的性能。

點擊查看更多內容

本文原創發布于慕課網 ,轉載請注明出處,謝謝合作

60人點贊

若覺得本文不錯,就分享一下吧!

評論

相關文章推薦

正在加載中
意見反饋 幫助中心 APP下載
官方微信

舉報

0/150
提交
取消
lpl竞猜