1. 程式人生 > >mysql資料庫讀寫分離

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伺服器來訪問資料庫中的資料了