天天看點

mysql:解決高并發通路瓶頸問題

一、緩存式的應用程式架構:

在應用層和db層之間加一層cache層,主要目的:減少資料庫讀取負擔,提高資料讀取速度。cache存取的媒介是記憶體,可以考慮采用分布式的cache層,這樣更容易破除記憶體容量的限制,同時增加了靈活性。遊戲多采用redis、Memcached這類。

二、實作MySQL資料庫異步查詢實作:

通常情況下在PHP中MySQL查詢是串行的,如果能實作MySQL查詢的異步化,就能實作多條SQL語句同時執行,這樣就能大大地縮短MySQL查詢的耗時,提高資料庫查詢的效率。目前MySQL的異步查詢隻在MySQLi擴充提供,查詢方法分别是:

1、使用MYSQLI_ASYNC模式執行mysqli::query

2、擷取異步查詢結果:mysqli::reap_async_query

使用mysql異步查詢,需要使用mysqlnd作為PHP的MySQL資料庫驅動。

使用MySQL異步查詢,因為需要給所有查詢都建立一個新的連接配接,而MySQL服務端會為每個連接配接建立一個單獨的線程進行處理,如果建立的線程過多,則會造成線程切換引起系統負載過高。Swoole中的異步MySQL其原理是通過MYSQLI_ASYNC模式查詢,然後擷取mysql連接配接的socket,加入到epoll事件循環中,當資料庫傳回結果時會回調指定函數,這個過程是完全異步非阻塞的。

三、MySQL主從讀寫分離(選擇高效操作的表存儲格式):

當資料庫的寫壓力增加,cache層(如Memcached)隻能緩解資料庫的讀取壓力。讀寫集中在一個資料庫上讓資料庫不堪重負。使用主從複制技術(master-slave模式)來達到讀寫分離,以提高讀寫性能和讀庫的可擴充性。讀寫分離就是隻在主伺服器上寫,隻在從伺服器上讀,基本原理是讓主資料庫處理事務性查詢,而從資料庫處理select查詢,資料庫複制被用于把事務性查詢(增删改)導緻的改變更新同步到叢集中的從資料庫。

MySQL讀寫分離提升系統性能:

1、主從隻負責各自的讀和寫,極大程度緩解X鎖和S鎖争用。

2、slave可以配置MyISAM引擎,提升查詢性能以及節約系統開銷。

3、master直接寫是并發的,slave通過主庫發送來的binlog恢複資料是異步的。

4、slave可以單獨設定一些參數來提升其讀的性能。

5、增加備援,提高可用性。

實作主從分離可以使用MySQL中間件如:Atlas

四、分表分庫(分布式):

在cache層的高速緩存,MySQL的主從複制,讀寫分離的基礎上,這時MySQL主庫的寫壓力開始出現瓶頸,而資料量的持續猛增,由于MyISAM使用表鎖,在高并發下會出現嚴重的鎖問題,大量的高并發MySQL應用開始使用InnoDB引擎代替MyISAM。采用Master-Slave複制模式的MySQL架構,隻能對資料庫的讀進行擴充,而對資料的寫操作還是集中在Master上。這時需要對資料庫的吞吐能力進一步地擴充,以滿足高并發通路與海量資料存儲的需求。

對于通路極為頻繁且資料量巨大的單表來說,首先要做的是減少單表的記錄條數,以便減少資料查詢所需的時間,提高資料庫的吞吐,這就是所謂的分表【水準拆分】。在分表之前,首先需要選擇适當的分表政策,使得資料能夠較為均衡地分布到多張表中,并且不影響正常的查詢。

分表能夠解決單表資料量過大帶來的查詢效率下降的問題,但是卻無法給資料庫的并發處理能力帶來質的提升。面對高并發的讀寫通路,當資料庫master伺服器無法承載寫操作壓力時,不管如何擴充Slave伺服器都是沒有意義的,對資料庫進行拆分,進而提高資料庫寫入能力,即分庫【垂直拆分】。

分庫分表的理由政策如下:

1、中間變量=user_id % ( 庫數量 * 每個庫的表數量 )

2、庫=取整(中間變量 / 每個庫的表數量)

3、表=中間變量 % 每個庫的表數量

資料庫經過業務拆分及分庫分表,雖然查詢性能和并發處理能力提高了。但是原本跨表的事務上升為分布式事務;由于記錄被切分到不同的庫和不同的表中,難以進行多表關聯查詢,并且不能不指定路由字段對資料進行查詢。且分庫分表後需要進一步對系統進行擴容(路由政策變更)将變得非常不友善,需要重新進行資料遷移。

五、資料操作

資料庫加索引

選擇利于高效查詢的資料類型

1.多用數字運算,少用字元串運算

2.當較小類型夠用時,就不用較大類型

3.把資料列聲明成NOT NULL

4.考慮使用ENUM

5.整理表碎片

6.使用合成索引

Innodb與Myisam引擎的差別與應用場景

1. 差別:

(1)事務處理:

MyISAM是非事務安全型的,而InnoDB是事務安全型的(支援事務處理等進階處理);

(2)鎖機制不同:

MyISAM是表級鎖,而InnoDB是行級鎖;

(3)select ,update ,insert ,delete 操作:

MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇 InnoDB:如果你的資料執行大量的INSERT或UPDATE,出于性能方面的考慮,應該使用InnoDB表

(4)查詢表的行數不同:

MyISAM:select count(*) from table,MyISAM隻要簡單的讀出儲存好的行數,注意的是,當count(*)語句包含    where條件時,兩種表的操作是一樣的 InnoDB : InnoDB 中不儲存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行 (5)外鍵支援: mysiam表不支援外鍵,而InnoDB支援

2. 為什麼MyISAM會比Innodb 的查詢速度快。

INNODB在做SELECT的時候,要維護的東西比MYISAM引擎多很多;

1)資料塊,INNODB要緩存,MYISAM隻緩存索引塊,  這中間還有換進換出的減少; 

2)innodb尋址要映射到塊,再到行,MYISAM 記錄的直接是檔案的OFFSET,定位比INNODB要快

3)INNODB還需要維護MVCC一緻;雖然你的場景沒有,但他還是需要去檢查和維護 MVCC ( Multi-Version Concurrency Control )多版本并發控制  3. 應用場景

MyISAM适合:(1)做很多count 的計算;(2)插入不頻繁,查詢非常頻繁;(3)沒有事務。

InnoDB适合:(1)可靠性要求比較高,或者要求事務;(2)表更新和查詢都相當的頻繁,并且行鎖定的機會比較大的情況。

參考:

https://blog.csdn.net/u010832551/article/details/77836681

https://www.cnblogs.com/changna1314/p/6878900.html

轉載于:https://www.cnblogs.com/losophy/p/9232292.html