亚洲欧美日韩综合系列在线_91精品人妻一区二区_欧美大肥婆一级特大AA片_九色91视频免费观看_亚洲综合国产精品_av中文字幕在线不卡_久久精品色综合网_看黄色视频的软件_无卡无码高清中文字幕码2024_亚洲欧美日韩天堂网

java 高并發(fā)如何優(yōu)化

來源:小屁孩大帥-楊一凡 發(fā)布時間:2018-12-05 14:52:52 閱讀量:1086

問題產(chǎn)生的原因?

同步和異步--數(shù)據(jù)訪問次數(shù)增大-


 


一般程序中,是如何處理并發(fā)和同步的?

代碼層次上,Java同步鎖-

       一種是代碼層次上的,如java中的同步鎖,典型的就是同步關(guān)鍵字synchronized


數(shù)據(jù)庫層次上,,比較典型的就是悲觀鎖和樂觀鎖。這里我們重點講解的就是悲觀鎖(傳統(tǒng)的物理鎖)和樂觀鎖

悲觀鎖:--數(shù)據(jù)庫鎖機制---多讀少寫的情況下


對數(shù)據(jù)被外界調(diào)用使用修改保持保守悲觀的態(tài)度;


使整個數(shù)據(jù)再處理中,將數(shù)據(jù)處于鎖定狀態(tài)下;


往往是依靠數(shù)據(jù)庫提供的鎖機制


也只有數(shù)據(jù)庫層提供的鎖機制才能 真正保證數(shù)據(jù)訪問的排他性,


否則,即使在本系統(tǒng) 中實現(xiàn)了加鎖機制,也無法保證外部系 統(tǒng)不會修改數(shù)據(jù)


樂觀鎖:---版本記錄機制實現(xiàn)version--少寫,多度的情況下


大多是基于數(shù)據(jù)版本   Version )記錄機制實現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識,在基于數(shù)據(jù)庫表的版本解決方案中,一般是通


過為數(shù)據(jù)庫表增加一個 “version” 字段來 實現(xiàn)。 讀取出數(shù)據(jù)時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提 交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)


3,悲觀和樂觀的區(qū)別和聯(lián)系


悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。


 


樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號等機制。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫如果提供類似于write_condition機制的其實都是提供的樂觀鎖。


 


兩種鎖各有優(yōu)缺點,不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下,即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。但如果經(jīng)常產(chǎn)生沖突,上層應(yīng)用會不斷的進(jìn)行retry,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。


案例分析

   案例一:訂票系統(tǒng)案例,某航班只有一張機票,假定有1w個人打開你的網(wǎng)站來訂票,問你如何解決并發(fā)問題(可擴展到任何高并發(fā)網(wǎng)站要考慮


               的并發(fā)讀寫問題)


    問題,1w個人來訪問,票沒出去前要保證大家都能看到有票,不可能一個人在看到票的時候別人就不能看了。到底誰能搶到,那得看這個人的“運氣”(網(wǎng)


             絡(luò)快慢等)


其次考慮的問題,并發(fā),1w個人同時點擊購買,到底誰能成交?總共只有一張票。


首先我們?nèi)菀紫氲胶筒l(fā)相關(guān)的幾個方案 :


鎖同步同步更多指的是應(yīng)用程序的層面,多個線程進(jìn)來,只能一個一個的訪問,java中指的是syncrinized關(guān)鍵字。鎖也有2個層面,一個是java中談到的對


象鎖,用于線程同步;另外一個層面是數(shù)據(jù)庫的鎖;如果是分布式的系統(tǒng),顯然只能利用數(shù)據(jù)庫端的鎖來實現(xiàn)。


假定我們采用了同步機制或者數(shù)據(jù)庫物理鎖機制,如何保證1w個人還能同時看到有票,顯然會犧牲性能,在高并發(fā)網(wǎng)站中是不可取的。使用hibernate后我們


提出了另外一個概念:樂觀鎖、悲觀鎖(即傳統(tǒng)的物理鎖);


采用樂觀鎖即可解決此問題。樂觀鎖意思是不鎖定表的情況下,利用業(yè)務(wù)的控制來解決并發(fā)問題,這樣即保證數(shù)據(jù)的并發(fā)可讀性又保證保存數(shù)據(jù)的排他性,保


證性能的同時解決了并發(fā)帶來的臟數(shù)據(jù)問題。


hibernate中如何實現(xiàn)樂觀鎖:


前提:在現(xiàn)有表當(dāng)中增加一個冗余字段,version版本號, long類型


原理:


1)只有當(dāng)前版本號》=數(shù)據(jù)庫表版本號,才能提交


2)提交成功后,版本號version ++


實現(xiàn)很簡單:在ormapping增加一屬性optimistic-lock="version"即可,以下是樣例片段


<hibernate-mapping>


<class name="com.insigma.stock.ABC" optimistic-lock="version" table="T_Stock" schema="STOCK">


