mysql資料庫讀寫分離
(1)、基本的理論知識:
首先,要實現mysql的讀寫分離,可以使用mysql的主(master)從(slave)複製(Replication)來實現:
主(master)庫只提供寫資料的服務,而從(slave)庫只提供讀資料的服務。
什麼是主從複製?
簡單來說,就是主(master)庫把對資料改動的操作儲存到一個檔案裡面,而從(slave)庫會隔一個時間間隔根據這個檔案更新自己的資料
(所以讀到的資料是有延遲的,這個延遲取決於從(slave)庫設定的時間間隔)
(2)、實際操作步驟:
使用以下兩臺電腦:
主庫(master)的IP:192.168.1.65
從庫(slave)的IP:192.168.1.49 //這兩個IP是我摘自網上的,用的時候用自己資料庫的IP就好,DOS命令ipconfig就能看本機IP
兩臺電腦都安裝了MySQL5.7 //個人感覺版本沒什麼影響吧,我看的教程裝的是5.5的版本,我自己在5.7的版本上也能夠實現
然後把兩臺電腦的mysql服務停掉
A、開啟主庫(master)的mysql安裝目錄,開啟配置檔案my.ini //這裡開啟的路徑是對於5.5版本來說的,對於5.7版本的ini路徑在C:\ProgramData\MySQL\MySQL Server 5.7,根據自己的電腦進行查詢此路徑,還有一點,網上有許多教程說的是開啟cnf檔案,其實這個是對於Linux來說的,windows下的檔案是ini。
在[mysqld]的後面新增如下程式碼:
log-bin=mysql-bin #slave會基於此log-bin來做replication
binlog-do-db=test #用於master-slave的具體資料庫
binlog_ignore_db=mysql #不用於master-slave的具體資料庫
binlog_ignore_db=information_schema #和binlog-do-db一樣,可以設定多個
//這裡也需要說一下,我看的教程上,有新增
server-id=1 #master的標示
這一行程式碼,其實是多餘的(因為接下來的步驟中會提示這個錯誤,我也是被這個絆了好久才改過來)因為ini檔案中有server-id=1這個程式碼,只需要保持不變即可,無需修改。
開啟主庫(master)的mysql服務,進入mysql的命令列,輸入如下程式碼:
Showmaster status\G;
D、記錄一下file(日誌檔案)和position,然後分別給兩個從庫複製許可權
grant replication slave on *.* to'slave'@'192.168.1.%' identified by '123456';
其中的’slave’為登入賬號,’123456’為密碼,’192.168.1.%’為從庫的IP(這裡偷懶使用了萬用字元~) //我在做的時候提示了一個警告,但是個人覺得沒啥問題,所以不用管就行
E、開啟從庫1的mysql安裝目錄,開啟配置檔案my.ini,在[mysqld]的後面新增如下程式碼:
log-bin=mysql-bin#slave會基於此log-bin來做replication
replicate-do-db=test#用於master-slave的具體資料庫
//這裡就要在說明一下,之前說過ini檔案中本身就有server-id,所以這裡也不需要新增,只需要找到對應的server-id把它的值改大就行,=2就可以,如果還有做別的從庫,只要保證從庫之間不能有一樣即可。
儲存後啟動從庫的mysql服務,進入mysql的命令列,輸入如下程式碼:
先停止它的slave:
stopslave;
再改變它的master:
change master tomaster_host='192.168.1.65',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='mysql-bin.000040',
master_log_pos=107; //這裡的資料和圖片我也是摘自別人的教程,大家要靈活的區結合自己的資料庫進行修改
再啟動它的slave;
startslave;
然後再輸入如下程式碼,檢查是否成功:
Showslave status\G;
如果看到上面這些的,那就沒問題了~
當然你也可以在主庫(master)上做修改資料的操作,看看從庫會不會更新~(注意:從庫(slave)的資料庫需要自己手動建立)
G.到這裡,mysql的讀寫分離就完成了~
但是這樣不夠方便,因為我們寫資料時需要連線主庫,而讀資料時需要連線從庫。在連線從庫時,不能負載均衡。
這時候就要靠神器Amoeba了~
它就像一箇中轉站,將所有的寫請求分配給主庫,讀請求分配給從庫,並且在從庫之間實現負載均衡,丟個官網的圖~
H.配置Amoeba伺服器:
這裡最好找另外的一臺電腦充當Amoeba伺服器:192.168.1.62
博主使用的版本是amoeba-mysql-3.0.5-RC-distribution,連結如下:
下載連結
下載完成後解壓,開啟conf資料夾,配置amoeba.xml和dbServer.xml:
amoeba.xml:
<proxy>
<!-- service class must implements com.meidusa.amoeba.service.Service -->
<service class="com.meidusa.amoeba.mysql.server.MySQLService" name="Amoeba for Mysql">
<!-- amoeba代理埠號 -->
<property name="port">8066</property>
<!-- amoeba伺服器IP地址 -->
<property name="ipAddress">192.168.1.62</property>
<property name="connectionFactory">
<bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">
<property name="sendBufferSize">128</property>
<property name="receiveBufferSize">64</property>
</bean>
</property>
<property name="authenticateProvider">
<bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
<!-- amoeba伺服器使用者名稱 -->
<property name="user">amoeba</property>
<!-- amoeba伺服器密碼 -->
<property name="password">123456</property>
<property name="filter">
<bean class="com.meidusa.toolkit.net.authenticate.server.IPAccessController">
<property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
</bean>
</property>
</bean>
</property>
</service>
<runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">
<!-- proxy server client process thread size -->
<property name="executeThreadSize">128</property>
<!-- per connection cache prepared statement size -->
<property name="statementCacheSize">500</property>
<!-- default charset -->
<property name="serverCharset">utf8</property>
<!-- query timeout( default: 60 second , TimeUnit:second) -->
<property name="queryTimeout">60</property>
</runtime>
</proxy>
<!--
Each ConnectionManager will start as thread
manager responsible for the Connection IO read , Death Detection
-->
<connectionmanagerlist>
<connectionmanager class="com.meidusa.toolkit.net.MultiConnectionManagerWrapper" name="defaultManager">
<property name="subManagerClassName">com.meidusa.toolkit.net.AuthingableConnectionManager</property>
</connectionmanager>
</connectionmanagerlist>
<!-- default using file loader -->
<dbserverloader class="com.meidusa.amoeba.context.DBServerConfigFileLoader">
<property name="configFile">${amoeba.home}/conf/dbServers.xml</property>
</dbserverloader>
<queryrouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
<property name="ruleLoader">
<bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
<property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
<property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
</bean>
</property>
<property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
<property name="LRUMapSize">1500</property>
<!-- 設定預設節點-->
<property name="defaultPool">master</property>
<!-- 設定可寫節點-->
<property name="writePool">master</property>
<!-- 設定只讀節點-->
<property name="readPool"> multiPool </property>
<property name="needParse">true</property>
</queryrouter>
</amoeba:configuration>
dbServers.xml:
<!--
Each dbServer needs to be configured into a Pool,
If you need to configure multiple dbServer with load balancing that can be simplified by the following configuration:
add attribute with name virtual = "true" in dbServer, but the configuration does not allow the element with name factoryConfig
such as 'multiPool' dbServer
-->
<dbserver abstractive="true" name="abstractServer">
<factoryconfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="connectionManager">${defaultManager}</property>
<property name="sendBufferSize">64</property>
<property name="receiveBufferSize">128</property>
<!-- mysql port(資料庫埠) -->
<property name="port">3306</property>
<!-- mysql schema(資料庫名稱,資料庫中必須存在此資料庫) -->
<property name="schema">test</property>
<!-- mysql user(控制資料庫使用者名稱) -->
<property name="user">proxy</property>
<!-- mysql password(控制資料庫密碼) -->
<property name="password">123456</property>
</factoryconfig>
<poolconfig class="com.meidusa.toolkit.common.poolable.PoolableObjectPool">
<property name="maxActive">500</property>
<property name="maxIdle">500</property>
<property name="minIdle">1</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testOnReturn">true</property>
<property name="testWhileIdle">true</property>
</poolconfig>
</dbserver>
<!-- 主資料庫配置 -->
<dbserver name="master" parent="abstractServer">
<factoryconfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.1.65</property>
</factoryconfig>
</dbserver>
<!-- 從資料庫配置 -->
<dbserver name="slave1" parent="abstractServer">
<factoryconfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.1.64</property>
</factoryconfig>
</dbserver>
<dbserver name="slave2" parent="abstractServer">
<factoryconfig>
<!-- mysql ip -->
<property name="ipAddress">192.168.1.49</property>
</factoryconfig>
</dbserver>
<!-- 定義虛擬伺服器組,即只讀池 -->
<dbserver name="multiPool" virtual="true">
<poolconfig class="com.meidusa.amoeba.server.MultipleServerPool">
<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
<property name="loadbalance">1</property>
<!-- Separated by commas,such as: server1,server2,server1 -->
<property name="poolNames">slave1,slave2</property>
</poolconfig>
</dbserver>
</amoeba:dbservers>
I.給Amoeba授權:
分別到主庫、從庫1、從庫2的mysql控制檯下給Amoeba伺服器授權,程式碼如下:
1 |
grant all on *.* to 'proxy'@'192.168.1.62' identified by '123456'; |
這裡的賬號和密碼必須和dbServers.xml中的配置一毛一樣:
然後使用這個連線對資料庫test做資料修改操作,再到主庫從庫上面檢視是否有同步修改,如果有,那就完成了讀寫分離~
如果想看看有沒有實現負載均衡,可以開啟Amoeba安裝目錄的logs/root.log檢視查詢日誌。
然後我們的應用就可以通過連線Amoeba伺服器來訪問資料庫中的資料了