总结了很久发现上面的仁兄给出的解答是最佳答案,从基础上面解决问题。
首先需要对 Database class 进行改造,注意我是直接改的 Kohana 核心文件,如果大家不方便或谨慎起见请覆写它们的子类:
1. 添加一个类的属性: Database::$slaves
2. 对 instance() 改写,加载 Database 中的配置项
3. 增加一个随机选择 slave 的配置项
abstract class Kohana_Database {
/**
* @var array slaves name
*/
public static $slaves = array();
public static function instance($name = NULL, array $config = NULL)
{
if ($name === NULL)
{
// Use the default instance name
$name = Database::$default;
}
if ( ! isset(Database::$instances[$name]))
{
if ($config === NULL)
{
// Load the configurations for all databases
$config = Kohana::config('database');
// Load the configuration for this database
$default = $config->$name;
}
if ( ! Database::$slaves)
{
foreach($config as $conf_name => $conf_database)
{
if (strpos($conf_name, 'slave') !== FALSE)
{
Database::$slaves[] = $conf_name;
}
}
}
if ( ! isset($default['type']))
{
throw new Exception('Database type not defined in [ '.$name.' ] configuration');
}
// Set the driver class name
$driver = 'Database_'.ucfirst($default['type']);
// Create the database connection instance
new $driver($name, $default);
}
return Database::$instances[$name];
}
public function select_slave()
{
// Get slave total
$slaves_total = count(Database::$slaves);
if ($slaves_total > 0)
{
// Get a random time
$time = round(microtime(true), 2) * 100;
$time = substr($time, strlen($time) - 2);
// Generate slave index
$handle = 100 / $slaves_total;
$choosen_index = floor($time/$handle);
// Get slave name
return Database::$slaves[$choosen_index];
}
return Database::$default;
}
}
4. 在 Kohana_Database_Mysql class 的 query 中判断执行 sql 的类型从而选择数据库源:
class Kohana_Database_MySQL extends Kohana_Database {
...
public function query($type, $sql, $as_object)
{
if ($type === Database::SELECT)
{
$name = $this->select_slave();
}
else
{
$name = Database::$default;
}
if ($this->_instance != $name)
{
$this->_connection = NULL;
$this->_instance = $name;
$this->_config = Kohana::config('database')->$name;
}
// 下面是原来的内容...
}
5. Database 配置文件,对于 slave 的数据源都要以 'slave‘ 为开头,后面可以随意,比如: slave, slave1, slave2...
return array ( 'default' => array ( 'type' => 'mysql', 'connection' => array( 'hostname' => 'localhost', 'database' => 'master', 'username' => 'root', 'password' => '', 'persistent' => FALSE, ), 'table_prefix' => '', 'charset' => 'utf8', 'caching' => FALSE, 'profiling' => TRUE, ), 'slave' => array ( 'type' => 'mysql', 'connection' => array( 'hostname' => 'localhost', 'database' => 'slave01', 'username' => 'root', 'password' => '', 'persistent' => FALSE, ), 'table_prefix' => '', 'charset' => 'utf8', 'caching' => FALSE, 'profiling' => TRUE, ), );
完工!


Post new reply