Can magento use multiple MySQL slaves?

こ雲淡風輕ζ 提交于 2019-12-07 04:50:16

问题


The following is part of my config for using a single slave.

<default_read>                 
    <connection>               
        <use/>                 
        <host><![CDATA[slavedb1.amazonaws.com]]></host>
        <username><![CDATA[username]]></username>
        <password><![CDATA[Password]]></password>
        <dbname><![CDATA[shop]]></dbname>
        <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
        <model><![CDATA[mysql4]]></model>
        <type><![CDATA[pdo_mysql]]></type>
        <pdoType><![CDATA[]]></pdoType>
        <active>1</active>  
    </connection>
</default_read>

However, I want to use multiple slaves. Is this possible with Magento?

To clarify, I have already got a single master/slave setup working with Magento already. I want to add another slave so that I have two slaves. I am wondering how the config will change to make use of this second slave.


回答1:


As far as I am aware it is not possible to use multiple slaves with Magento.

If you are using AWS you could maybe use larger instances for your master/slave setup?




回答2:


Given your comments above and assuming you have correct replication setup of your Databases.

Solution :-

- Step 1:

In File

app/etc/config.xml

Find "core_read" Closing tag

<resources>
    ....
    <core_read>
            <connection>
                <use>default_read</use>
            </connection>
        </core_read>
    ....
</resources>

Add After the closing tag ( as many as databases you want to use ) it should look like below:

<resources>
    ....
        <core_read>
            <connection>
                <use>default_read</use>
            </connection>
        </core_read>
        <slave_db_1>
            <connection>
                <use>slave_one_db</use>
            </connection>
        </slave_db_1>
        <slave_db_2>
            <connection>
                <use>slave_two_db</use>
            </connection>
        </slave_db_2>
    ....
</resources>

- Step 2:

And Add the new connection in your apt/etc/local.xml after ( "/default_setup>" closing tag )

<resources>
    ....            
        <slave_one_db>
            <connection>
                <host><![CDATA[localhost]]></host>
                <username><![CDATA[slave_one_db_user]]></username>
                <password><![CDATA[slave_one_db_password]]></password>
                <dbname><![CDATA[slave_db_one_name]]></dbname>
                <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
                <model><![CDATA[mysql4]]></model>
                <type><![CDATA[pdo_mysql]]></type>
                <pdoType><![CDATA[]]></pdoType>
                <active>1</active>
            </connection>
        </slave_one_db>
        <slave_two_db>
            <connection>
                <host><![CDATA[localhost]]></host>
                <username><![CDATA[slave_tow_db_user]]></username>
                <password><![CDATA[slave_tow_db_password]]></password>
                <dbname><![CDATA[slave_db_one_tow]]></dbname>
                <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
                <model><![CDATA[mysql4]]></model>
                <type><![CDATA[pdo_mysql]]></type>
                <pdoType><![CDATA[]]></pdoType>
                <active>1</active>
            </connection>
        </slave_two_db>
    ....
</resources>

- Step 3:

Copy the File From " app/code/core/Mage/Core/Model/Resource.php " == TO ==> " app/code/local/Mage/Core/Model/Resource.php "

1- Find protected $_mappedTableNames;

2- Add this method below :

public function getSlaveDb()
{
    $prefix = 'slave_db_'; // prefix for the slaves databased in the xml file
    $cookieExpireTime = 1209600; // 2 weeks Cookie ( database selection ) expire time
    $dbArray = array(1,2); // All slaves Db in-case the cookie has invalid value
    $slaveDb = array_rand( array_flip($dbArray),1 ); // How to alternate between databases ( in this demo i just use 2 database ) adjust the selection of the database to fit hoe many database you want to use !
    if(!isset($_COOKIE['read_db']) || !in_array($_COOKIE['read_db'],$dbArray)) // Check for the cookie values
    {
        setcookie("read_db", $slaveDb, time()+$cookieExpireTime); // set the current database to the user in cookie so next time user use same connection to database ! to avoid jumping or hopping on different databases in short time
    }else{
        $slaveDb = $_COOKIE['read_db']; // return the database selected if the user has it in the cookies
    }
    return $prefix.$slaveDb;
}

