深入了解 memcache

QQ 群名 称 : cbsi 技术交流群
群   号 :3940869




               华多网络科技有限公司
提纲

•   memcache 的内存管理机制

•   addServer 的工作原理

•   memcache 的分布式策略

•   memcache 高级应用案例

•   memcache 监控

•   memcache 监控工具

•   参考 addServer 思路写 mysql 分布式连接类实现 mysql 集群
1 , memcache 的内存管理机制

1.1 内存分配机制

1.2 缓存删除与失效机制

1.3 内存不足时的 LRU 失效机制
1.1 内存分配机制

1.1.1 Page 为内存分配的最小单位。

1.1.2 Slabs 划分数据空间。

1.1.3 问题:
为什么采用这样的内存分配方式,而不是使用某个 key 的时候再 malloc ,用完 free 。
1.1.1 Page 为 内存分配的最小单 位。

1 , Memcached 的内存分配以 page 为单位,默认情况下一个 page 是 1M 。

2 , page 的申请是根据 slab 区域来申请。比如如果 slab1 的存放内存单位是 1-
   104 bytes ,那 slab1 申请的 page 将以 104byte 为单位来划分成 10082 个
   单位。
1.1.2 Slabs 划 分数据空间 。

1 , 根据 Slabs 划分数据空间
 Memcached 并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列 slabs ,
 每个 slab 只负责一定范围内的数据存储。如下图,每个 slab 只存储大于其上一个 slab 的 size 并小
 于或者等于自己最大 size 的数据。例如: slab 3 只存储大小介于 137 到 224 bytes 的数据。如
 果一个数据大小为 230byte 将被分配到 slab 4 中。从下图可以看出,每个 slab 负责的空间其实是
 不等的, memcached 默认情况下下一个 slab 的最大值为前一个的 1.25 倍。
1.1.2 Slabs 划 分数据空间 。

1 , Chunk 才是存放缓存数据的单位。
 Chunk 是一系列固定的内存空间,这个大小就是管理它的 slab 的最大存放大小。例如: slab 1 的
 所有 chunk 都是 104byte 。
1.1.3 问题

为什么采用这样的内存分配方式,而不是使用某个 key 的时候再 malloc ,用完
  free 。
1.1.3 问题

为什么采用这样的内存分配方式,而不是使用某个 key 的时候再 malloc ,用完
  free 。




答案:
1 ,提高性能。
2 ,预防产生内存碎片。
1.2 缓 存删 除与失效机制

1 ,缓存删除:
  放入一个删除队列 , 表明它不可以通过 get 命令获取到值 , 但是同时 add 和 replace 命令也会失
 败 ( 无论如何 set 命令都会成功 ). 在这段时间过去后 , 元素最终被从服务端内存中 free 删除掉。


2 ,缓存过期:
 memcache 使用的是一种 Lazy Expiration 策略,自己不会监控存入的 key/value 是否过期,而是
 在获取 key 值时查看记录的时间戳,检查 key/value 对空间市口过去。


3 ,问题:
 1 , memcache 为什么不主动回收过期内存?
1.2 缓 存删 除与失效机制

1 ,缓存删除:
  放入一个删除队列 , 表明它不可以通过 get 命令获取到值 , 但是同时 add 和 replace 命令也会失
 败 ( 无论如何 set 命令都会成功 ). 在这段时间过去后 , 元素最终被从服务端内存中 free 删除掉。


2 ,缓存过期:
 memcache 使用的是一种 Lazy Expiration 策略,自己不会监控存入的 key/value 是否过期,而是
 在获取 key 值时查看记录的时间戳,检查 key/value 对空间市口过去。


3 ,问题:
 1 , memcache 为什么不主动回收过期内存?

 答案:一切为了性能,大家使用 memcache 就是因为它的高性能。内存过期检测会浪费大量 CPU
 资源。
1.3 内存不足时 的 LRU 失效机制

