MySQL中間件之ProxySQL(10):讀寫分離方法論

返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.htmlhtml

 

1.不一樣類型的讀寫分離

數據庫中間件最基本的功能就是實現讀寫分離,ProxySQL固然也支持。並且ProxySQL支持的路由規則很是靈活,不只能夠實現最簡單的讀寫分離,還能夠將讀/寫都分散到多個不一樣的組,以及實現分庫sharding(分表sharding的規則比較難寫,但也能實現)。python

本文只描述經過規則制定的語句級讀寫分離,不討論經過 ip/port, client, username, schemaname 實現的讀寫分離。mysql

下面描述了ProxySQL能實現的常見讀寫分離類型。git

1.1 最簡單的讀寫分離

如圖。github

這種模式的讀寫分離,嚴格區分後端的master和slave節點,且slave節點必須設置選項read_only=1。在ProxySQL上,分兩個組,一個寫組HG=10,一個讀組HG=20。同時在ProxySQL上開啓monitor模塊的read_only監控功能,讓ProxySQL根據監控到的read_only值來自動調整節點放在HG=10(master會放進這個組)仍是HG=20(slave會放進這個組)。sql

這種模式的讀寫分離是最簡單的,只需在mysql_users表中設置用戶的默認路由組爲寫組HG=10,並在mysql_query_rules中加上兩條簡單的規則(一個select for update,一個select)便可。數據庫

例如,下面實現的就是這種讀寫分離模式。後端

mysql_replication_hostgroups: 
+------------------+------------------+----------+
| writer_hostgroup | reader_hostgroup | comment  |
+------------------+------------------+----------+
| 10               | 20               | cluster1 |
+------------------+------------------+----------+

mysql_servers: 
+--------------+----------+------+--------+--------+
| hostgroup_id | hostname | port | status | weight |
+--------------+----------+------+--------+--------+
| 10           | master   | 3306 | ONLINE | 1      |
| 20           | slave1   | 3306 | ONLINE | 1      |
| 20           | slave2   | 3306 | ONLINE | 1      |
+--------------+----------+------+--------+--------+

mysql_users: 
+----------+-------------------+
| username | default_hostgroup |
+----------+-------------------+
| root     | 10                |
+----------+-------------------+

mysql_query_rules: 
+---------+-----------------------+----------------------+
| rule_id | destination_hostgroup | match_digest         |
+---------+-----------------------+----------------------+
| 1       | 10                    | ^SELECT.*FOR UPDATE$ |
| 2       | 20                    | ^SELECT              |
+---------+-----------------------+----------------------+

這種讀寫分離模式,在環境較小時能知足絕大多數需求。可是需求複雜、環境較大時,這種模式就太過死板,由於一切都是monitor模塊控制的。緩存

1.2 多個讀組或寫組的分離模式

前面那種讀寫分離模式,是經過monitor模塊監控read_only來調整的,因此每個後端集羣必須只能分爲一個寫組,一個讀組。工具

但若是想要區分不一樣的select,並將不一樣的select路由到不一樣的節點上。例若有些查詢語句的開銷很是大,想讓它們獨佔一個節點/組,其它查詢共享一個節點/組,怎麼實現?

例如,下面這種模式。

看上去很是簡單。可是卻能適應各類需求。例如,後端作了分庫,對某庫的查詢要路由到特定的主機組(後文專門分析這種狀況)。

至於各個組機組是同一個主從集羣(下圖左邊),仍是互相獨立的主從集羣環境(下圖右邊),要看具體的需求,不過這種讀寫分離模式都能應付。

在實現這種模式時,前提是不能開啓monitor模塊的read_only監控功能,也不要設置 mysql_replication_hostgroup 表。

例如,下面的配置實現的是上圖左邊的結構:寫請求路由給HG=10,對test1庫的select語句路由給HG=20,其它select路由給HG=30。

mysql_servers: 
+--------------+----------+------+--------+--------+
| hostgroup_id | hostname | port | status | weight |
+--------------+----------+------+--------+--------+
| 10           | host1    | 3306 | ONLINE | 1      |
| 20           | host2    | 3306 | ONLINE | 1      |
| 30           | host3    | 3306 | ONLINE | 1      |
+--------------+----------+------+--------+--------+

mysql_users: 
+----------+-------------------+
| username | default_hostgroup |
+----------+-------------------+
| root     | 10                |
+----------+-------------------+

