網站高併發解決方案(理論知識)

一:mysql方面

mysql方面,我們主要要從以下幾點去考慮:

1:索引

mysql其實沒有想象中的那麼差,相反,mysql表數據,只要查到了索引,都不會慢,(1.5億數據表查索引0.0幾秒),所以mysql索引是個好東西,用好之後,查詢效率自然很快,

所以,數據表設計,一定要考慮全面,給查詢頻繁使用的字段增加索引,或者組合索引

索引學習傳送門https://www.cnblogs.com/zhaobingqing/p/7071331.html

 

2:查詢數據緩存

配置數據,某些變更不頻繁或查詢頻繁的數據可以通過redis,memcache,file(不推薦)等方式增加緩存,避免數據庫頻繁查詢造成額外的數據庫性能消耗

場景一:進網站的輪播圖,由於變更不頻繁,可以設置緩存1天,當輪播圖修改更新時,更新緩存

場景二:10萬個會員的聊天室,進來需要查詢聊天記錄,由於聊天記錄變更頻繁並且查詢頻繁,可設置緩存1-3秒,緩存失效纔去取一次數據庫,將大部分查詢都進入緩存中查詢,大大降低了數據庫壓力

 

3:查詢邏輯優化

場景一:當你想在一個1000萬的訪問表,統計會員A的訪問記錄時,你會發現,就算給會員id增加了索引,也會很慢,因爲這個涉及到了數據命中條數

mysql命中條數越多,則查詢越慢

優化方案:由於是訪問表,不算是重要數據,可增加一個統計表,統計每天的訪問數量,當你要查會員A的訪問總數,則直接去sum統計表中的數據,大大提高了性能

 

場景二:某個抽獎程序,A獎品限制每天只能出1萬個,判斷當天是否超出限制時,一般情況是count(1) 查出獎記錄表,這樣做是不正確的,正確做法:

1:增加個庫存字段,每天自動更新爲10000,每次抽中減一,判斷是否出完只需要查看庫存字段

2:增加個計數表,按每天爲單位,每次抽中則字段num+1,判斷是否超出限制,只需要查出當天記錄的num字段比對就行

 

場景三:高併發下,會員搶10萬個紅包怎麼做?

每天新增1萬條獎品記錄,並生成緩存隊列(redis),每次搶完則從隊列中取數據,搶完批量更新回數據庫

 

場景三:額,不算是場景了,當有一個表,字段數有50,而你取數據只需要10個字段時,儘量把select * 寫成 select 字段名,字段名,可以讓mysql節省沒必要的返回數據,從而影響效率

 

二:服務器硬盤方面

大多數人,可能不知道有iops(硬盤每秒輸入輸出量)這個東西存在,所以在硬盤方面的優化直接被忽略了

下圖是阿里雲的各硬盤比對

仙士可博客

通俗來講,就是硬盤的每秒讀取文件的數量有限,舉個例子,你的程序從啓動到輸出include了100個文件,高效雲盤的iops是3000,代表着你的程序,每秒最多只可以訪問3000/100=30的併發數(只是理論數據,當大併發下,操作系統會適當的優化)

這就是laravel框架慢的原因,加載的文件太多了

 

優化方案?優化方案,在前幾個月,我的圈子有討論過,具體方案有以下幾種

1:將php框架,編譯成一個php文件,這樣一次請求下來,只有一個文件的輸出,大大的降低了硬盤的壓力,其實,tp3.2就已經有了這個功能,只是大家沒注意而已

http://document.thinkphp.cn/manual_3_2.html#app_compile

 

2:在swoole文檔中,韓大有說https://wiki.swoole.com/wiki/page/836.html

仙士可博客

 

在linux中,/dev/shm是映射的內存路徑,當框架啓動時,將框架代碼複製到該文件夾下面去運行(注意,內存,關機數據就會沒有,只能保存固定的業務代碼,不能保存業務數據)

windows也有內存盤,可以實現該操作

內存讀取速度非常快,所以並不用擔心磁盤I/O問題

 

三:服務器帶寬方面

服務器,帶寬是非常貴的,而網站的訪問都離不開帶寬,

下圖是我的博客一次請求下來的網頁大小

仙士可博客

一次請求就需要600kb,這相當於什麼呢?當我服務器帶寬只有1m(出口帶寬128kb/s)時,某次訪問進來,最少需要600/128約等於5秒的時間
相當於我服務器的秒併發量只有1/6......

何況這只是個博客,商城呢?假設商城的請求大小有1m,服務器帶寬有100M(12.8m/s)的話,秒併發量最多隻有12.8.....

這就是帶寬方面的限制了
當然,瀏覽器在一次請求之後,會智能的緩存頁面(js,css,圖片等靜態文件),這樣大大的節省了服務器帶寬,但是新進來的用戶,或者有用戶禁止了緩存頁面,就得請求這麼多數據了

至於優化方案,我的方案是上cdn(內容分發網絡)

它的大致原理是:將域名轉到他們的dns服務器,由他們進行管理域名的請求ip
例如:我的www.php20.cn,將dns轉移到百度雲cdn,那麼所有訪問www.php20.cn的請求都會被百度雲cdn接管

在在某個地區(百度雲cdn有多個地區的服務器,保證網站資源第一時間響應給用戶)第一次請求時,由於百度雲還沒有緩存,將會請求正確的服務器地址(百度雲cdn後臺域名解析),把數據返回給用戶端並緩存到百度雲cdn

當有緩存之後,百度雲將不再請求服務器的資源,將百度雲緩存的靜態數據,直接返回給用戶端,這就是cdn的作用了

所以,當網站上cdn之後,所有的靜態文件請求,cdn會幫助你緩存,並不消耗服務器的帶寬,大大的降低了帶寬的消耗,唯一需要返回的,也就是動態輸出的html文件了

 

四:使用nginx服務器

可能大家都知道,高併發下,都得使用nginx服務器,這是爲什麼呢?

咳咳,可以看以下文章https://www.cnblogs.com/yum777/p/6244935.html

 

五:php代碼邏輯

再好的架構,也會死在垃圾代碼上面,上面的一系列優化好了,那就是php方面了,主要注意以下幾點:

1:多使用php內置函數(內置函數寫在了php c底層,無需編譯,速度快)

2:判斷邏輯,(當有個獎品需要判斷是每週2萬個,每天最多5000個時,先判斷是否超過了每週限制,當真的超出了每週限制時,將節省每天判斷的時間)

3:避免循環運行sql語句(需要插入/更新多條數據時,請在循環外批量插入/更新)

http://www.php20.cn/article/sw/%E6%95%B0%E6%8D%AE/105  tp5好像已經內部實現了批量更新功能

4:儘量少的查詢數據庫

能一條語句查出的,儘量不要多條

例如,有個訂單表,有2種付款方式(payment_type=1,payment_type=2),對應1個付款金額的字段(total_money),

當你需要統計2種付款方式總計金額時,大多數人會根據payment_type=1,=2進行查詢2次數據,該怎麼優化呢?

可以使用mysql的判斷查詢:http://www.php20.cn/article/sw/%E5%88%A4%E6%96%AD/95

5:過濾掉惡意請求

通過驗證碼,手機短信等方法,將機器人排除在外,爲了避免惡意請求,可限制每秒請求次數不得超過10(普通人哪能點擊這麼快),當超過時,則系統底層拒絕響應,等到下一秒纔可以繼續請求

 

六:其他

本文一切都是理論知識,算是實踐過,但是併發量不大,所以大神們勿噴,互相學習,如果有錯誤或者有其他優化方案,希望大神們給小弟補補課,我很樂意接受批評

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章