1 , LRU 机制:
   当空间被占满时, memcache 就会使用 LRU 算法来分配空间,删除最近少使用的 key/value 对,
  将其空间分配给新的 key/value 对。


2 ,为了性能,还是不能让 memcache 内存不够
   由于使用 LRU 算法分配空间会消耗 CPU 资源,为了性能,最好让你的 memcache 保存足够的空
  间。
2 , addServer 的工作原理

PHP 手册的介绍:
 Memcached::addServer() 增加指定服务器到服务器池中。此时不会建立与服务端的连接, 但是,
 如果你使用一致性 key 分布选项( Memcached::DISTRIBUTION_CONSISTENT 或
 Memcached::OPT_LIBKETAMA_COMPATIBLE ),一些内部的数据结构将会被更新。 因此,如果
 你需要增加多台服务器,更好的方式是使用 Memcached::addServers 以确保这种更新只发生一次
 。

  同一台服务器可以在服务器池中多次出现,因为这里没有做重复检测。但这是不推荐的做法,对
 于期望提高某台服务器 权重的需求,请使用 weight 参数。
3 , memcache 的分布式策略

3.1 取余分布式策略

3.2 一致性分布式策略

3.3 设计自定义的分布式策略
3.1 取余分布式策略

3.1.1 取余分布式策略概念

3.1.2 用 php 写一个取余分布式策略来分析实现原理

3.1.3 取余分布式算法的优缺点
3.1.1 取余分布式策略概念

3.1.1 取余分布式策略概念

  取余分布式算法是先求得 key 的整数 hash 值,再除以服务器台数,根据余数来选择连接哪一台
 服务器,把数据存储到该服务器上。
3.1.2 用 php 写一个取余分布式策略来分析实现 原理