mysql_query_rules: 
+---------+-----------------------+----------------------+
| rule_id | destination_hostgroup | match_digest         |
+---------+-----------------------+----------------------+
| 1       | 10                    | ^SELECT.*FOR UPDATE$ |
| 2       | 20                    | ^SELECT.*test1\..*   |
| 3       | 30                    | ^SELECT              |
+---------+-----------------------+----------------------+

1.3 sharding後的讀寫分離

ProxySQL對sharding的支持比較弱,要寫sharding的路由規則真心以爲有點繁瑣。但不管如何,ProxySQL經過定製路由規則是能實現簡單的sharding的。這也算是讀寫分離的一種狀況。

以下圖,將課程所在庫分爲三個庫:"MySQL"、"python"和"Linux"。當查詢條件中的篩選條件是MySQL時,就路由給MySQL庫所在的主機組HG=20,篩選條件是Python時,就路由給HG=10,同理HG=30。

關於ProxySQL如何實現sharding的具體細節,我後面的文章會介紹。

2.找出須要特殊對待的SQL語句

有些SQL語句執行次數較多、性能開銷較大、執行時間較長等等,這幾類語句都須要特殊對待。例如,將它們路由到獨立的節點/主機組,或者爲它們開啓緩存功能。

詳細內容參見官方手冊裏的一篇文章,我已經把它翻譯過了:ProxySQL Read Write Split (HOWTO)

本文經過sysbench來模擬,以便爲官方手冊裏的這篇文章提供測試環境。固然,若是您會sysbench或其它性能測試工具,可無視。

1.首先建立測試數據庫sbtest。這裏我直接鏈接到後端的MySQL節點建立庫和表

mysqladmin -h192.168.100.22 -uroot -pP@ssword1! -P3306 create sbtest;

2.準備測試表,假設以2張表爲例,每一個表中10W行數據。填充完後,兩張表表名爲sbtest1和sbtest2

SYSBENCH=/usr/share/sysbench/
sysbench --mysql-host=192.168.100.22 \
         --mysql-port=3306 \
         --mysql-user=root \
         --mysql-password=P@ssword1! \
         $SYSBENCH/oltp_common.lua \
         --tables=1 \
         --table_size=100000 \
         prepare

3.sysbench鏈接到ProxySQL,作只讀測試。注意下面的選項--db-ps-mode必須設置爲disable,表示禁止ProxySQL使用prepare statement,目前ProxySQL還不支持對prepare語句的緩存。不過ProxySQL做者已經將此功能提上日程了

sysbench --threads=4 \
         --time=20 \
         --report-interval=5 \
         --mysql-host=127.0.0.1 \
         --mysql-port=6033 \
         --mysql-user=root \
         --mysql-password=P@ssword1! \
         --db-ps-mode=disable \
         $SYSBENCH/oltp_read_only.lua \
         --skip_trx=on \
         --tables=1 \
         --table_size=100000 \
         run

因爲這時候尚未設置sysbench的測試語句的路由,因此它們全都會路由到同一個主機組,例如默認的組。

4.查看stats_mysql_query_digest表,按照各類測試指標條件進行排序,例如按照總執行時間字段sum_time降序以便找出最耗時的語句,按照count_star降序排序找出執行次數最多的語句,還能夠按照平均執行時間降序等等。請參照上面列出的官方手冊文章

例如,此處按照sum_time降序排序:

Admin> SELECT count_star,sum_time,digest,digest_text 
       FROM stats_mysql_query_digest 
       ORDER BY sum_time DESC 
       LIMIT 4;
+------------+----------+--------------------+---------------------------------------------+
| count_star | sum_time | digest             | digest_text                                 |
+------------+----------+--------------------+---------------------------------------------+
| 72490      | 17732590 | 0x13781C1DBF001A0C | SELECT c FROM sbtest1 WHERE id=?            |
| 7249       | 9629225  | 0x704822A0F7D3CD60 | SELECT DISTINCT c FROM sbtest1 XXXXXXXXXXXX |
| 7249       | 6650716  | 0xADF3DDF2877EEAAF | SELECT c FROM sbtest1 WHERE id XXXXXXXXXXXX |
| 7249       | 3235986  | 0x7DD56217AF7A5197 | SELECT c FROM sbtest1 WHERE id yyyyyyyyyyyy |
+------------+----------+--------------------+---------------------------------------------+

5.對那些開銷大的語句,制定獨立的路由規則,並決定是否開啓查詢緩存以及緩存過時時長
6.寫好規則後進行測試

相關文章
相關標籤/搜索