mysql讀寫分離在項目實踐中的應用

語言: CN / TW / HK

工程背景介紹:我們開發了一個萬能接口,用户通過這個接口中傳入數據,我們拿到數據進行復雜的邏輯處理然後再將數據各種匹配展示分發等操作,處理的流程相當龐大,接口中我們只保留了接收數據和返回一個本次請求的id的操作,其餘操作都是異步到其他程序中處理的。

返回id的操作是需要和數據庫進行兩次連接,一次讀庫得到最新的id 然後把id更新到數據庫。

項目出現問題:我們以為自己的程序就像上圖中的那樣運行,一次請求,讀庫,寫庫,返回id,其餘異步處理。但是沒有考慮高併發,強壓力寫的性能問題,在高併發下,多個接口線程同事訪問數據庫,這樣的情況會出現併發同步的問題,當然這點我們是考慮到了 ,使用線程鎖可避免數據的幻讀,重複讀等。可一旦這樣大量的接口線程堆積,很快服務器cpu將扛不住發生宕機!

那如果不試用線程同步鎖呢,很明顯不只是數據的錯亂問題將發生,數據庫在極大線程的訪問壓力下也將抗不住,cpu使用率達到85%!程序面臨着癱瘓的風險。

解決方式:

1.數據庫集羣?

好處:增加數據庫服務器,壓力隨之分攤到幾個服務器中,減小數據庫壓力

壞處:硬件成本大 數據庫主從問題 哈希一致性問題 單點故障問題

2.接口服務器集羣

好處:訪問壓力被分攤到幾個服務器中 線程的堆積問題得到有效解決

壞處:硬件成本大 單點故障問題 nignx負載均衡服務器的搭建 操作複雜

 

以上兩種方案都是增加硬件成本,加大了開發難度,難以真正實施

終極解決方案:讀寫分離的應用!

好處:硬件成本不變 釋放了數據庫壓力 再也不用擔心數據庫和服務器壓力了

壞處:無

 

實現思路:

1.對讀庫操作解耦合,增加緩存服務ecache(也可以是其它如redis),讀不再直接面對數據庫,只有緩存中沒有數據時才把數據庫中的數據讀寫到緩存之中,這樣數據庫的讀壓力完全被釋放!

 

2.對寫數據庫進行異步操作,在更新數據庫操作中增加消息中間件rabbitmq(也可以是其它如activemq,spring對前者支持較好),我們將更新後的id寫入到rabbitmq中,單線程消費mq到數據庫,由於此時跟新後的id已經返回給客户,寫庫的操作並不需要高時效性。這樣數據庫的寫壓力也完全被釋放!

這個時候我們來看看整個操作,讀寫均不再直接面對數據庫,但是數據庫中的數據依然沒有錯亂,緩存的操作速度極快,接口服務器也不再有很多的線程擠壓,我們在硬件成本不變的情況下解決了數據庫和服務器壓力過大,可以説是一種完美的解決方案

至此,壓力的問題成功解決,當然問題的解決並非是一撮而就的,這裏還有着一些其它的問題,比如分佈式事務的解決,這裏不再一一贅述,後面我們找機會仔聊聊這些分佈式服務的經典問題!

以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,更多PHP大廠PDF面試文檔,PHP進階架構視頻資料,PHP精彩好文免費獲取可以關注公眾號:PHP開源社區,或者訪問:

2021金三銀四大廠面試真題集錦,必看!

四年精華PHP技術文章整理合集——PHP框架篇

四年精華PHP技術文合集——微服務架構篇

四年精華PHP技術文合集——分佈式架構篇

四年精華PHP技術文合集——高併發場景篇

四年精華PHP技術文章整理合集——數據庫篇