3- Modify the method " public function getConnection($name) " to Look like below :

public function getConnection($name)
{
    if($name =='core_read') // Only applied for READ Connections !!!
    {
        $name = $this->getSlaveDb(); // change the name of the connection to the one we get from our main method
    }
    //....... Leave the rest of the function as it is !!
}

This will allow you to use as many as databases you specify in the XML and PHP CODE for core_read connection and the default_setup connection for all other connections in magento ( core_write, core_setup )

Hope this solve your problem.




回答3:


You can get your solution over here. Need help writing to multiple database through single Magento installation

I think this is what is required




回答4:


From my experience, the best setup would be to use a Load Balancer to spread reads across the multiple slaves.

The reason behind this , is that with a Load Balancer, if any Slave dies , there will be very little seen from Magento itself (the customers). If you use Mageneto's method of multiple slaves, then if one slave is down, a query will need to timeout before it can be sent to another node (customers will see lag on the frontend).

I have used Stingray/Zeus (Commercial Product) but I've also seen HAProxy used for this.




回答5:


Maybe Someone is reading this thread again:

The Codesnippets written by Meabed are still valid, if you want to use single master with multiple slaves in magento. magento's default setup, doesnt support multiple slaves.

First take a look at app\code\core\Mage\Core\Model\Resource.php -> function getConnection( $name )

This function returns the correct connection for de current query. E.g. Master Connection for Write Queries and Slave Connection for Read Queries.

The passed variable $name, defines which Connection should be used. This Code ( about Line 95 )

$connConfig = Mage::getConfig()->getResourceConnectionConfig($name);

returns the Read or Write Connection.

So there are only a few modifications needed, to work with multiple slaves. First Modify your local.xml

<default_setup>
    <connection>
        <host><![CDATA[127.0.0.1]]></host>
        <username><![CDATA[root]]></username>
        <password><![CDATA[]]></password>
        <dbname><![CDATA[yourdatabase]]></dbname>
        <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
        <model><![CDATA[mysql4]]></model>
        <type><![CDATA[pdo_mysql]]></type>
        <pdoType><![CDATA[]]></pdoType>
        <active>1</active>
    </connection>
</default_setup>    

<slave_db_one>
    <connection>
        <use />
        <host><![CDATA[127.0.0.3]]></host>
        <username><![CDATA[root]]></username>
        <password><![CDATA[]]></password>
        <dbname><![CDATA[yourdatabase]]></dbname>
        <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
        <model><![CDATA[mysql4]]></model>
        <type><![CDATA[pdo_mysql]]></type>
        <pdoType><![CDATA[]]></pdoType>
        <active>1</active>
    </connection>
</slave_db_one>                          

<slave_db_two>
    <connection>
        <use />
        <host><![CDATA[127.0.02]]></host>
        <username><![CDATA[root]]></username>
        <password><![CDATA[]]></password>
        <dbname><![CDATA[yourdatabase]]></dbname>
        <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
        <model><![CDATA[mysql4]]></model>
        <type><![CDATA[pdo_mysql]]></type>
        <pdoType><![CDATA[]]></pdoType>
        <active>1</active>
    </connection>
</slave_db_two>     

So only add two more nodes after the closing tag of your default connection.

As "Meabed" descripted some days ago, you only need to modify the variable "$name" in a way to get the correct connection node. e.g. put this at the top of the method "getConnection"

if ( $name == 'core_read' ) {
$name   = 'slave_db_two';

}

You can also write an function and return random another connection name.

public function getRunningSlave() {
$input = array("slave_db_one", "slave_db_two");
$rand_keys = array_rand($input, 2);
return $input[$rand_keys[0]];

}

Another way, check with SHOW SLAVE STATUS the state of the slave, if the slave is currently offline, get another connection or return master connection for reading queries.

cheers



来源:https://stackoverflow.com/questions/18636169/can-magento-use-multiple-mysql-slaves

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!