案例二、股票交易系統(tǒng)、銀行系統(tǒng),大數(shù)據(jù)量你是如何考慮的


首先,股票交易系統(tǒng)的行情表,每幾秒鐘就有一個行情記錄產(chǎn)生,一天下來就有(假定行情3秒一個) 股票數(shù)量×20×60*6 條記錄,一月下來這個表記錄數(shù)


量多大? oracle中一張表的記錄數(shù)超過100w后 查詢性能就很差了,如何保證系統(tǒng)性能?


再比如,中國移動有上億的用戶量,表如何設(shè)計?把所有用于存在于一個表么?


所以,大數(shù)量的系統(tǒng),必須考慮表拆分-(表名字不一樣,但是結(jié)構(gòu)完全一樣),通用的幾種方式:(視情況而定)


1)按業(yè)務(wù)分,比如 手機號的表,我們可以考慮 130開頭的作為一個表,131開頭的另外一張表 以此類推


2)利用oracle的表拆分機制做分表


3)如果是交易系統(tǒng),我們可以考慮按時間軸拆分,當(dāng)日數(shù)據(jù)一個表,歷史數(shù)據(jù)弄到其它表。這里歷史數(shù)據(jù)的報表和查詢不會影響當(dāng)日交易。


當(dāng)然,表拆分后我們的應(yīng)用得做相應(yīng)的適配。單純的or-mapping也許就得改動了。比如部分業(yè)務(wù)得通過存儲過程等


此外,我們還得考慮緩存


這里的緩存,指的不僅僅是hibernate,hibernate本身提供了一級二級緩存。這里的緩存獨立于應(yīng)用,依然是內(nèi)存的讀取,假如我們能減少數(shù)據(jù)庫頻繁的訪


問,那對系統(tǒng)肯定大大有利的。比如一個電子商務(wù)系統(tǒng)的商品搜索,如果某個關(guān)鍵字的商品經(jīng)常被搜,那就可以考慮這部分商品列表存放到緩存(內(nèi)存中


去),這樣不用每次訪問數(shù)據(jù)庫,性能大大增加。


簡單的緩存大家可以理解為自己做一個hashmap,把常訪問的數(shù)據(jù)做一個key,value是第一次從數(shù)據(jù)庫搜索出來的值,下次訪問就可以從map里讀取,而不


讀數(shù)據(jù)庫;專業(yè)些的目前有獨立的緩存框架比如memcached 等,可獨立部署成一個緩存服務(wù)器。


 


常見的提高高并發(fā)下訪問的效率的手段

 首先要了解高并發(fā)的的瓶頸在哪里?


     1、可能是服務(wù)器網(wǎng)絡(luò)帶寬不夠


     2.可能web線程連接數(shù)不夠


     3.可能數(shù)據(jù)庫連接查詢上不去。


     根據(jù)不同的情況,解決思路也不同。


像第一種情況可以增加網(wǎng)絡(luò)帶寬,DNS域名解析分發(fā)多臺服務(wù)器。


負(fù)載均衡,前置代理服務(wù)器nginx、apache等等


數(shù)據(jù)庫查詢優(yōu)化,讀寫分離,分表等等


   最后復(fù)制一些在高并發(fā)下面需要常常需要處理的內(nèi)容:


盡量使用緩存,包括用戶緩存,信息緩存等,多花點內(nèi)存來做緩存,可以大量減少與數(shù)據(jù)庫的交互,提高性能。


用jprofiler等工具找出性能瓶頸,減少額外的開銷。


優(yōu)化數(shù)據(jù)庫查詢語句,減少直接使用hibernate等工具的直接生成語句(僅耗時較長的查詢做優(yōu)化)。


優(yōu)化數(shù)據(jù)庫結(jié)構(gòu),多做索引,提高查詢效率。


統(tǒng)計的功能盡量做緩存,或按每天一統(tǒng)計或定時統(tǒng)計相關(guān)報表,避免需要時進(jìn)行統(tǒng)計的功能。


能使用靜態(tài)頁面的地方盡量使用,減少容器的解析(盡量將動態(tài)內(nèi)容生成靜態(tài)html來顯示)。


解決以上問題后,使用服務(wù)器集群來解決單臺的瓶頸問題。


 

總 結(jié):其實我們在開發(fā)中都很少考慮這種問題,直接都是先將功能實現(xiàn),當(dāng)一個程序員在干到1到2年,就會感覺光實現(xiàn)功能不是最主要的,安全性能、質(zhì)量等等才是 一個開發(fā)人員最該關(guān)心的。今天我所說的是高并發(fā)。


我的解決思路是:


1、采用分布式應(yīng)用設(shè)計


2、分布式緩存數(shù)據(jù)庫


3、代碼優(yōu)化

--------------------- 



標(biāo)簽: PHP 環(huán)境搭建
分享:
評論:
你還沒有登錄,請先