<?php
class mm{
     private $mm_config = array(
                0 => array('host'=>‘192.168.1.2','port'=>'11211'),
                1 => array('host'=>‘192.168.1.3','port'=>'11211'),
     );
     private $mm = '';
     public function set( $key ){
        $this->mm = new Memcache();
                $mm_con_key = hexdec( substr( md5( $key ) , 0 , 10 ) );
                $server = ($mm_con_key%count($this->mm_config));
                $this->mm->connect( $this->mm_config[$server]['host'] , $this->mm_config[$server]['port'] );
                echo 'server:'.$server.' , host: '.$this->mm_config[$server]['host'].' , port:'.$this->mm_config[$server]
     ['port'].'<br/>';
                var_dump( $this->mm->getStats() );
     }
}
$mm = new mm();
$mm->set( 'fsegsjkljklio' );
$mm->set( 'fse1gsjkljklio' );
?>
3.1.3 取余分布式算法的优 缺点

有什么有缺点:
3.1.3 取余分布式算法的优 缺点

有什么有缺点:




优点: 计算很简单 , 效率很高。

缺点:如果增加或减少一台服务器的话,所有 key 都失效,负载一下子会很高。



结论: 大型 memcache 集群中很少人采用这种方式, php 的 memcache 扩展的
  addServer 函数也放弃了这种分布式策略。
3.2 一致性分布式策略

3.2.1 一致性分布式策略概念

3.2.2 用 php 写一个一致性分布式策略来分析实现原理

3.2.3 一致性分布式算法的优缺点
3.2.1 一致性分布式策略概念

3.2.1 一致性分布式策略概念

  一致性 hash 的原理是算先算出 memcache 服务器的 hash 值,并将其分散到 0-2 的 32 次方的圆
 上,然后从数据映射到的位置开始顺时针查找,将数据保存到查找到的第一个服务器上,如果超过
 2 的 32 次方依然没找到,将数据保存到第一台 memcache 服务器上。
3.2.2 用 php 写一个一致性分布式策略来分析实现 原理


<?php
class mm{
     private $mm_config = array(
              1 => array('host'=>'192.168.1.2','port'=>'11211'),
              2 => array('host'=>‘192.168.1.3','port'=>'11211'),
     );
     private $max = 0; // 圆圈的最大值
     private $node_max = array(); // 节点的最大值
     private $mm = '';
     public function set( $key ){
        $this->mm = new Memcache();
              // 计算圆圈的最大值
              $this->max = hexdec('FFFFF');
              // 计算各节点值
              $server_num = count( $this->mm_config );
              $_node = ceil( $this->max/$server_num );
              for( $i=1 ; $i<=$server_num ; $i++ ){
                 $this->node_max[$i] = $_node*$i;
              }
              // 计算当前 key 的值
              $mm_con_key = hexdec( substr( md5( $key ) , 0 , 5 ) );
3.2.2 用 php 写一个一致性分布式策略来分析实现 原理


                // 找到当前 key 的节点号
                foreach( $this->node_max as $key=>$val ){
                    if( $mm_con_key < $val ){
                                  $server = $key;
                                               break;
                                }
                }
                // 如果找不到节点,将数据保存到第一台 memcache 服务器
                if( !isset( $server ) || !array_key_exists( $server , $this->mm_config ) ){
                    $server = 1;
                }
                $this->mm->connect( $this->mm_config[$server]['host'] , $this->mm_config[$server]['port'] );
                echo 'server:'.$server.' , host: '.$this->mm_config[$server]['host'].' , port:'.$this->mm_config[$server]
     ['port'].' , key: '.$mm_con_key.'<br/>';
                var_dump( $this->mm->getStats() );
     }
}
$mm = new mm();
$mm->set( 'fsegsjkljklio' );
$mm->set( 'fse1gsjkljklio' );
?>
3.2.3 一致性分布式算法的优 缺点

一致性分布式算法有什么优缺点
3.2.3 一致性分布式算法的优 缺点

一致性分布式算法有什么优缺点



优点:添加新的服务器,只影响了少部分缓存的失效,现在大部分都采用这种方
  式来实现 memcache 分布式。考虑容灾和扩容时候最好使用一致性分布式算
  法,以确保在出现故障或容量问题时减少对数据库的影响。
4 , memcache 高级应 用案例

4.1memcache 集群出现的一些问题与决解思路
    4.1.1 避免 key 冲突问题
    2.1.2 如何清理某项目某模块的缓存问题

4.2 用 memcache 做分页缓存

4.3 用 memcache 做 top10 实时排序
4.1memcache 集群出现 的一些问题 与决解思路

4.1.1 避免 key 冲突问题

4.1.2 如何清理某项目某模块的缓存问题




备注:参考资料文件下的 cache 类,并从 cache 扩展到项目模块缓存的实现。
4.2 用 memcache 做分页缓 存

参考我写的文章: http://dwphp.blog.51cto.com/4563391/826408
4.3 用 memcache 做 top10 实时 排序

实现思路:




我们把 top10 设置为一个数组变量存储到 memcache 中,下次各文章页面有用户访问的时候,统计该
  页
面访问数量,并与 top10 的数组最小一个数字比较,如果比最小的数字大,替换最小的数字,然后从
  新
排序该数组,写入 memcache 。
5 , memcache 监 控

5.1 命中率监控   ( get_hits/ cmd_get )

5.2 内存使用量监控

5.3 带宽监控
6 , memcache 监 控工具

6.1 用 memcache.php 监控

6.2 用 cacti 监控

6.3 用 memAdmin 监控
7 ,参考 addServer 思路写 mysql 分布式连 接类实现 mysql 集群


7.1 用 ip hash 策略实现读写单例模式连接 mysql 。
7.1 用 ip hash 策略实现读 写单 例模式连 接 mysql

<?php
class Model{
     private $master_config = array(
              1 =>
     array('host'=>'192.168.1.2','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT
     F-8'),
              2 =>
     array('host'=>'192.168.1.3','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT
     F-8'),
     );
     private $slave_config = array(
              1 =>
     array('host'=>'192.168.1.4','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT
     F-8'),
              2 =>
     array('host'=>'192.168.1.5','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT
     F-8'),
     );
     private $max = 0;           // 圆圈的最大值
     private $node_max = array(); // 节点的最大值
     private static $master = ''; // 主库的句柄
7.1 用 ip hash 策略实现读 写单 例模式连 接 mysql

  public function master( ){
           // 计算圆圈的最大值
           $this->max = pow(255,4)+pow(255,3)+pow(255,2)+255;
           // 计算各节点值
           $server_num = count( $this->master_config );
           $_node = ceil( $this->max/$server_num );
           for( $i=1 ; $i<=$server_num ; $i++ ){
              $this->node_max[$i] = $_node*$i;
           }
           $_SERVER["REMOTE_ADDR"] = '100.1.1.1';
           //$_SERVER["REMOTE_ADDR"] = '200.120.11.12';
           echo $_SERVER["REMOTE_ADDR"].'<br/>';
           // 计算当前 key 的值
           $ip = explode( '.' , $_SERVER["REMOTE_ADDR"] );
           $master_key = $ip[0]*pow(255,3) + $ip[1]*pow(255,2)+$ip[2]*255+$ip[3];
           // 找到当前 key 的节点号
           foreach( $this->node_max as $key=>$val ){
              if( $master_key < $val ){
                            $server = $key;
                                       break;
                          }
           }
7.1 用 ip hash 策略实现读 写单 例模式连 接 mysql

           if( !isset( $server ) || !array_key_exists( $server , $this->master_config ) ){
               $server = 1;
           }
           echo 'server:'.$server.' , host: '.$this->master_config[$server]['host'].' , port:'.$this-
    >master_config[$server]['port'].' , key: '.$master_key.'<br/>';
           // 实现单例连接
           $this->_master_connect( $server );

    }
    // 选择节点连接主库的函数
    private function _master_connect( $choose_master ){
       if( !is_object( Model::$master ) ){
                  // 连接数据库
               }
               return Model::$master;
    }

}
$model = new Model();
$master = $model->master();
?>
Thank you
单击 此处编辑 母版标题样 式


     单击此处编辑母版副标题样式

深入了解Memcache

  • 1.
    深入了解 memcache QQ 群名 称: cbsi 技术交流群 群   号 :3940869 华多网络科技有限公司
  • 2.
    提纲 • memcache 的内存管理机制 • addServer 的工作原理 • memcache 的分布式策略 • memcache 高级应用案例 • memcache 监控 • memcache 监控工具 • 参考 addServer 思路写 mysql 分布式连接类实现 mysql 集群
  • 3.
    1 , memcache的内存管理机制 1.1 内存分配机制 1.2 缓存删除与失效机制 1.3 内存不足时的 LRU 失效机制
  • 4.
    1.1 内存分配机制 1.1.1 Page为内存分配的最小单位。 1.1.2 Slabs 划分数据空间。 1.1.3 问题: 为什么采用这样的内存分配方式,而不是使用某个 key 的时候再 malloc ,用完 free 。
  • 5.
    1.1.1 Page 为内存分配的最小单 位。 1 , Memcached 的内存分配以 page 为单位,默认情况下一个 page 是 1M 。 2 , page 的申请是根据 slab 区域来申请。比如如果 slab1 的存放内存单位是 1- 104 bytes ,那 slab1 申请的 page 将以 104byte 为单位来划分成 10082 个 单位。
  • 6.
    1.1.2 Slabs 划分数据空间 。 1 , 根据 Slabs 划分数据空间 Memcached 并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列 slabs , 每个 slab 只负责一定范围内的数据存储。如下图,每个 slab 只存储大于其上一个 slab 的 size 并小 于或者等于自己最大 size 的数据。例如: slab 3 只存储大小介于 137 到 224 bytes 的数据。如 果一个数据大小为 230byte 将被分配到 slab 4 中。从下图可以看出,每个 slab 负责的空间其实是 不等的, memcached 默认情况下下一个 slab 的最大值为前一个的 1.25 倍。
  • 7.
    1.1.2 Slabs 划分数据空间 。 1 , Chunk 才是存放缓存数据的单位。 Chunk 是一系列固定的内存空间,这个大小就是管理它的 slab 的最大存放大小。例如: slab 1 的 所有 chunk 都是 104byte 。
  • 8.
  • 9.
    1.1.3 问题 为什么采用这样的内存分配方式,而不是使用某个 key的时候再 malloc ,用完 free 。 答案: 1 ,提高性能。 2 ,预防产生内存碎片。
  • 10.
    1.2 缓 存删除与失效机制 1 ,缓存删除: 放入一个删除队列 , 表明它不可以通过 get 命令获取到值 , 但是同时 add 和 replace 命令也会失 败 ( 无论如何 set 命令都会成功 ). 在这段时间过去后 , 元素最终被从服务端内存中 free 删除掉。 2 ,缓存过期: memcache 使用的是一种 Lazy Expiration 策略,自己不会监控存入的 key/value 是否过期,而是 在获取 key 值时查看记录的时间戳,检查 key/value 对空间市口过去。 3 ,问题: 1 , memcache 为什么不主动回收过期内存?
  • 11.
    1.2 缓 存删除与失效机制 1 ,缓存删除: 放入一个删除队列 , 表明它不可以通过 get 命令获取到值 , 但是同时 add 和 replace 命令也会失 败 ( 无论如何 set 命令都会成功 ). 在这段时间过去后 , 元素最终被从服务端内存中 free 删除掉。 2 ,缓存过期: memcache 使用的是一种 Lazy Expiration 策略,自己不会监控存入的 key/value 是否过期,而是 在获取 key 值时查看记录的时间戳,检查 key/value 对空间市口过去。 3 ,问题: 1 , memcache 为什么不主动回收过期内存? 答案:一切为了性能,大家使用 memcache 就是因为它的高性能。内存过期检测会浪费大量 CPU 资源。
  • 12.
    1.3 内存不足时 的LRU 失效机制 1 , LRU 机制: 当空间被占满时, memcache 就会使用 LRU 算法来分配空间,删除最近少使用的 key/value 对, 将其空间分配给新的 key/value 对。 2 ,为了性能,还是不能让 memcache 内存不够 由于使用 LRU 算法分配空间会消耗 CPU 资源,为了性能,最好让你的 memcache 保存足够的空 间。
  • 13.
    2 , addServer的工作原理 PHP 手册的介绍: Memcached::addServer() 增加指定服务器到服务器池中。此时不会建立与服务端的连接, 但是, 如果你使用一致性 key 分布选项( Memcached::DISTRIBUTION_CONSISTENT 或 Memcached::OPT_LIBKETAMA_COMPATIBLE ),一些内部的数据结构将会被更新。 因此,如果 你需要增加多台服务器,更好的方式是使用 Memcached::addServers 以确保这种更新只发生一次 。 同一台服务器可以在服务器池中多次出现,因为这里没有做重复检测。但这是不推荐的做法,对 于期望提高某台服务器 权重的需求,请使用 weight 参数。
  • 14.
    3 , memcache的分布式策略 3.1 取余分布式策略 3.2 一致性分布式策略 3.3 设计自定义的分布式策略
  • 15.
    3.1 取余分布式策略 3.1.1 取余分布式策略概念 3.1.2用 php 写一个取余分布式策略来分析实现原理 3.1.3 取余分布式算法的优缺点
  • 16.
    3.1.1 取余分布式策略概念 3.1.1 取余分布式策略概念 取余分布式算法是先求得 key 的整数 hash 值,再除以服务器台数,根据余数来选择连接哪一台 服务器,把数据存储到该服务器上。
  • 17.
    3.1.2 用 php写一个取余分布式策略来分析实现 原理 <?php class mm{ private $mm_config = array( 0 => array('host'=>‘192.168.1.2','port'=>'11211'), 1 => array('host'=>‘192.168.1.3','port'=>'11211'), ); private $mm = ''; public function set( $key ){ $this->mm = new Memcache(); $mm_con_key = hexdec( substr( md5( $key ) , 0 , 10 ) ); $server = ($mm_con_key%count($this->mm_config)); $this->mm->connect( $this->mm_config[$server]['host'] , $this->mm_config[$server]['port'] ); echo 'server:'.$server.' , host: '.$this->mm_config[$server]['host'].' , port:'.$this->mm_config[$server] ['port'].'<br/>'; var_dump( $this->mm->getStats() ); } } $mm = new mm(); $mm->set( 'fsegsjkljklio' ); $mm->set( 'fse1gsjkljklio' ); ?>
  • 18.
  • 19.
    3.1.3 取余分布式算法的优 缺点 有什么有缺点: 优点:计算很简单 , 效率很高。 缺点:如果增加或减少一台服务器的话,所有 key 都失效,负载一下子会很高。 结论: 大型 memcache 集群中很少人采用这种方式, php 的 memcache 扩展的 addServer 函数也放弃了这种分布式策略。
  • 20.
    3.2 一致性分布式策略 3.2.1 一致性分布式策略概念 3.2.2用 php 写一个一致性分布式策略来分析实现原理 3.2.3 一致性分布式算法的优缺点
  • 21.
    3.2.1 一致性分布式策略概念 3.2.1 一致性分布式策略概念 一致性 hash 的原理是算先算出 memcache 服务器的 hash 值,并将其分散到 0-2 的 32 次方的圆 上,然后从数据映射到的位置开始顺时针查找,将数据保存到查找到的第一个服务器上,如果超过 2 的 32 次方依然没找到,将数据保存到第一台 memcache 服务器上。
  • 22.
    3.2.2 用 php写一个一致性分布式策略来分析实现 原理 <?php class mm{ private $mm_config = array( 1 => array('host'=>'192.168.1.2','port'=>'11211'), 2 => array('host'=>‘192.168.1.3','port'=>'11211'), ); private $max = 0; // 圆圈的最大值 private $node_max = array(); // 节点的最大值 private $mm = ''; public function set( $key ){ $this->mm = new Memcache(); // 计算圆圈的最大值 $this->max = hexdec('FFFFF'); // 计算各节点值 $server_num = count( $this->mm_config ); $_node = ceil( $this->max/$server_num ); for( $i=1 ; $i<=$server_num ; $i++ ){ $this->node_max[$i] = $_node*$i; } // 计算当前 key 的值 $mm_con_key = hexdec( substr( md5( $key ) , 0 , 5 ) );
  • 23.
    3.2.2 用 php写一个一致性分布式策略来分析实现 原理 // 找到当前 key 的节点号 foreach( $this->node_max as $key=>$val ){ if( $mm_con_key < $val ){ $server = $key; break; } } // 如果找不到节点,将数据保存到第一台 memcache 服务器 if( !isset( $server ) || !array_key_exists( $server , $this->mm_config ) ){ $server = 1; } $this->mm->connect( $this->mm_config[$server]['host'] , $this->mm_config[$server]['port'] ); echo 'server:'.$server.' , host: '.$this->mm_config[$server]['host'].' , port:'.$this->mm_config[$server] ['port'].' , key: '.$mm_con_key.'<br/>'; var_dump( $this->mm->getStats() ); } } $mm = new mm(); $mm->set( 'fsegsjkljklio' ); $mm->set( 'fse1gsjkljklio' ); ?>
  • 24.
  • 25.
    3.2.3 一致性分布式算法的优 缺点 一致性分布式算法有什么优缺点 优点:添加新的服务器,只影响了少部分缓存的失效,现在大部分都采用这种方 式来实现 memcache 分布式。考虑容灾和扩容时候最好使用一致性分布式算 法,以确保在出现故障或容量问题时减少对数据库的影响。
  • 26.
    4 , memcache高级应 用案例 4.1memcache 集群出现的一些问题与决解思路 4.1.1 避免 key 冲突问题 2.1.2 如何清理某项目某模块的缓存问题 4.2 用 memcache 做分页缓存 4.3 用 memcache 做 top10 实时排序
  • 27.
    4.1memcache 集群出现 的一些问题与决解思路 4.1.1 避免 key 冲突问题 4.1.2 如何清理某项目某模块的缓存问题 备注:参考资料文件下的 cache 类,并从 cache 扩展到项目模块缓存的实现。
  • 28.
    4.2 用 memcache做分页缓 存 参考我写的文章: http://dwphp.blog.51cto.com/4563391/826408
  • 29.
    4.3 用 memcache做 top10 实时 排序 实现思路: 我们把 top10 设置为一个数组变量存储到 memcache 中,下次各文章页面有用户访问的时候,统计该 页 面访问数量,并与 top10 的数组最小一个数字比较,如果比最小的数字大,替换最小的数字,然后从 新 排序该数组,写入 memcache 。
  • 30.
    5 , memcache监 控 5.1 命中率监控 ( get_hits/ cmd_get ) 5.2 内存使用量监控 5.3 带宽监控
  • 31.
    6 , memcache监 控工具 6.1 用 memcache.php 监控 6.2 用 cacti 监控 6.3 用 memAdmin 监控
  • 32.
    7 ,参考 addServer思路写 mysql 分布式连 接类实现 mysql 集群 7.1 用 ip hash 策略实现读写单例模式连接 mysql 。
  • 33.
    7.1 用 iphash 策略实现读 写单 例模式连 接 mysql <?php class Model{ private $master_config = array( 1 => array('host'=>'192.168.1.2','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT F-8'), 2 => array('host'=>'192.168.1.3','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT F-8'), ); private $slave_config = array( 1 => array('host'=>'192.168.1.4','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT F-8'), 2 => array('host'=>'192.168.1.5','port'=>'3306','username'=>'test','passwd'=>'123456','dbname'=>'test','charset'=>'UT F-8'), ); private $max = 0; // 圆圈的最大值 private $node_max = array(); // 节点的最大值 private static $master = ''; // 主库的句柄
  • 34.
    7.1 用 iphash 策略实现读 写单 例模式连 接 mysql public function master( ){ // 计算圆圈的最大值 $this->max = pow(255,4)+pow(255,3)+pow(255,2)+255; // 计算各节点值 $server_num = count( $this->master_config ); $_node = ceil( $this->max/$server_num ); for( $i=1 ; $i<=$server_num ; $i++ ){ $this->node_max[$i] = $_node*$i; } $_SERVER["REMOTE_ADDR"] = '100.1.1.1'; //$_SERVER["REMOTE_ADDR"] = '200.120.11.12'; echo $_SERVER["REMOTE_ADDR"].'<br/>'; // 计算当前 key 的值 $ip = explode( '.' , $_SERVER["REMOTE_ADDR"] ); $master_key = $ip[0]*pow(255,3) + $ip[1]*pow(255,2)+$ip[2]*255+$ip[3]; // 找到当前 key 的节点号 foreach( $this->node_max as $key=>$val ){ if( $master_key < $val ){ $server = $key; break; } }
  • 35.
    7.1 用 iphash 策略实现读 写单 例模式连 接 mysql if( !isset( $server ) || !array_key_exists( $server , $this->master_config ) ){ $server = 1; } echo 'server:'.$server.' , host: '.$this->master_config[$server]['host'].' , port:'.$this- >master_config[$server]['port'].' , key: '.$master_key.'<br/>'; // 实现单例连接 $this->_master_connect( $server ); } // 选择节点连接主库的函数 private function _master_connect( $choose_master ){ if( !is_object( Model::$master ) ){ // 连接数据库 } return Model::$master; } } $model = new Model(); $master = $model->master(); ?>
  • 36.
    Thank you 单击 此处编辑母版标题样 式 单击此处编辑母版副标题样式