十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
想要知道如何處理數(shù)據(jù)并發(fā),自然需要先了解數(shù)據(jù)并發(fā)。
成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供衡東網(wǎng)站建設(shè)、衡東做網(wǎng)站、衡東網(wǎng)站設(shè)計、衡東網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、衡東企業(yè)網(wǎng)站模板建站服務(wù),十余年衡東做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
什么是數(shù)據(jù)并發(fā)操作呢?
就是同一時間內(nèi),不同的線程同時對一條數(shù)據(jù)進行讀寫操作。
在互聯(lián)網(wǎng)時代,一個系統(tǒng)常常有很多人在使用,因此就可能出現(xiàn)高并發(fā)的現(xiàn)象,也就是不同的用戶同時對一條數(shù)據(jù)進行操作,如果沒有有效的處理,自然就會出現(xiàn)數(shù)據(jù)的異常。而最常見的一種數(shù)據(jù)并發(fā)的場景就是電商中的秒殺,成千上萬個用戶對在極端的時間內(nèi),搶購一個商品。針對這種場景,商品的庫存就是一個需要控制的數(shù)據(jù),而多個用戶對在同一時間對庫存進行重寫,一個不小心就可能出現(xiàn)超賣的情況。
針對這種情況,我們?nèi)绾斡行У奶幚頂?shù)據(jù)并發(fā)呢?
第一種方案、數(shù)據(jù)庫鎖
從鎖的基本屬性來說,可以分為兩種:一種是共享鎖(S),一種是排它鎖(X)。在MySQL的數(shù)據(jù)庫中,是有四種隔離級別的,會在讀寫的時候,自動的使用這兩種鎖,防止數(shù)據(jù)出現(xiàn)混亂。
這四種隔離級別分別是:
讀未提交(Read Uncommitted)
讀提交(Read Committed)
可重復(fù)讀(Repeated Read)
串行化(Serializable)
當(dāng)然,不同的隔離級別,效率也是不同的,對于數(shù)據(jù)的一致性保證也就有不同的結(jié)果。而這些可能出現(xiàn)的又有哪些呢?
臟讀(dirty read)
當(dāng)事務(wù)與事務(wù)之間沒有任何隔離的時候,就可能會出現(xiàn)臟讀。例如:商家想看看所有的訂單有哪些,這時,用戶A提交了一個訂單,但事務(wù)還沒提交,商家卻看到了這個訂單。而這時就會出現(xiàn)一種問題,當(dāng)商家去操作這個訂單時,可能用戶A的訂單由于部分問題,導(dǎo)致數(shù)據(jù)回滾,事務(wù)沒有提交,這時商家的操作就會失去目標(biāo)。
不可重復(fù)讀(unrepeatable read)
一個事務(wù)中,兩次讀操作出來的同一條數(shù)據(jù)值不同,就是不可重復(fù)讀。
例如:我們有一個事務(wù)A,需要去查詢一下商品庫存,然后做扣減,這時,事務(wù)B操作了這個商品,扣減了一部分庫存,當(dāng)事務(wù)A再次去查詢商品庫存的時候,發(fā)現(xiàn)這一次的結(jié)果和上次不同了,這就是不可重復(fù)讀。
幻讀(phantom problem)
一個事務(wù)中,兩次讀操作出來的結(jié)果集不同,就是幻讀。
例如:一個事務(wù)A,去查詢現(xiàn)在已經(jīng)支付的訂單有哪些,得到了一個結(jié)果集。這時,事務(wù)B新提交了一個訂單,當(dāng)事務(wù)A再次去查詢時,就會出現(xiàn),兩次得到的結(jié)果集不同的情況,也就是幻讀了。
那針對這些結(jié)果,不同的隔離級別可以干什么呢?
“讀未提(Read Uncommitted)”能預(yù)防啥?啥都預(yù)防不了。
“讀提交(Read Committed)”能預(yù)防啥?使用“快照讀(Snapshot Read)”方式,避免“臟讀”,但是可能出現(xiàn)“不可重復(fù)讀”和“幻讀”。
“可重復(fù)讀(Repeated Red)”能預(yù)防啥?使用“快照讀(Snapshot Read)”方式,鎖住被讀取記錄,避免出現(xiàn)“臟讀”、“不可重復(fù)讀”,但是可能出現(xiàn)“幻讀”。
“串行化(Serializable)”能預(yù)防啥?有效避免“臟讀”、“不可重復(fù)讀”、“幻讀”,不過運行效率奇差。
好了,鎖說完了,但是,我們的數(shù)據(jù)庫鎖,并不能有效的解決并發(fā)的問題,只是盡可能保證數(shù)據(jù)的一致性,當(dāng)并發(fā)量特別大時,數(shù)據(jù)庫還是容易扛不住。那解決數(shù)據(jù)并發(fā)的另一個手段就是,盡可能的提高處理的速度。
因為數(shù)據(jù)的IO要提升難度比較大,那么通過其他的方式,對數(shù)據(jù)進行處理,減少數(shù)據(jù)庫的IO,就是提高并發(fā)能力的有效手段了。
最有效的一種方式就是:緩存
想要減少并發(fā)出現(xiàn)的概率,那么讀寫的效率越高,讀寫的執(zhí)行時間越短,自然數(shù)據(jù)并發(fā)的可能性就變小了,并發(fā)性能也有提高了。
還是用剛才的秒殺舉例,我們?yōu)榈木褪潜WC庫存的數(shù)據(jù)不出錯,賣出一個商品,減一個庫存,那么,我們就可以將庫存放在內(nèi)存中進行處理。這樣,就能夠保證庫存有序的及時扣減,并且不出現(xiàn)問題。這樣,我們的數(shù)據(jù)庫的寫操作也變少了,執(zhí)行效率也就大大提高了。
當(dāng)然,常用的分布式緩存方式有:Redis和Memcache,Redis可以持久化到硬盤,而Memcache不行,應(yīng)該怎么選擇,就看具體的使用場景了。
當(dāng)然,緩存畢竟使用的范圍有限,很多的數(shù)據(jù)我們還是必須持久化到硬盤中,那我們就需要提高數(shù)據(jù)庫的IO能力,這樣避免一個線程執(zhí)行時間太長,造成線程的阻塞。
那么,讀寫分離就是另一種有效的方式了
當(dāng)我們的寫成為了瓶頸的時候,讀寫分離就是一種可以選擇的方式了。
我們的讀庫就只需要執(zhí)行讀,寫庫就只需要執(zhí)行寫,把讀的壓力從主庫中分離出去,讓主庫的資源只是用來保證寫的效率,從而提高寫操作的性能。
限流算法目前程序開發(fā)過程常用的限流算法有兩個:漏桶算法和令牌桶算法。
漏桶算法
漏桶算法的原理比較簡單,請求進入到漏桶中,漏桶以一定的速率漏水。當(dāng)請求過多時,水直接溢出。可以看出,漏桶算法可以強制限制數(shù)據(jù)的傳輸速度。如圖所示,把請求比作是水滴,水先滴到桶里,通過漏洞并以限定的速度出水,當(dāng)水來得過猛而出水不夠快時就會導(dǎo)致水直接溢出,即拒絕服務(wù)。
圖片來自網(wǎng)絡(luò)
漏桶的出水速度是恒定的,那么意味著如果瞬時大流量的話,將有大部分請求被丟棄掉(也就是所謂的溢出)。
令牌桶算法
令牌桶算法的原理是系統(tǒng)以一定速率向桶中放入令牌,如果有請求時,請求會從桶中取出令牌,如果能取到令牌,則可以繼續(xù)完成請求,否則等待或者拒絕服務(wù)。這種算法可以應(yīng)對突發(fā)程度的請求,因此比漏桶算法好。
圖片來自網(wǎng)絡(luò)
漏桶算法和令牌桶算法的選擇
兩者的主要區(qū)別漏桶算法能夠強行限制處理數(shù)據(jù)的速率,不論系統(tǒng)是否空閑。而令牌桶算法能夠在限制數(shù)據(jù)的平均處理速率的同時還允許某種程度的突發(fā)流量。如何理解上面的含義呢?漏桶算法,比如系統(tǒng)吞吐量是 120/s,業(yè)務(wù)請求 130/s,使用漏斗限流 100/s,起到限流的作用,多余的請求將產(chǎn)生等待或者丟棄。對于令牌桶算法,每秒產(chǎn)生 100 個令牌,系統(tǒng)容量 200 個令牌。正常情況下,業(yè)務(wù)請求 100/s 時,請求能被正常被處理。當(dāng)有突發(fā)流量過來比如 200 個請求時,因為系統(tǒng)容量有 200 個令牌可以同一時刻處理掉這 200 個請求。如果是漏桶算法,則只能處理 100 個請求,其他的請求等待或者被丟棄。
使用mysql異步查詢,需要使用mysqlnd作為PHP的MySQL數(shù)據(jù)庫驅(qū)動。 使用MySQL異步... 如果創(chuàng)建的線程過多,則會造成線程切換引起系統(tǒng)負載過高。Swoole中的異步MySQL其...
可以的,mysql中典型的是mvcc協(xié)議:
MVCC是為了實現(xiàn)數(shù)據(jù)庫的并發(fā)控制而設(shè)計的一種協(xié)議。從直觀理解上來看,要實現(xiàn)數(shù)據(jù)庫的并發(fā)訪問控制,最簡單的做法就是加鎖訪問,即讀的時候不能寫(允許多個西線程同時讀,即共享鎖,S鎖),寫的時候不能讀(一次最多只能有一個線程對同一份數(shù)據(jù)進行寫操作,即排它鎖,X鎖)。這樣的加鎖訪問,其實并不算是真正的并發(fā),或者說它只能實現(xiàn)并發(fā)的讀,因為它最終實現(xiàn)的是讀寫串行化,這樣就大大降低了數(shù)據(jù)庫的讀寫性能。加鎖訪問其實就是和MVCC相對的LBCC,即基于鎖的并發(fā)控制(Lock-Based Concurrent Control),是四種隔離級別中級別最高的Serialize隔離級別。為了提出比LBCC更優(yōu)越的并發(fā)性能方法,MVCC便應(yīng)運而生。
方法一:進入MYSQL安裝目錄 打開MYSQL配置文件 my.ini 或 my.cnf查找 max_connections=100 修改為 max_connections=1000 服務(wù)里重起MYSQL即可
方法二:MySQL的最大連接數(shù)默認是100客戶端登錄:mysql -uusername -ppassword
設(shè)置新的最大連接數(shù)為200:mysql set GLOBAL max_connections=200
顯示當(dāng)前運行的Query:mysql show processlist
顯示當(dāng)前狀態(tài):mysql show status
退出客戶端:mysql exit
查看當(dāng)前最大連接數(shù):mysqladmin -uusername -ppassword variables