问题
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