用 PHP 編寫支持高並發的網站,需要做什麼處理?

但是很難做靜態化啊,像做一個微博那樣子的東西,並發又高,跟新又快,這種需求的話,應該怎麼處理呢?


一般來說,解決WEB高並發的有效手段都是採用可線性擴展的多層分散式架構,

我生產項目的架構是這樣的,就在這裡拋磚引玉一下。

  1. Webserver (Nginx) :這一層是可以輕鬆分散式部署的,結合智能DNS解析可以簡易地防止單點故障、實現區域訪問加速,結合LVS很容易實現負載均衡。這一層主要是負責處理靜態請求和轉發PHP請求至第二層的PHP處理節點,至於靜態資源地址(http://misc.xxxx.com)可以單獨拿出來部署,或者直接使用商用的雲存儲服務(國內七牛不錯,國外有Amazon S3)
  2. PHP處理節點:一個節點其實就是一個監聽特定埠的系統進程,webserver的請求通過負載均衡器(我用的AWS的loadbalancer)進行分發,很好實現分散式和負載均衡。我現在用的還是php自帶的php-fpm,其實facebook出的hhvm性能非常強悍,但是還不能100%通過我項目的單元測試,等hhvm成熟過後可以平滑替換

  3. 高速緩存:用的memcached,這一層的作用主要是減輕資料庫IO和加快熱數據訪問,緩存策略與程序耦合度較高,不贅述,但簡單地說有兩種方式,一種是在程序的全局層面加一個緩存處理,這種方法代碼耦合度低,但是有效命中率不高,有些項目不一定適應,另一種是在具體的數據存取處加緩存處理,這種辦法程序耦合度較高,但是緩存命中率非常高,幾乎沒有無效緩存存在,我用的是這種。
  4. 資料庫 :我現在的項目數據規模不大,暫時只用了單台資料庫,但是程序邏輯上已做好了資料庫線性擴展的準備。其實資料庫層的擴展是老生常談了,常用手段是分庫分表,這一塊需要在前期的代碼就打下基礎,另外更平滑地手段是使用中間件,比如360的Atlas,阿里巴巴的cobar,淘寶的TDDL,中間件可以在不大範圍變更代碼的情況下擴展,但是具體的使用場景還是有限的,具體項目還需單獨考察。
  5. 其他:根據不同的項目,架構還可以選擇性地使用隊列,我現在用的beantalkd,Redis也是一個很好的選擇。隊列常用的使用環境是郵件發送和站內消息推送上面,但是在某些場景下也可以作為核心資料庫的緩衝,對應對大並發或者突發性流量也是不錯的選擇


一般使用LVS+PHP集群(1000台),就算日均80億次請求,每秒有10萬並發,那分到每台機器的請求只有100個。只要你的PHP程序不是太差,100QPS總沒問題吧?

而真正的瓶頸在於資料庫和存儲系統,數據的一致性,可擴展性,可用性很難保證。所以需要根據具體的業務場景再做橫向和縱向的分庫分表。

再輔以memcache集群緩存,key-value高性能存儲,非同步隊列任務系統,整個架構就可以建立起來。

還有一類是真正的高並發,比如WebIM,一台機器要承受數十萬的TCP客戶端連接,進行大規模的實時通信。這種的可以用PHP的非同步高並發擴展swoole 。鏈接:Swoole: PHP的非同步、並行、分散式擴展框架


億級Web系統搭建——單機到分散式集群

【問底】徐漢彬:億級Web系統搭建——單機到分散式集群-CSDN.NET


這個問題能寫本書了、

PHP網站的瓶頸基本在資料庫上。

一般中小項目,硬體比人力便宜,老闆都是會算賬的。別說主從同步了,那隻能解決實時性不高的場景。比如12306,用戶A在第一台DB里下了單,還沒傳到第100號DB,這時候第100號DB已經接受用戶B下單了。

恩,那就減少資料庫連接吧,100個用戶讀一樣的內容,那麼讀一次就行了。於是有了cache。

有了cache也有問題啊,比如怎麼保證cache和資料庫的內容一致,緩存失效一下子涌到DB怎麼辦?

恩,上面那個問題等遇見再談吧。 前面講了減少讀,現在要講減少寫,減少寫的頻率。 比如微博里給一群好友發條信息,實際上好多沒上線的,把上線的那些用戶的消息放在Redis里,數據不急著更新。

有錢,能不能再加台DB伺服器,反正伺服器便宜?每台各存一部分數據,要偶數id的帖子到A伺服器去拿,奇數到B伺服器拿。 什麼?帖子按照時間排序怎麼辦?按照點擊數排序怎麼辦? 新搞個DB伺服器去存點擊數和帖子id,有了id啥都好辦。 再有亂七八糟的需求找搜索團隊支持,實時性不高都好辦。另外看看訪問量大的搞幾個緩存。

N條評論,但是點了是空列表?這些功能99%可用就行,ICP說不定也有問題,用戶點一次沒反應,再點一次就行。

圖片。文件小啊,linux inode有限制。 把所有圖片保存在幾個大文件里,建個服務讀取。

音樂,視頻服務。

違規文字,音樂版權,小視頻,慢慢頭痛吧。


簡單來說 就是兩個思路:

1.讓同時並發數量降下來

2.讓同時處理效率升上去


一層層剝開來講,有以下部位需要注意。

1.資源。能靜態實現的就靜態實現,靜態資源也要盡量使用分散式存儲,例如雲存儲。

2.效率。PHP代碼里,盡量注意內存的使用,單個腳本的運行效率要Ok.

3.緩存。使用memcache來實現非持久存儲,使用no-sql來實現持久存儲。

4.server。使用nginx+fpm或者nginx+apache,來實現動靜態分離訪問。

5.mysql。作為最終的存儲庫以及一些不可避免的實時調用庫,做主從處理,Master+多Slave,多個只讀副本來實現實時的調用庫。

6.負載。建議架設一層負載均衡,來實現web server的輪詢。例如雲平台中的LBS。


真不知道這個世界上有多少「億級PV」的網站。

真上有上億PV的網站現在一定不會再問這樣的問題。


能靜態化的靜態化

不能靜態化的用分散式演算法

最好不要將運算交給資料庫,尤其是複雜的演算法


做靜態化 這樣就減少了資料庫的壓力


php是一個語言工具,由php來把apache/nginx/memcache/redis/mysql/httpds等工具組合到一起,根據具體的業務需求,選取不同的系統架構模型;高並發其實考驗的是系統的架構

1. 數據的讀寫層

高並發更多考驗的是數據的讀寫,最終考驗的是根據具體的業務需求進行系統的架構;哪些數據要滿足實時讀寫,哪些數據可以非同步讀寫等要考慮好;數據的讀寫模型分析清楚後就要設計數據的存儲方案,mysql擅長的是關係數據和數據統計,但是並發訪問是瓶頸;memcache擅長的是數據緩存,但kv的數據結構有限;redis作為內存資料庫但內存空間畢竟沒有硬碟空間大;

各有優缺點,那麼就要根據自己的業務來綜合或者選取用這些工具

2. 靜態/動態訪問

有條件的就使用cdn,沒條件的至少弄一個靜態訪問層,至於使用apache還是nginx或者其它的,自己在虛擬機上都安裝一遍,做一個壓力測試對比一下

非靜態訪問轉發到動態訪問層

3. 邏輯處理即php

到php了,php承接動態訪問的輸入,進行邏輯運算,最後到數據層去進行讀寫;

別做太傻的事就可以了,比如無謂的foreach循環,複製等操作;再比如,對於實時訪問,對10個數據進行排序,就不要再用mysql 的select order by 了,直接用php的函數來排序就好了。


重點是緩存,PHP有個致命缺點,沒法利用本進程的緩存空間,大家用的都是memcached,這玩意能和堆內存比嗎?所以要解決這個問題,只能自己用C編寫PHP的模塊,或者換一門WEB體系。


同步 和負載均衡 緩存。其餘的就是再加機器了。


和平台語言無關係,我說下我知道的東西。

前段資源cdn處理

應用集群部署

大的應用拆分為小的應用

應用緩存redis等

搜索引擎使用solr等

資料庫分庫分表


swoole+redis+nginx


20W並發,30台平攤,ops 一輪100w用戶,一秒鐘30W用戶,4次操作(程序內部業務邏輯操作,一個應用調用了各大平台的API實現一個功能)ops=&>30W*4=120W的redis請求。這裡的最優處理模式cdn+靜態化+redis+go改造的http請求服務(非同步請求數據),嵌套在nginx中的反向代理中。這裡網路swoole的PHP第三方擴展非同步開發請求。反正,麻煩不斷。


儘可能緩存,用redis做分散式,可以參考stackoverflow架構


資料庫優化好

使用緩存

伺服器性能好

細節要做的東西多了去了!


只是http應用的話,減少io,儘可能減少io,所有高並發方案都是為了這個目的。微博把最近幾天的feed用redis來減少io耗時,過時的數據持久化。而真正複雜的高並發場景才應該要考慮很多的,比如一場大型的搶紅包之類的,除了io之外還有一致性,高可用的權衡。


各種cache


這篇文章分析的挺好的,不同階段作不同的優化 常見的網站伺服器架構有哪些?


cdn+緩存+靜態化


做大量緩存,減少資料庫的壓力


緩存。

程序本身優化。

多加幾台伺服器。


推薦閱讀:

SESSION在服務端(PHP/JAVA)具體是如何實現的?
PHP該怎麼學?
PHP 初學者應該用哪種框架比較好?
感覺技術提高很慢,怎麼安撫浮躁的情緒?

TAG:PHP | 高並發 | PHP開發 |