在app/config/database.php中配置如下:
'redis' => array(
'cluster' => true,
'default' => array(
'host' => '172.21.107.247',
'port' => 6379,
),
'redis1' => array(
'host' => '172.21.107.248',
'port' => 6379,
),
其中cluster選擇為true,接下來就可以作集群使用了;
如果把session的driver設置為redis,則可以使用其集群功能了:
我們來看下session的實現,當我們在代碼中這樣寫:
Session::put('test', 124);
實際的執行流程是這樣的:
Illuminate\Support\Facades\Session
Illuminate\Support\Facades\Facade
Illuminate\Session\Facade::app['session']->put
Illuminate\Session\Facade::app['session']為Illuminate\Session\SessionManager
Illuminate\Support\Manager::__call
Session會根據返回創建driver
$this->app['config']['session.driver']
即配置文件中配置的,這里我們配置為redis
Illuminate\Session\SessionManager::Illuminate\Session\SessionManager
最終由Illuminate\Session\Store來負責put的調用
而Store類負責存儲的類是Illuminate\Session\CacheBasedSessionHandler
后者又將請求轉發給$this->app['cache']->driver($driver)
……
經過一系列代碼追查,存儲類為Predis\Client\Database,看其構造函數:
public function __construct(array $servers = array())
{
if (isset($servers['cluster']) && $servers['cluster'])
{
$this->clients = $this->createAggregateClient($servers);
}
else
{
$this->clients = $this->createSingleClients($servers);
}
}
如果設置為集群,則調用createAggregateClient方法
protected function createAggregateClient(array $servers)
{
$servers = array_except($servers, array('cluster'));
return array('default' => new Client(array_values($servers)));
}
這里會把所有服務器放在default組中
實際存數據的類是Predis\Client,這里有根據配置創建服務器的代碼,具體可以自己看下;
Predis\Cluster\PredisClusterHashStrategy類負責計算key的hash,關鍵函數:
getHash
getKeyFromFirstArgument
而Predis\Cluster\Distribution\HashRing負責服務器環的維護,關鍵函數
addNodeToRing
get
hash
大概原理是這樣,如執行以下redis命令
get ok
會將ok作crc32運算得到一個hash值
所有服務器按一定算法放到一個長度默認為128的數組中,每個服務器在其中占幾項,由以下決定:
權重/總權重*總的服務器數量*128,可參考Predis\Cluster\Distribution\HashRing::addNodeToRing方法
每一項的hash值是按服務器ip:端口的格式,作crc32計算的
protected function addNodeToRing(&$ring, $node, $totalNodes, $replicas, $weightRatio)
{
$nodeObject = $node['object'];
$nodeHash = $this->getNodeHash($nodeObject);
$replicas = (int) round($weightRatio * $totalNodes * $replicas);
for ($i = 0; $i < $replicas; $i++) {
$key = crc32("$nodeHash:$i");
$ring[$key] = $nodeObject;
}
}
key的hash值也有了,服務器環也計算好了,剩下的就是查找了,二分法能較快的查找相應的服務器節點