您好,欢迎访问一九零五行业门户网

数据库主从设置_PHP教程

对于一些访问量比较大的项目,我们常常采用数据库主从的方式进行读写分离,以分流用户操作,实现负载均衡。因此网上查找了相关的信息,做一个总结。下面的概念部分内容摘自百科或网络ppt,结尾的代码源自此次项目。
首先,因为之前没有做过类似的功能,需要在概念上进行了解:
负载均衡
负载均衡(load balance):将负载(工作任务)进行平衡、分摊到多个操作单元上进行执行,从而共同完成工作任务。主要分为两种类型:
1.集群(clustering)
单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,使系统处理能力得到大幅度提高。
2.分流
大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间,这主要针对web服务器、ftp服务器、企业关键应用服务器等网络应用。主从架构就是这种类型的负载均衡。
主从架构的好处
1.负载均衡(读写分离,提升数据处理效率)
2.高可用和故障转移的能力(数据分布,稳定性提升。主服务器出现故障,还可以用从服务器支撑)
3.备份(本身不能备份,但是能提供一个备份机,便于实现数据库的容灾、备份、恢复等操作)
4.数据一致性,避免冲突
5.测试mysql升级
mysql的复制功能
1:支持一主多从机制。数据通过主服务器复制到从服务器上。
2:支持多级结构。主从,从从,主主(互为主从)。
3:支持过滤功能(可以只复制主服务器上的部分数据,而非全部)。
复制的类型
1. 基于语句的复制:在主服务器上执行的sql语句,在从服务器上执行同样的sql语句。mysql默认采用基于语句的复制,效率比较高。
2. 基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍(mysql5.0开始支持)。
3. 混合类型的复制:默认采用基于语句的复制。发现基于语句无法精确复制时,就会采用基于行的复制
相应的二进制日志也有三种:
1:statement
2:row
3:mixed
服务器结构的要求
1:主从服务器中的表可以使用不同的表类型。另外:一台主服务器同时带多台从服务器,会影响其性能,可以拿出一台服务器作为从服务器代理,使用blockhole表类型。只记录日志,不写数据,由它带多台服务器,从而提升性能。     
2:主从服务器中的表可以使用不同的字段类型。
3:主从服务器中的表可以使用不同的索引。主服务器主要用来写操作,所以除了主键和唯一索引等保证数据关系的索引一般都可以不加;从服务器一般用来读操作,所以可以针对查询特征设置索引。甚至:不同的从服务器可以针对不同的查询设置不同的索引。
复制流程
1:master服务器将改变记录到二进制日志文件(binary log)中,这些记录叫做二进制日志事件(binary log events)
2:slave服务器将master的binary log  events拷贝到他的中继日志(relay log)
3:slave重做中继日志的事件,将改变反映到它自己的数据。
php代码实现
1.服务器连接配置文件
如有多态主|从服务器,那么只需数字往下递增即可。
[php] 
[database] 
dbname                              = vis_db 
charset                             = utf8 
;主 
servers.0.master                    = true 
servers.0.adapter                   = mysqli 
servers.0.host                      = vis_db 
servers.0.username                  = vis 
servers.0.password                  = vis 
;从 
servers.1.master                    = false 
servers.1.adapter                   = mysqli 
servers.1.host                      = vis_mmc 
servers.1.username                  = vis 
servers.1.password                  = vis 
2.数据库操作类代码
根据用户ip取余后,确定连接哪台服务器上的数据库。
项目中使用了zend framework框架。
[php] 
_getdbconfig($sname); 
            self::$_dbs[$sname] = zend_db::factory($params['adapter'], $params); 
        } catch (exception $e) { 
            if (debug) { 
                echo $e->getmessage(); 
            } 
            exit; 
        } 
    }
/**
     * 获取zend_db_adapter实例
     * @return zend_db_adapter
     */ 
    public static function getdb($sname) 
    { 
        if (emptyempty($sname)) { 
            exit; 
        }
if (!isset(self::$_dbs[$sname])) { 
            new self($sname); 
        } 
        return self::$_dbs[$sname]; 
    }
/**
     * 获取数据库的配置
     */ 
    private function _getdbconfig($sname) 
    { 
        $configarr = array(); 
        $dbconfig = zend_registry::get('db')->database->toarray(); 
        $serverconfigs = $dbconfig['servers']; 
        $masters = array(); 
        $slaves = array(); 
        foreach ($serverconfigs as $value) { 
            if (!isset($value['master'])) { 
                continue; 
            } 
            if (true == $value['master']) { 
                $masters[] = $value; 
            } 
            if (false == $value['master']) { 
                $slaves[] = $value; 
            } 
        } 
        $masternum = count($masters); 
        $slavenum = count($slaves);
$requestip = $this->_getrequestip();
switch ($sname) { 
            case 'master' : 
                if ($masternum > 1) { 
                    $configarr = $masters[$requestip % $masternum]; 
                } else { 
                    $configarr = $masters[0]; 
                } 
                break; 
            case 'slave' : 
                if ($slavenum > 1) { 
                    $configarr = $slaves[$requestip % $slavenum]; 
                } else { 
                    $configarr = $slaves[0]; 
                } 
                break; 
            default : 
                break; 
        } 
        if (emptyempty($configarr)) { 
            return array(); 
        }
$configarr['dbname'] = $dbconfig['dbname']; 
        $configarr['charset'] = $dbconfig['charset']; 
        return $configarr; 
    }
/**
     * 获取请求ip
     */ 
    private function _getrequestip() 
    { 
        $ip = getrequestip(true); 
        return sprintf('%u', ip2long($ip)); 
    }   www.2cto.com
/**
     * 析构zend_db_adapter实体(由于有些请求很耗时间,这段时间可能会让数据库超时)
     */ 
    public static function destructdb($sname = null) 
    { 
        if (null === $sname) { 
            self::$_dbs = null; 
        } else { 
            unset(self::$_dbs[$sname]); 
        } 
    }

调用代码时,传入一个标志,确定是操作主还是从数据库即可:
[php] 
$oslavedb = free_db_factory::getdb('slave');
作者:xinsheng2011
http://www.bkjia.com/phpjc/478116.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/478116.htmltecharticle对于一些访问量比较大的项目,我们常常采用数据库主从的方式进行读写分离,以分流用户操作,实现负载均衡。因此网上查找了相关的信...
其它类似信息

推荐信息