眾所周知,PHP是一個單線程的腳本開發語言,它常在Web開發及系統集成中出現。其靈活簡單成本低廉深受互聯網公司青睞,初期大量公司使用它進行快速迭代高效迭代出大量產品服務,但是當流量增長后他的弊端會漸漸展現,很多公司為此吃過不少他的苦頭。但往往都是短期放棄后,待后端底層數據完善后又用起來,讓人又愛又恨,其中發生了什么,是什么造成這個狀態,下面我簡單介紹下PHP目前架構中碰到的各種問題及解決方法來慢慢分析事情的原因經過結果,當然最后還要介紹下PHP新的技術革命的并發編程開始。
聲明:此篇文章不是批判PHP,而是希望他更好的發展,請各位原諒我的狂放
相信每一家成長中的公司多少都會經歷以下事宜:
問題:PHP不是常駐內存的進程,每個請求過來后都會重新加載解析一次腳本,平時流量不多的時候看不出來,當業務發展后業務復雜度增加而PHP加載的文件越來越多,磁盤IO負載不斷增加,由于并發增多磁盤效率下降,每次請求都會漸漸變慢。
解決方法:使用opcache緩沖轉換后的代碼,文件如果沒有更新則只需轉換一次后就一直在內存中。
問題:不是常駐內存,從持久層獲取來的數據也不會有任何內存保存(當然其他常駐內存的語言即使能做到但也不會這么做,因為會因為數據不同步導致臟數據)當流量不斷增加的時候持久層一直是個單點服務器(主從后主庫也是唯一單點)前端服務器可以橫向擴展但是單點的持久層是不能增加的,最后導致大量的持久層拆分及相關繁瑣事宜。
解決方法:使用Memcache或Redis緩沖熱數據進行緩沖或啟用其他可分布式事務持久層。如果沒有統一的方案,只能使用架構對業務特有環境特性適配各種架構方案。目前redis雖然是個好的關系NOSQL但是還是太燒人和錢。或拆庫拆表,又一條悲壯的路。
問題:不是常駐內存,很多特殊服務無法使用PHP腳本實現,只能依靠外力去做,如制作計數服務只能依靠C或Redis等服務去做,而自己本身的擴展對于通訊及進程類支持很弱這導致了PHP對于集成功能逐漸走下坡路。社區的擴展熱情還是太小,這要加強!只要這個功能強化了用PHP搞分布式計算和數據挖掘都是小意思。
解決方法:發展社區,廣開言路,支持各種野八路提想法和擴展,不斷開發PHP能力擴展插件,要知道PHP是靠Extension擴展來擴展其能力的,而擴展是用C開發的,這意味著C能做什么PHP就能做什么,只要擴展社區活躍神馬語言都競爭不過他。之前有人說PHP性能不好,很多是因為PHP的弱類型變量,那好PHP7開始支持強類型了期望PHP走的更好更穩,能做到別人有我也有,別人沒有我也有的境界。不要說風格不是以前PHP了,要知道任何一門開發語言一直在升級變化適應需要。另外,可以考慮通訊使用Swoole。
框架規范性問題,PHP是一個很靈活的語言,相對于任何一個語言來說他沒有強制的規定開發人員可以做什么事情,不可以做什么事情。所以往往集團混戰的時候會導致項目可重用性可維護性較差,當然也是正式因為如此PHP才被互聯網采用(為什么?因為互聯網產品就是不斷的快速迭代翻新的,常規軟件的瀑布流方式會死)
解決方法:只要高手或者自律性極強或及其聽話的研發人員,統一制定開發標準,劃分模塊及項目,一人負責一塊,誰也不插手別人思考后的寫法。雖然不在一起工作,但是思想一定要統一。或采用一個隔離性極強的方式去做,如Socket通訊RPC等。
PHP是單進程單線程的,當處理復雜的業務的時候我們會發現他串行執行命令的時候CPU、磁盤、內存等利用的都很低有很多時候都是在排隊等待,有的時候我們想并發的讓他去執行一批任務然后一起拿解決結果是一件很痛苦的事情(自己用pthread或者其他方式才能解決,但是這很痛苦)
解決方法:分前后端,前端可以通過消息中間件,同步、異步 調用一個或多個接口。但是socket的擴展確確實實不咋好用。不是普通小企業能做的出來的。
問題:資源爭搶問題,當我們使用持久層的時候往往有些關鍵數據是不能及時同步的,如庫存剩余,搶購這類高并發的業務我們都會很自覺的在持久層或者前端做了大量攔截和鎖定,這時我們會發現我們的持久層壓力很大很多其他無關的業務也躺槍。
解決方法:使用隊列但是能讓php使用的完善隊列并不是很多,全局單個數據或事務鎖定服務目前PHP還在石器時代大多數小公司都是直接在持久層鎖定或使用Redis(Java研究分布式很久了,所以有zookeeper一類)
問題:單個文件并發寫亂問題,當業務產生錯誤及時的預警,文件無法異步寫只能等待寫完后(只有寫的內容多才會有感覺)
解決方法:使用擴展插件,并且將日志集中監控管理(facebook那個分布式日志系統就不說了光編譯都夠掉半管血),各位慢慢翻不著急。。。文件異步寫暫時不要想了目前大部分語言都不能
問題:文件共享問題,同上個問題,目前可以和PHP配合使用(從小公司發展到大公司的過程都適用的方案很少)的分布式文件存儲實在太少了,大貓小貓三兩只,即使有也不出名不完善不好用。
解決方法:再翻翻開源找一個。。逼作者完善,或寫到redis然后異步隊列慢慢dump。
問題:并發流量增加后,資源爭搶嚴重,很多簡單的事情變得撲朔迷離,如mysql主從延遲超過30秒,我們往往查詢一個用戶是否點過贊他點過了,從庫好好久才能同步在這個期間他可以點1000次刷分等。
解決方法:前端cookie加鎖,服務加公共鎖(setnx+expire),學會使用悲觀鎖樂觀鎖。
問題:由于大量使用memcache很多無用數據都扔進去,導致memcache成天在不同大小的slab亂扔數據。
解決方法:燒錢多搭建幾個memcache,好好規劃下自己的數據緩沖及規則。超過1M的數據memcache會不緩沖的。
問題:memcache內的數據是臟的
解決方法:集中封裝底層DAO,一旦數據發生變更,自動更新相關cache,如果更新頻率極高扔到redis內存儲。確認前端哪些部分的數據是無所謂是否過時的。
問題:模塊劃分不清晰,很多數據重復獲取
解決方法:模塊層級太多,導致一些東西被重復調用,只能說改改吧。。或者用依賴注入,類自己本身緩沖一些數據,但是可能是過時的數據,或者導致PHP內存超。
事實上以上問題不僅僅PHP遇到了,很多主流開發語言碰到同樣的問題。很多情況下小公司流量不大的時候是不會碰到以上大坑的,但是當某一天流量增長了這些問題都會慢慢浮現不斷折磨每一個開發人員的神經。
造成以上原因的情況很多都是因為幾個關鍵字:
PHP沒有常駐內存(雖然他能)
PHP很難獨立做服務 (雖然他能)
PHP分布式云支持少 (雖然他也能)
PHP擴展太少了(C開發難度大,國內程序精力問題)
PHP規范太少(沒人強制規定他標準對錯)
PHP對持久層依賴太大(繼續等開源)
說了這么多,PHP沒救了?NO!你想錯了
發現了問題就去解決他
PHP沒有常駐內存?那么我們用PHP Cli即可
PHP很難獨立做服務?那是因為通訊組件不好用,用Swoole啊
PHP分布式云支持很少,通訊問題都解決了害怕啥自己寫個都行
PHP擴展太少了?沒事我們后期也可以使用php寫擴展了請看zephir
PHP規范太少了?沒關系,我們團隊自己商量著來,比規范的太規范沒有空間只能hack做事要好太多了!
PHP對持久層依賴太大?好吧這個是一直存在的,我們多用各種開源NOSQL吧,有的沒給我們PHP寫驅動?那好我們用Swoole+zephir搞定他,什么mysql代理,什么redis一致性hash代理,什么longtail。
PHP性能不好?等新版吧~雖然不是最快的但也不是最慢的我相信這個世界上沒有最好的開發語言,只有最好的社區。
PHP目前來說是互聯網產出最快,經歷最多的一門語言之一。
只要我們認為他是一個好開發語言,不斷努力改進它,豐富他
任何語言,思路,想法都不會超越PHP,因為他們有我們也可以有。
走起~PHP社區加油!Swoole加油!
期望Swoole的出現是一個引爆點,再次將PHP的輝煌重現,要知道C能做什么,PHP就能做什么,要知道 linux也是C系列寫的~:p
別人能編譯我們也能編譯(HHVM)
別人能做代理我們也能做代理(Swoole)
別人能做長連接我們也能做長連接(Swoole,Socket,libevent,Libuv)
別人能并發異步調用我們也能并發異步調用(Swoole,LibUV,Libevent)
別人能用LXC寫系統隔離我們也能用它寫系統隔離(等PHP性能再提升一次,鳥哥加油我們看好你:D)
別人能用開發語言寫自己的擴展我們也能(Zephir等)
別人有高性能框架我們也有(Phalcon,Yaf)
別人能開發分布式存儲,我們也能開發分布式存儲
當然他們還在成長,并且很緩慢。各位,我們需要作什么才能加速這個過程?請支持他們,那就是使用!宣揚!反饋!促進他們成長!也讓我們自己成長!
他們成長了,我們腳下的巨人才會更健壯。我們才能站得更高,做的更廣。
此致敬禮!
作者:thinkpc
來源:http://blog.sina.com.cn/s/blog_54ef39890102vi9c.html
- PHP技術文章
- PHP中session和cookie的區別
- php設計模式(一):簡介及創建型模式
- php設計模式結構型模式
- Php設計模式(三):行為型模式
- 十款最出色的 PHP 安全開發庫中文詳細介紹
- 12個提問頻率最高的PHP面試題
- PHP 語言需要避免的 10 大誤區
- PHP 死鎖問題分析
- 致PHP路上的“年輕人”
- PHP網站常見安全漏洞,及相應防范措施總結
- 各開源框架使用與設計總結(一)
- 數據庫的本質、概念及其應用實踐(二)
- PHP導出MySQL數據到Excel文件(fputcsv)
- PHP中14種排序算法評測
- 深入理解PHP原理之--echo的實現
- PHP性能分析相關的函數
- PHP 性能分析10則
- 10 位頂級 PHP 大師的開發原則
- 30條爆笑的程序員梗 PHP是最好的語言
- PHP底層的運行機制與原理
- PHP 性能分析與實驗——性能的宏觀分析
- PHP7 性能翻倍關鍵大揭露
- 鳥哥:寫在PHP7發布之際一些話
- PHP與MySQL通訊那點事
- Php session內部執行流程的再次剖析
- 關于 PHP 中的 Class 的幾點個人看法
- PHP Socket 編程過程詳解
- PHP過往及現在及變革
- PHP吉祥物大象的由來
- PHP生成靜態頁面的方法
- 吊炸天的 PHP 7 ,你值得擁有!
- PHP開發中文件操作疑難問答
- MongoDB PHP Driver的連接處理解析
- PHP 雜談《重構-改善既有代碼的設計》之二 對象
- 在php中判斷一個請求是ajax請求還是普通請求的方法
- 使用HAProxy、PHP、Redis和MySQL支撐10億請求每周架構細節
- HTML、HTML5、XHTML、CSS、SQL、JavaScript、PHP、Web Services 是什么?
- 重構-改善既有代碼的設計
- PHP場景中getshell防御思路分享
- 移動互聯時代,你看看除了PHP你還會些什么
- 安卓系統上搭建本地php服務器環境
- PHP中常見的緩存技術!
- PHP里10個鮮為人知但卻非常有用的函數
- 成為一名PHP專家其實并不難
- PHP 命令行?是的,您可以!
- PHP開發提高效率技巧
- PHP八大安全函數解析
- PHP實現四種基本排序算法
- PHP開發中的中文編碼問題
- php.get.post
- php發送get、post請求的6種方法簡明總結
- 中高級PHP開發者應該掌握哪些技術?
- 前端開發
- web前端知識體系大全
- 前端工程與性能優化(下)
- 前端工程與性能優化(上)
- 2016 年技術發展方向
- Web應用檢查清單
- 如何成為一名優秀的web前端工程師
- 前端組件化開發實踐
- 移動端H5頁面高清多屏適配方案
- 2015前端框架何去何從
- 從前端看“百度遷徙”的技術實現(一)
- 從前端看“百度遷徙”的技術實現(二)
- 前端路上的旅行
- 大公司里怎樣開發和部署前端代碼?
- 5個經典的前端面試問題
- 前端工程師新手必讀
- 手機淘寶前端的圖片相關工作流程梳理
- 一個自動化的前端項目實現(附源碼)
- 前端代碼異常日志收集與監控
- 15年雙11手淘前端技術總結 - H5性能最佳實踐
- 深入理解javascript原型和閉包系列
- 一切都是對象
- 函數和對象的關系
- prototype原型
- 隱式原型
- instanceof
- 繼承
- 原型的靈活性
- 簡述【執行上下文】上
- 簡述【執行上下文】下
- this
- 執行上下文棧
- 簡介【作用域】
- 【作用域】和【上下文環境】
- 從【自由變量】到【作用域鏈】
- 閉包
- 完結
- 補充:上下文環境和作用域的關系
- Linux私房菜