本篇文章給大家分享的是有關(guān)java項(xiàng)目中如何利用高并發(fā)將信息寫(xiě)入數(shù)據(jù)庫(kù),小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著小編一起來(lái)看看吧。
成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)公司、微信開(kāi)發(fā)、微信小程序、集團(tuán)成都定制網(wǎng)頁(yè)設(shè)計(jì)等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶(hù);涵蓋的客戶(hù)類(lèi)型包括:PVC花箱等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶(hù)的一致贊美!
假定存在這樣一種情況
多個(gè)用戶(hù)對(duì)數(shù)據(jù)庫(kù)進(jìn)行寫(xiě),我們的業(yè)務(wù)邏輯規(guī)定,每個(gè)用戶(hù)只能寫(xiě)一次,大部分用戶(hù)也只發(fā)一次請(qǐng)求。
public void write(Uers u){ // do something }
但是有一種情況(1%的情況下吧)的就是有的用戶(hù)會(huì)發(fā)兩次甚至更多次寫(xiě)請(qǐng)求(因?yàn)閿?shù)據(jù)庫(kù)限制,我們不方便在主鍵上做文章)。
如果這個(gè)特殊的用戶(hù)發(fā)送的兩次請(qǐng)求時(shí)間間隔比較大,那就簡(jiǎn)單了,再每次寫(xiě)入的時(shí)候,寫(xiě)去數(shù)據(jù)庫(kù)里看看,這個(gè)人有沒(méi)有寫(xiě)過(guò),如果已經(jīng)寫(xiě)過(guò)了,就直接拋棄這個(gè)請(qǐng)求。
public void write(Uers u){ if(!checkIfExistUser(u)){ // do something } }
不過(guò)最大的問(wèn)題就是,如果用戶(hù)幾乎在瞬時(shí),發(fā)送了兩個(gè)寫(xiě)操作。
而且假定我們的do something比較耗時(shí),那么上面的策略就有可能失敗。
為啥失敗?我不用解釋了吧。
那咋辦?
方法一
萬(wàn)年不變的synchronized。
public synchronized void write(Uers u){ if(!checkIfExistUser(u)){ // do something } }
當(dāng)然,我們得承認(rèn),有了上面的方法,就不會(huì)出現(xiàn),數(shù)據(jù)庫(kù)里有兩條張三的記錄了
但上面的鎖的粒度太大了,張三寫(xiě)的時(shí)候,李四也不能寫(xiě)了。
其實(shí)我們想要的只是:張三自己本人,不能同時(shí)多次寫(xiě)入。
方法二
類(lèi) String 維護(hù)一個(gè)字符串池。 當(dāng)調(diào)用 intern 方法時(shí),如果池已經(jīng)包含一個(gè)等于此 String 對(duì)象的字符串(該對(duì)象由 equals(Object) 方法確定),則返回池中的字符串??梢?jiàn),當(dāng)String相同時(shí),String.intern()總是返回同一個(gè)對(duì)象,因此就實(shí)現(xiàn)了對(duì)同一用戶(hù)加鎖。由于鎖的粒度局限于具體用戶(hù),使系統(tǒng)獲得了最大程度的并發(fā)。
public synchronized void write(Uers u){ synchronized(u.getUserId.intern()) { // do something } }
上面的思路就保證了張三寫(xiě)的時(shí)候,李四可以寫(xiě),但是不能兩個(gè)張三一塊寫(xiě)。
方法三
其實(shí)我個(gè)人覺(jué)得,方法二已經(jīng)很好了,如果非要說(shuō)方法二還有什么問(wèn)題的話(huà),只能說(shuō):
String.inter()的缺陷是類(lèi) String 維護(hù)一個(gè)字符串池是放在JVM perm區(qū)的,如果用戶(hù)數(shù)特別多,導(dǎo)致放入字符串池的String不可控,有可能導(dǎo)致OOM錯(cuò)誤或者過(guò)多的Full GC。
那咋辦?
public synchronized void write(Uers u){ String userSuffix=getSuffix(u); synchronized(userSuffix.intern()) { // do something } }
至于那個(gè)獲得后綴的策略,大家自己想。
有了這個(gè)策略,我就能保證1億個(gè)用戶(hù),可能只有10000個(gè)不同的后綴。
有可能張三李四的后綴一樣,但是張三李四同時(shí)發(fā)請(qǐng)求的概率,應(yīng)該也不會(huì)太大。就算真的同時(shí)發(fā)了,那你等一下不行么?
方法四
Map locks = new Map(); List lockKeys = new List(); for(int number : 1 - 10000) { Object lockKey = new Object(); lockKeys.add(lockKey); locks.put(lockKey, new Object()); } public void doSomeThing(String uid) { Object lockKey = lockKeys.get(uid.hash() % lockKeys.size()); Object lock = locks.get(lockKey); synchronized(lock) { // do something } }
個(gè)人感覺(jué)和方法三的核心差不多。
方法五
如果是集群情況下,兩個(gè)張三幾乎瞬時(shí)進(jìn)入兩臺(tái)服務(wù)器,那java語(yǔ)言級(jí)別的鎖都得報(bào)廢。
可以使用redis的分布式鎖
方法六
使用zookeeper
只是聽(tīng)說(shuō)有這么一個(gè)思路,但是本人沒(méi)用過(guò)zookeeper,這個(gè)方法就不多說(shuō)了。
以上就是java項(xiàng)目中如何利用高并發(fā)將信息寫(xiě)入數(shù)據(jù)庫(kù),小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站名稱(chēng):java項(xiàng)目中如何利用高并發(fā)將信息寫(xiě)入數(shù)據(jù)庫(kù)
網(wǎng)站地址:http://chinadenli.net/article16/joidgg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、全網(wǎng)營(yíng)銷(xiāo)推廣、、外貿(mào)網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化、定制開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)