十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
當(dāng)前做分布式的廠商有幾家,我知道比較出名的有“華為云分布式數(shù)據(jù)庫DDM”和“阿里云分布式數(shù)據(jù)庫”,感興趣可以自行搜素了解下。
創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比黃梅網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式黃梅網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋黃梅地區(qū)。費(fèi)用合理售后完善,10年實(shí)體公司更值得信賴。
分布式數(shù)據(jù)庫的幾點(diǎn)概念可以了解一下。
數(shù)據(jù)分庫:
以表為單位,把原有數(shù)據(jù)庫切分成多個(gè)數(shù)據(jù)庫。切分后不同的表存儲(chǔ)在不同的數(shù)據(jù)庫上。
以表中的數(shù)據(jù)行記錄為單位,把原有邏輯數(shù)據(jù)庫切分成多個(gè)物理數(shù)據(jù)庫分片,表數(shù)據(jù)記錄分布存儲(chǔ)在各個(gè)分片上。
路由分發(fā):
在分布式數(shù)據(jù)庫中,路由的作用即將SQL語句進(jìn)行解析,并轉(zhuǎn)發(fā)到正確的分片上,保證SQL執(zhí)行后得到正確的結(jié)果,并且節(jié)約QPS資源。
讀寫分離:
數(shù)據(jù)庫中對(duì)計(jì)算和緩存資源消耗較多的往往是密集或復(fù)雜的SQL查詢。當(dāng)系統(tǒng)資源被查詢語句消耗,反過來會(huì)影響數(shù)據(jù)寫入操作,進(jìn)而導(dǎo)致數(shù)據(jù)庫整體性能下降,響應(yīng)緩慢。因此,當(dāng)數(shù)據(jù)庫CPU和內(nèi)存資源占用居高不下,且讀寫比例較高時(shí),可以為數(shù)據(jù)庫添加只讀數(shù)據(jù)庫。
memcached的總結(jié)和分布式一致性hash
當(dāng)前很多大型的web系統(tǒng)為了減輕數(shù)據(jù)庫服務(wù)器負(fù)載,會(huì)采用memchached作為緩存系統(tǒng)以提高響應(yīng)速度。
目錄: ()
memchached簡(jiǎn)介
hash
取模
一致性hash
虛擬節(jié)點(diǎn)
源碼解析
參考資料
1. memchached簡(jiǎn)介
memcached是一個(gè)開源的高性能分布式內(nèi)存對(duì)象緩存系統(tǒng)。
其實(shí)思想還是比較簡(jiǎn)單的,實(shí)現(xiàn)包括server端(memcached開源項(xiàng)目一般只單指server端)和client端兩部分:
server端本質(zhì)是一個(gè)in-memory key-value store,通過在內(nèi)存中維護(hù)一個(gè)大的hashmap用來存儲(chǔ)小塊的任意數(shù)據(jù),對(duì)外通過統(tǒng)一的簡(jiǎn)單接口(memcached protocol)來提供操作。
client端是一個(gè)library,負(fù)責(zé)處理memcached protocol的網(wǎng)絡(luò)通信細(xì)節(jié),與memcached server通信,針對(duì)各種語言的不同實(shí)現(xiàn)分裝了易用的API實(shí)現(xiàn)了與不同語言平臺(tái)的集成。
web系統(tǒng)則通過client庫來使用memcached進(jìn)行對(duì)象緩存。
2. hash
memcached的分布式主要體現(xiàn)在client端,對(duì)于server端,僅僅是部署多個(gè)memcached server組成集群,每個(gè)server獨(dú)自維護(hù)自己的數(shù)據(jù)(互相之間沒有任何通信),通過daemon監(jiān)聽端口等待client端的請(qǐng)求。
而在client端,通過一致的hash算法,將要存儲(chǔ)的數(shù)據(jù)分布到某個(gè)特定的server上進(jìn)行存儲(chǔ),后續(xù)讀取查詢使用同樣的hash算法即可定位。
client端可以采用各種hash算法來定位server:
取模
最簡(jiǎn)單的hash算法
targetServer = serverList[hash(key) % serverList.size]
直接用key的hash值(計(jì)算key的hash值的方法可以自由選擇,比如算法CRC32、MD5,甚至本地hash系統(tǒng),如java的hashcode)模上server總數(shù)來定位目標(biāo)server。這種算法不僅簡(jiǎn)單,而且具有不錯(cuò)的隨機(jī)分布特性。
但是問題也很明顯,server總數(shù)不能輕易變化。因?yàn)槿绻黾?減少memcached server的數(shù)量,對(duì)原先存儲(chǔ)的所有key的后續(xù)查詢都將定位到別的server上,導(dǎo)致所有的cache都不能被命中而失效。
一致性hash
為了解決這個(gè)問題,需要采用一致性hash算法(consistent hash)
相對(duì)于取模的算法,一致性hash算法除了計(jì)算key的hash值外,還會(huì)計(jì)算每個(gè)server對(duì)應(yīng)的hash值,然后將這些hash值映射到一個(gè)有限的值域上(比如0~2^32)。通過尋找hash值大于hash(key)的最小server作為存儲(chǔ)該key數(shù)據(jù)的目標(biāo)server。如果找不到,則直接把具有最小hash值的server作為目標(biāo)server。
為了方便理解,可以把這個(gè)有限值域理解成一個(gè)環(huán),值順時(shí)針遞增。
如上圖所示,集群中一共有5個(gè)memcached server,已通過server的hash值分布到環(huán)中。
如果現(xiàn)在有一個(gè)寫入cache的請(qǐng)求,首先計(jì)算x=hash(key),映射到環(huán)中,然后從x順時(shí)針查找,把找到的第一個(gè)server作為目標(biāo)server來存儲(chǔ)cache,如果超過了2^32仍然找不到,則命中第一個(gè)server。比如x的值介于A~B之間,那么命中的server節(jié)點(diǎn)應(yīng)該是B節(jié)點(diǎn)
可以看到,通過這種算法,對(duì)于同一個(gè)key,存儲(chǔ)和后續(xù)的查詢都會(huì)定位到同一個(gè)memcached server上。
那么它是怎么解決增/刪server導(dǎo)致的cache不能命中的問題呢?
假設(shè),現(xiàn)在增加一個(gè)server F,如下圖
此時(shí),cache不能命中的問題仍然存在,但是只存在于B~F之間的位置(由C變成了F),其他位置(包括F~C)的cache的命中不受影響(刪除server的情況類似)。盡管仍然有cache不能命中的存在,但是相對(duì)于取模的方式已經(jīng)大幅減少了不能命中的cache數(shù)量。
虛擬節(jié)點(diǎn)
但是,這種算法相對(duì)于取模方式也有一個(gè)缺陷:當(dāng)server數(shù)量很少時(shí),很可能他們?cè)诃h(huán)中的分布不是特別均勻,進(jìn)而導(dǎo)致cache不能均勻分布到所有的server上。
如圖,一共有3臺(tái)server – 1,2,4。命中4的幾率遠(yuǎn)遠(yuǎn)高于1和2。
為解決這個(gè)問題,需要使用虛擬節(jié)點(diǎn)的思想:為每個(gè)物理節(jié)點(diǎn)(server)在環(huán)上分配100~200個(gè)點(diǎn),這樣環(huán)上的節(jié)點(diǎn)較多,就能抑制分布不均勻。
當(dāng)為cache定位目標(biāo)server時(shí),如果定位到虛擬節(jié)點(diǎn)上,就表示cache真正的存儲(chǔ)位置是在該虛擬節(jié)點(diǎn)代表的實(shí)際物理server上。
另外,如果每個(gè)實(shí)際server的負(fù)載能力不同,可以賦予不同的權(quán)重,根據(jù)權(quán)重分配不同數(shù)量的虛擬節(jié)點(diǎn)。
// 采用有序map來模擬環(huán)
this.consistentBuckets = new TreeMap();
MessageDigest md5 = MD5.get();//用MD5來計(jì)算key和server的hash值
// 計(jì)算總權(quán)重
if ( this.totalWeight for ( int i = 0; i this.weights.length; i++ )
this.totalWeight += ( this.weights[i] == null ) ? 1 : this.weights[i];
} else if ( this.weights == null ) {
this.totalWeight = this.servers.length;
}
// 為每個(gè)server分配虛擬節(jié)點(diǎn)
for ( int i = 0; i servers.length; i++ ) {
// 計(jì)算當(dāng)前server的權(quán)重
int thisWeight = 1;
if ( this.weights != null this.weights[i] != null )
thisWeight = this.weights[i];
// factor用來控制每個(gè)server分配的虛擬節(jié)點(diǎn)數(shù)量
// 權(quán)重都相同時(shí),factor=40
// 權(quán)重不同時(shí),factor=40*server總數(shù)*該server權(quán)重所占的百分比
// 總的來說,權(quán)重越大,factor越大,可以分配越多的虛擬節(jié)點(diǎn)
double factor = Math.floor( ((double)(40 * this.servers.length * thisWeight)) / (double)this.totalWeight );
for ( long j = 0; j factor; j++ ) {
// 每個(gè)server有factor個(gè)hash值
// 使用server的域名或IP加上編號(hào)來計(jì)算hash值
// 比如server - "172.45.155.25:11111"就有factor個(gè)數(shù)據(jù)用來生成hash值:
// 172.45.155.25:11111-1, 172.45.155.25:11111-2, ..., 172.45.155.25:11111-factor
byte[] d = md5.digest( ( servers[i] + "-" + j ).getBytes() );
// 每個(gè)hash值生成4個(gè)虛擬節(jié)點(diǎn)
for ( int h = 0 ; h 4; h++ ) {
Long k =
((long)(d[3+h*4]0xFF) 24)
| ((long)(d[2+h*4]0xFF) 16)
| ((long)(d[1+h*4]0xFF) 8 )
| ((long)(d[0+h*4]0xFF));
// 在環(huán)上保存節(jié)點(diǎn)
consistentBuckets.put( k, servers[i] );
}
}
// 每個(gè)server一共分配4*factor個(gè)虛擬節(jié)點(diǎn)
}
// 采用有序map來模擬環(huán)
this.consistentBuckets = new TreeMap();
MessageDigest md5 = MD5.get();//用MD5來計(jì)算key和server的hash值
// 計(jì)算總權(quán)重
if ( this.totalWeight for ( int i = 0; i this.weights.length; i++ )
this.totalWeight += ( this.weights[i] == null ) ? 1 : this.weights[i];
} else if ( this.weights == null ) {
this.totalWeight = this.servers.length;
}
// 為每個(gè)server分配虛擬節(jié)點(diǎn)
for ( int i = 0; i servers.length; i++ ) {
// 計(jì)算當(dāng)前server的權(quán)重
int thisWeight = 1;
if ( this.weights != null this.weights[i] != null )
thisWeight = this.weights[i];
// factor用來控制每個(gè)server分配的虛擬節(jié)點(diǎn)數(shù)量
// 權(quán)重都相同時(shí),factor=40
// 權(quán)重不同時(shí),factor=40*server總數(shù)*該server權(quán)重所占的百分比
// 總的來說,權(quán)重越大,factor越大,可以分配越多的虛擬節(jié)點(diǎn)
double factor = Math.floor( ((double)(40 * this.servers.length * thisWeight)) / (double)this.totalWeight );
for ( long j = 0; j factor; j++ ) {
// 每個(gè)server有factor個(gè)hash值
// 使用server的域名或IP加上編號(hào)來計(jì)算hash值
// 比如server - "172.45.155.25:11111"就有factor個(gè)數(shù)據(jù)用來生成hash值:
// 172.45.155.25:11111-1, 172.45.155.25:11111-2, ..., 172.45.155.25:11111-factor
byte[] d = md5.digest( ( servers[i] + "-" + j ).getBytes() );
// 每個(gè)hash值生成4個(gè)虛擬節(jié)點(diǎn)
for ( int h = 0 ; h 4; h++ ) {
Long k =
((long)(d[3+h*4]0xFF) 24)
| ((long)(d[2+h*4]0xFF) 16)
| ((long)(d[1+h*4]0xFF) 8 )
| ((long)(d[0+h*4]0xFF));
// 在環(huán)上保存節(jié)點(diǎn)
consistentBuckets.put( k, servers[i] );
}
}
// 每個(gè)server一共分配4*factor個(gè)虛擬節(jié)點(diǎn)
}
// 用MD5來計(jì)算key的hash值
MessageDigest md5 = MD5.get();
md5.reset();
md5.update( key.getBytes() );
byte[] bKey = md5.digest();
// 取MD5值的低32位作為key的hash值
long hv = ((long)(bKey[3]0xFF) 24) | ((long)(bKey[2]0xFF) 16) | ((long)(bKey[1]0xFF) 8 ) | (long)(bKey[0]0xFF);
// hv的tailMap的第一個(gè)虛擬節(jié)點(diǎn)對(duì)應(yīng)的即是目標(biāo)server
SortedMap tmap = this.consistentBuckets.tailMap( hv );
return ( tmap.isEmpty() ) ? this.consistentBuckets.firstKey() : tmap.firstKey();
更多問題到問題求助專區(qū)()
根據(jù)自己多年銷售、運(yùn)營(yíng)服務(wù)器的經(jīng)驗(yàn)說一下
選擇云主機(jī)(云服務(wù)器)和選擇其他主機(jī)的方法類似,要選擇合適的云主機(jī)就需要對(duì)自己的網(wǎng)站情況以及云主機(jī)的各項(xiàng)配置
參數(shù)有一定了解,具體如下:
首先是網(wǎng)站的情況:
1、網(wǎng)站的類型:比如網(wǎng)站是靜態(tài)還是動(dòng)態(tài)為主,使用的什么的網(wǎng)站程序,對(duì)運(yùn)行環(huán)境有何要求,是否需要配置特定的環(huán)境,這將影響到操作系統(tǒng)、存儲(chǔ)模式的選擇。
2、網(wǎng)站的訪問量:網(wǎng)站的日均訪問人數(shù)和平均同時(shí)在線人數(shù)有多少,這將影響到CPU、內(nèi)存、帶寬等選擇。
3、網(wǎng)站的數(shù)據(jù)大?。壕W(wǎng)站目前的數(shù)據(jù)有多大,未來是否會(huì)快速增加,這將影響到硬盤的選擇。
4、網(wǎng)站的目標(biāo)用戶:網(wǎng)站是面向全國(guó)用戶還是本地用戶,這將影響到機(jī)房線路的選擇。
在確定網(wǎng)站情況之后可以結(jié)合云主機(jī)的各項(xiàng)配置參數(shù)進(jìn)行估算選擇:
云主機(jī)參數(shù)配置
1.CPU:CPU代表主機(jī)的運(yùn)算能力,如果網(wǎng)站流量較大,動(dòng)態(tài)頁面比較多,建議選擇2核以上CPU。
2.內(nèi)存:內(nèi)存也是決定網(wǎng)站打開速度的重要因素,內(nèi)存越大,可用緩存越大,打開速度也就越快,windows操作系統(tǒng)不支持選擇512MB內(nèi)存。
3.硬盤:硬盤的大小要根據(jù)網(wǎng)站的大小來決定,在選擇時(shí)應(yīng)該考慮到剩余空間。另外硬盤的I/O讀取速度直接決定文件讀取的快慢,新麥互聯(lián)云主機(jī)硬盤的讀取速度比其他網(wǎng)站快很多,一般情況下都?jí)蛴谩?/p>
4.帶寬:云主機(jī)沒有流量限制,所以主要考慮帶寬。帶寬是一個(gè)網(wǎng)站打開速度的直接體現(xiàn),帶寬越大,訪問的時(shí)候,打開速度就越快。訪問人數(shù)較多的網(wǎng)站,建議選擇大的帶寬。
5.操作系統(tǒng):操作系統(tǒng)的選擇和個(gè)人的熟悉情況和網(wǎng)站具體情況有關(guān),對(duì)哪種操作系統(tǒng)比較了解就選擇哪種操作系統(tǒng),另外windows系統(tǒng)對(duì)asp程序支持較好,不過占用內(nèi)存較多,而Linux系統(tǒng)對(duì)php程序支持較好,更省內(nèi)存,并且有的程序可能只支持某個(gè)操作系統(tǒng)。
6.機(jī)房線路:線路選擇合適的機(jī)房。
7.存儲(chǔ)模式:分布式存儲(chǔ)數(shù)據(jù)保留四份,而SSD固態(tài)硬盤適合對(duì)I/O讀取速度有更高要求的用戶。
如果還是不能確定選擇何種配置,可以先購(gòu)買一個(gè)標(biāo)準(zhǔn)配置運(yùn)行一段時(shí)間進(jìn)行觀察,如果發(fā)現(xiàn)配置不夠可以隨時(shí)升級(jí)
php 高并發(fā)解決思路解決方案,如何應(yīng)對(duì)網(wǎng)站大流量高并發(fā)情況。本文為大家總結(jié)了常用的處理方式,但不是細(xì)節(jié),后續(xù)一系列細(xì)節(jié)教程給出。希望大家喜歡。
一 高并發(fā)的概念
在互聯(lián)網(wǎng)時(shí)代,并發(fā),高并發(fā)通常是指并發(fā)訪問。也就是在某個(gè)時(shí)間點(diǎn),有多少個(gè)訪問同時(shí)到來。
二 高并發(fā)架構(gòu)相關(guān)概念
1、QPS (每秒查詢率) : 每秒鐘請(qǐng)求或者查詢的數(shù)量,在互聯(lián)網(wǎng)領(lǐng)域,指每秒響應(yīng)請(qǐng)求數(shù)(指 HTTP 請(qǐng)求)
2、PV(Page View):綜合瀏覽量,即頁面瀏覽量或者點(diǎn)擊量,一個(gè)訪客在 24 小時(shí)內(nèi)訪問的頁面數(shù)量
--注:同一個(gè)人瀏覽你的網(wǎng)站的同一頁面,只記做一次 pv
3、吞吐量(fetches/sec) :?jiǎn)挝粫r(shí)間內(nèi)處理的請(qǐng)求數(shù)量 (通常由 QPS 和并發(fā)數(shù)決定)
4、響應(yīng)時(shí)間:從請(qǐng)求發(fā)出到收到響應(yīng)花費(fèi)的時(shí)間
5、獨(dú)立訪客(UV):一定時(shí)間范圍內(nèi),相同訪客多次訪問網(wǎng)站,只計(jì)算為 1 個(gè)獨(dú)立訪客
6、帶寬:計(jì)算帶寬需關(guān)注兩個(gè)指標(biāo),峰值流量和頁面的平均大小
7、日網(wǎng)站帶寬: PV/統(tǒng)計(jì)時(shí)間(換算到秒) * 平均頁面大?。╧b)* 8
三 需要注意點(diǎn):
1、QPS 不等于并發(fā)連接數(shù)(QPS 是每秒 HTTP 請(qǐng)求數(shù)量,并發(fā)連接數(shù)是系統(tǒng)同時(shí)處理的請(qǐng)求數(shù)量)
2、峰值每秒請(qǐng)求數(shù)(QPS)= (總 PV 數(shù)*80%)/ (六小時(shí)秒數(shù)*20%)【代表 80%的訪問量都集中在 20%的時(shí)間內(nèi)】
3、壓力測(cè)試: 測(cè)試能承受的最大并發(fā)數(shù) 以及測(cè)試最大承受的 QPS 值
4、常用的性能測(cè)試工具【ab,wrk,httpload,Web Bench,Siege,Apache JMeter】
四 優(yōu)化
1、當(dāng) QPS 小于 50 時(shí)
優(yōu)化方案:為一般小型網(wǎng)站,不用考慮優(yōu)化
2、當(dāng) QPS 達(dá)到 100 時(shí),遇到數(shù)據(jù)查詢瓶頸
優(yōu)化方案: 數(shù)據(jù)庫緩存層,數(shù)據(jù)庫的負(fù)載均衡
3、當(dāng) QPS 達(dá)到 800 時(shí), 遇到帶寬瓶頸
優(yōu)化方案:CDN 加速,負(fù)載均衡
4、當(dāng) QPS 達(dá)到 1000 時(shí)
優(yōu)化方案: 做 html 靜態(tài)緩存
5、當(dāng) QPS 達(dá)到 2000 時(shí)
優(yōu)化方案: 做業(yè)務(wù)分離,分布式存儲(chǔ)
五、高并發(fā)解決方案案例:
1、流量?jī)?yōu)化
防盜鏈處理(去除惡意請(qǐng)求)
2、前端優(yōu)化
(1) 減少 HTTP 請(qǐng)求[將 css,js 等合并]
(2) 添加異步請(qǐng)求(先不將所有數(shù)據(jù)都展示給用戶,用戶觸發(fā)某個(gè)事件,才會(huì)異步請(qǐng)求數(shù)據(jù))
(3) 啟用瀏覽器緩存和文件壓縮
(4) CDN 加速
(5) 建立獨(dú)立的圖片服務(wù)器(減少 I/O)
3、服務(wù)端優(yōu)化
(1) 頁面靜態(tài)化
(2) 并發(fā)處理
(3) 隊(duì)列處理
4、數(shù)據(jù)庫優(yōu)化
(1) 數(shù)據(jù)庫緩存
(2) 分庫分表,分區(qū)
(3) 讀寫分離
(4) 負(fù)載均衡
5、web 服務(wù)器優(yōu)化
(1) nginx 反向代理實(shí)現(xiàn)負(fù)載均衡
(2) lvs 實(shí)現(xiàn)負(fù)載均衡