
正文
php分布式数据库 php分布式部署
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
php的memcached分布式hash算法,如何解决分布不均?crc32这个算法没办法把key值均匀的分布出去
memcached的总结和分布式一致性hash
当前很多大型的web系统为了减轻数据库服务器负载,会采用memchached作为缓存系统以提高响应速度。
目录: ()
memchached简介
hash
取模
一致性hash
虚拟节点
源码解析
参考资料
1. memchached简介
memcached是一个开源的高性能分布式内存对象缓存系统。
其实思想还是比较简单的,实现包括server端(memcached开源项目一般只单指server端)和client端两部分:
server端本质是一个in-memory key-value store,通过在内存中维护一个大的hashmap用来存储小块的任意数据,对外通过统一的简单接口(memcached protocol)来提供操作。
client端是一个library,负责处理memcached protocol的网络通信细节,与memcached server通信,针对各种语言的不同实现分装了易用的API实现了与不同语言平台的集成。
web系统则通过client库来使用memcached进行对象缓存。
2. hash
memcached的分布式主要体现在client端,对于server端,仅仅是部署多个memcached server组成集群,每个server独自维护自己的数据(互相之间没有任何通信),通过daemon监听端口等待client端的请求。
而在client端,通过一致的hash算法,将要存储的数据分布到某个特定的server上进行存储,后续读取查询使用同样的hash算法即可定位。
client端可以采用各种hash算法来定位server:
取模
最简单的hash算法
targetServer = serverList[hash(key) % serverList.size]
直接用key的hash值(计算key的hash值的方法可以自由选择,比如算法CRC32、MD5,甚至本地hash系统,如java的hashcode)模上server总数来定位目标server。这种算法不仅简单,而且具有不错的随机分布特性。
但是问题也很明显,server总数不能轻易变化。因为如果增加/减少memcached server的数量,对原先存储的所有key的后续查询都将定位到别的server上,导致所有的cache都不能被命中而失效。
一致性hash
为了解决这个问题,需要采用一致性hash算法(consistent hash)
相对于取模的算法,一致性hash算法除了计算key的hash值外,还会计算每个server对应的hash值,然后将这些hash值映射到一个有限的值域上(比如0~2^32)。通过寻找hash值大于hash(key)的最小server作为存储该key数据的目标server。如果找不到,则直接把具有最小hash值的server作为目标server。
为了方便理解,可以把这个有限值域理解成一个环,值顺时针递增。
如上图所示,集群中一共有5个memcached server,已通过server的hash值分布到环中。
如果现在有一个写入cache的请求,首先计算x=hash(key),映射到环中,然后从x顺时针查找,把找到的第一个server作为目标server来存储cache,如果超过了2^32仍然找不到,则命中第一个server。比如x的值介于A~B之间,那么命中的server节点应该是B节点
可以看到,通过这种算法,对于同一个key,存储和后续的查询都会定位到同一个memcached server上。
那么它是怎么解决增/删server导致的cache不能命中的问题呢?
假设,现在增加一个server F,如下图
此时,cache不能命中的问题仍然存在,但是只存在于B~F之间的位置(由C变成了F),其他位置(包括F~C)的cache的命中不受影响(删除server的情况类似)。尽管仍然有cache不能命中的存在,但是相对于取模的方式已经大幅减少了不能命中的cache数量。
虚拟节点
但是,这种算法相对于取模方式也有一个缺陷:当server数量很少时,很可能他们在环中的分布不是特别均匀,进而导致cache不能均匀分布到所有的server上。
如图,一共有3台server – 1,2,4。命中4的几率远远高于1和2。
为解决这个问题,需要使用虚拟节点的思想:为每个物理节点(server)在环上分配100~200个点,这样环上的节点较多,就能抑制分布不均匀。
当为cache定位目标server时,如果定位到虚拟节点上,就表示cache真正的存储位置是在该虚拟节点代表的实际物理server上。
另外,如果每个实际server的负载能力不同,可以赋予不同的权重,根据权重分配不同数量的虚拟节点。
// 采用有序map来模拟环
this.consistentBuckets = new TreeMap();
MessageDigest md5 = MD5.get();//用MD5来计算key和server的hash值
// 计算总权重
if ( this.totalWeight for ( int i = 0; i this.weights.length; i++ )
this.totalWeight += ( this.weights[i] == null ) ? 1 : this.weights[i];
} else if ( this.weights == null ) {
this.totalWeight = this.servers.length;
}
// 为每个server分配虚拟节点
for ( int i = 0; i servers.length; i++ ) {
// 计算当前server的权重
int thisWeight = 1;
if ( this.weights != null this.weights[i] != null )
thisWeight = this.weights[i];
// factor用来控制每个server分配的虚拟节点数量
// 权重都相同时,factor=40
// 权重不同时,factor=40*server总数*该server权重所占的百分比
// 总的来说,权重越大,factor越大,可以分配越多的虚拟节点
double factor = Math.floor( ((double)(40 * this.servers.length * thisWeight)) / (double)this.totalWeight );
for ( long j = 0; j factor; j++ ) {
// 每个server有factor个hash值
// 使用server的域名或IP加上编号来计算hash值
// 比如server - "172.45.155.25:11111"就有factor个数据用来生成hash值:
// 172.45.155.25:11111-1, 172.45.155.25:11111-2, ..., 172.45.155.25:11111-factor
byte[] d = md5.digest( ( servers[i] + "-" + j ).getBytes() );
// 每个hash值生成4个虚拟节点
for ( int h = 0 ; h 4; h++ ) {
Long k =
((long)(d[3+h*4]0xFF) 24)
| ((long)(d[2+h*4]0xFF) 16)
| ((long)(d[1+h*4]0xFF) 8 )
| ((long)(d[0+h*4]0xFF));
// 在环上保存节点
consistentBuckets.put( k, servers[i] );
}
}
// 每个server一共分配4*factor个虚拟节点
}
// 采用有序map来模拟环
this.consistentBuckets = new TreeMap();
MessageDigest md5 = MD5.get();//用MD5来计算key和server的hash值
// 计算总权重
if ( this.totalWeight for ( int i = 0; i this.weights.length; i++ )
this.totalWeight += ( this.weights[i] == null ) ? 1 : this.weights[i];
} else if ( this.weights == null ) {
this.totalWeight = this.servers.length;
}
// 为每个server分配虚拟节点
for ( int i = 0; i servers.length; i++ ) {
// 计算当前server的权重
int thisWeight = 1;
if ( this.weights != null this.weights[i] != null )
thisWeight = this.weights[i];
// factor用来控制每个server分配的虚拟节点数量
// 权重都相同时,factor=40
// 权重不同时,factor=40*server总数*该server权重所占的百分比
// 总的来说,权重越大,factor越大,可以分配越多的虚拟节点
double factor = Math.floor( ((double)(40 * this.servers.length * thisWeight)) / (double)this.totalWeight );
for ( long j = 0; j factor; j++ ) {
// 每个server有factor个hash值
// 使用server的域名或IP加上编号来计算hash值
// 比如server - "172.45.155.25:11111"就有factor个数据用来生成hash值:
// 172.45.155.25:11111-1, 172.45.155.25:11111-2, ..., 172.45.155.25:11111-factor
byte[] d = md5.digest( ( servers[i] + "-" + j ).getBytes() );
// 每个hash值生成4个虚拟节点
for ( int h = 0 ; h 4; h++ ) {
Long k =
((long)(d[3+h*4]0xFF) 24)
| ((long)(d[2+h*4]0xFF) 16)
| ((long)(d[1+h*4]0xFF) 8 )
| ((long)(d[0+h*4]0xFF));
// 在环上保存节点
consistentBuckets.put( k, servers[i] );
}
}
// 每个server一共分配4*factor个虚拟节点
}
// 用MD5来计算key的hash值
MessageDigest md5 = MD5.get();
md5.reset();
md5.update( key.getBytes() );
byte[] bKey = md5.digest();
// 取MD5值的低32位作为key的hash值
long hv = ((long)(bKey[3]0xFF) 24) | ((long)(bKey[2]0xFF) 16) | ((long)(bKey[1]0xFF) 8 ) | (long)(bKey[0]0xFF);
// hv的tailMap的第一个虚拟节点对应的即是目标server
SortedMap tmap = this.consistentBuckets.tailMap( hv );
return ( tmap.isEmpty() ) ? this.consistentBuckets.firstKey() : tmap.firstKey();
更多问题到问题求助专区()
相关问答
Q1: TDSQL TCA 分布式实例特点初探分布表和SQL透传
TDSQL分布式实例通过Proxy接口提供和mysql兼容的连接方式php分布式数据库,用户通过IP地址、端口号以及用户名、密码进行连接:
(注意:公有云TDSQL需要在实例页面申请公网连接地址)
连接示例:mysql -h172.21.32.13 (proxy地址) -P3306(proxy端口) -utest (数据库账号) -p
与普通的mysql连接方法一致php分布式数据库,分布式实例兼容mysql的协议和语法,支持SSL加密等功能。当然,您也可以使用navicat、 jdbc、 odbc、 php、 Python等来连接分布式TDSQL实例。
1、TDSQL分布式实例支持表的类型介绍
a、分布式表: 即水平拆分表,也成为“分表”,该表从业务视角是一张完整的逻辑表,但后端根据分表键(shardkey)的HASH值将数据分布到不同的物理节点组(SET)中。
b、普通表: 又名Noshard表,即无需拆分的表,和传统集中式数据库中的表一致,且没有做任何特殊处理的表,目前分布式实例将该表默认存放在第一个物理节点组(set)中。
c、广播表: 又名小表广播技术,即设置为广播表后,该表的所有操作都将广播到所有物理节点组(set)中,每个set都有该表的全量数据,常用于业务系统关联查询较多,修改较少的小表或配置表等。
表类型选用注意事项:
在分布式实例中,如果两张表分表键相等,这意味着两张表**相同的分表键对应的行**,存储在相同的物理节点组中。这种场景通常被称为组拆分(groupshard),会极大的提升业务联合查询等语句的处理效率。由于单表默认放置在第一个set上,如果在分布式实例中建立大的单表,则会导致第一个set的负载太大。除非特别需要,在分布式实例中尽量使用分布式表,这也是分布式实例的特点之一。
2、TDSQL分布式实例表的创建
接下来我们来看下分布式数据库TDSQL所支持的三种类型表的使用方法和注意事项。
a、分布式表的使用
简述:普通的分表创建时必须在最后面**指定分表键(shardkey)的值,该值为表中的一个字段名字,会用于后续sql的路由选择。连接到TDSQL分布式实例后,我们创建一个本次操作使用的数据库名为:testdb
mysql create database testdb;
mysqluse testdb;
接下来我们创建分布式表,命名以分布式拼音首字母命名
**建表语句1:**
MySQL testdb create table fbs ( a int, b int, c char(20),primary key (a),unique key u_1(a,c) ) shardkey=a;
Query OK, 0 rows affected (0.07 sec)
**建表语句2:**
MySQL testdb create table fbs2 ( a int, b int, c char(20), primary key (a,b) ) shardkey=a;
Query OK, 0 rows affected (0.09 sec)
b、广播表的创建
简述:支持建小表(广播表),此时该表在所有set中都是全部数据,这个主要方用于跨set的join操作,同时通过分布式事务保证修改操作的原子性,使得所有set的数据是完全一致的 。
**语句:**
MySQL testdb create table gbb(a int,b int key) **shardkey=noshardkey_allset;**
Query OK, 0 rows affected (0.03 sec)
c、传统普通表
简述:支持建立普通的表,语法和传统mysql完全一样,此时该表的数据全量存在第一个set节点中,所有该类型的表都放在第一个set中。
MySQL testdb create table ptb(a int ,b varchar(10));
Query OK, 0 rows affected (0.03 sec)
注意事项:
1、在分布式实例中,分布式表shardkey对应后端数据库的分区字段,因此必须是主键以及所有唯一索引的一部分, 否则可能无法完成建表操作。
2、分布式表shardkey字段的值不包含中文, 否则proxy会转换字符集可能会出错。另外SQL语法上如:shardkey=a 一般放在SQL语句最后来写。
3、TDSQL分布式实例表的数据操作
为了更好的发挥分布式架构的优势,在进行SQL操作时和传统数据库还是有部分差异。接下来我们从数据库的插入,更新,删除方面分别来看有哪些注意事项。
======INSERT插入操作=======
**插入语句1:**
MySQL testdb insert into fbs(a,b) values(10,1000);
Query OK, 1 row affected (0.00 sec)
**插入语句2:**
MySQL testdb insert into fbs values(1,10,1000);
或
MySQL testdb insert into test1 (b,c) values(100,"record3");
ERROR 810 (HY000): Proxy ERROR:sql is too complex,need to send to only noshard table.Shard table insert must has field spec
注意:语句2报错的原因insert时字段需要包含shardkey,否则会拒绝执行该sql,因为Proxy不知道该sql发往哪个后端分片节点。
=====UPDATE、DELETE更新、删除操作=====
更新语句1:
MySQL testdb update fbs set b=2000 where a=10;
Query OK, 1 row affected (0.00 sec)
更新语句2:
MySQL testdb update fbs set b=2000 ;
ERROR 658 (HY000): Proxy ERROR: Join internal error: update query has no where clause
删除操作:
MySQL testdb delete from fbs;
ERROR 913 (HY000): Proxy ERROR:Join internal error: delete query has no where clause
注意事项:
1、出于数据操作安全上和减少人为误操作导致数据丢失情况的出现,TDSQL禁止update 无 where 条件的更新动作。
2、同样的delete操作无where条件也会被禁止执行,如果确认要删除表数据或表,建议备份后用truncate或drop方式操作。
3、同样的update操作时尽量避免更新shardkey字段,因为影响Proxy中的路由更新,会导致错误。
1、TDSQL透传功能介绍
对于分布式实例,会对SQL进行语法解析,有一定的限制,如果用户想在某个set中获取单个节点数据,或在指定节点执行SQL,可以使用TDSQL的透传SQL的功能。
使用透传功能,我们需要重新连接登录TDSQL分布式实例时指定 **- c选项**。普通登录方式,不支持指定节点执行SQL的透传功能。
登录如下:
mysql -h172.21.32.13 (proxy地址) -utest -P3306 -p -c(透传必须指定-c)
2、TDSQL透传操作演示
首先我们重新登陆TDSQL分布式实例: mysql -h172.21.32.13 -utest -P3306 -p -c
仍旧切换使用testdb数据库。
a、查看分布式实例set节点
使用/*proxy*/show status 查看当前的TDSQL分布式实例的节点信息,共有两个set ,分别为set_1605181898_1、set_1605181972_3
MySQL testdb /*proxy*/show status ;
+-----------------------------+-------------------------------------------------------------------+
| status_name | value |
+-----------------------------+-------------------------------------------------------------------+
| cluster | group_1605181791_302290 |
| **set_1605181898_1:ip | 10.53.179.14:4322;s1@10.53.178.227:4322@1@IDC_GZ_YDSS0301_79263@0 |
| set_1605181898_1:hash_range | 0---31 |
| **set_1605181972_3:ip | 10.53.179.14:4323;s1@10.53.178.227:4323@1@IDC_GZ_YDSS0301_79263@0 |
| set_1605181972_3:hash_range | 32---63 |
| set | set_1605181898_1,set_1605181972_3 |
+-----------------------------+-------------------------------------------------------------------+
6 rows in set (0.00 sec)
b、演示数据插入
我们针对之前创建的fbs分布式表进行数据的插入
MySQL testdb insert into fbs(a,b,c) values(10,1,'AAA'),(20,2,'bbb'),(30,3,'ccc'),(40,4,'dddd'),(50,5,'eee'),(60,6,'fff'),(70,7,'ggg'),(80,8,'hhhh');
MySQL testdb select * from fbs order by 1;
+----+------+------+
| a | b | c |
+----+------+------+
| 10 | 1 | AAA |
| 20 | 2 | bbb |
| 30 | 3 | ccc |
| 40 | 4 | dddd |
| 50 | 5 | eee |
| 60 | 6 | fff |
| 70 | 7 | ggg |
| 80 | 8 | hhhh |
+----+------+------+
8 rows in set (0.00 sec)
c、透传查看数据在各个节点的分布情况
MySQL testdb /*proxy*/show status;
+-----------------------------+-------------------------------------------------------------------+
| status_name | value |
+-----------------------------+-------------------------------------------------------------------+
| cluster | group_1605181791_302290 |
| **set_1605181898_1:ip | 10.53.179.14:4322;s1@10.53.178.227:4322@1@IDC_GZ_YDSS0301_79263@0 |
| set_1605181898_1:hash_range | 0---31 |
| set_1605181972_3:ip | 10.53.179.14:4323;s1@10.53.178.227:4323@1@IDC_GZ_YDSS0301_79263@0 |
| set_1605181972_3:hash_range | 32---63 |
| set | set_1605181898_1,set_1605181972_3 |
+-----------------------------+-------------------------------------------------------------------+
6 rows in set (0.00 sec)
查看数据在set_1605181898_1 节点上的分布
MySQL testdb /*sets:set_1605181898_1*/select * from fbs order by 1;
+----+------+------+------------------+
| a | b | c | info |
+----+------+------+------------------+
| 10 | 1 | AAA | set_1605181898_1 |
| 30 | 3 | ccc | set_1605181898_1 |
| 40 | 4 | dddd | set_1605181898_1 |
| 50 | 5 | eee | set_1605181898_1 |
| 80 | 8 | hhhh | set_1605181898_1 |
+----+------+------+------------------+
5 rows in set (0.00 sec)
查看数据在set_1605181972_3节点上的分布
MySQL testdb /*sets:set_1605181972_3*/select * from fbs order by 1;
+----+------+------+------------------+
| a | b | c | info |
+----+------+------+------------------+
| 20 | 2 | bbb | set_1605181972_3 |
| 60 | 6 | fff | set_1605181972_3 |
| 70 | 7 | ggg | set_1605181972_3 |
+----+------+------+------------------+
3 rows in set (0.00 sec)
d、通过shardkey分片号查看数据
MySQL testdb /*shardkey:2*/select * from fbs order by 1;
+----+------+------+
| a | b | c |
+----+------+------+
| 20 | 2 | bbb |
| 60 | 6 | fff |
| 70 | 7 | ggg |
+----+------+------+
3 rows in set (0.00 sec)
支持透传种类和格式:
1、set名字可以通过/*proxy*/show status查询
2、/*sets:set_1名称*/ 透传指定节点
3、/*sets:allsets*/ 透传所有节点
4、/*shardkey:10*/ 透传到shardkey分片对应的set
5、支持透传sql到对应的一个或者多个set
分布式表的DDL部分的语句限制:
暂不支持CREATE TABLE ... LIKE
暂不支持CREATE TABLE ... SELECT
暂不支持CREATE TEMPORARY TABLE
暂不支持CREATE/DROP/ALTER SERVER/LOGFILE GROUP/
暂不支持ALTER对分表键(shardkey)进行重命名,不过可以修改类型
分布式表的DML部分的语句限制:
暂不支持SELECT INTO OUTFILE/INTO DUMPFILE/INTO LOAD DATA导出
暂不支持INSERT ... SELECT
暂不支持UPDATE 分布式shardkey列的值
本操作主要是面向传统数据库的开发者或者DBA用户,让大家能够初步入手php分布式数据库了解分布式数据库的特点。另外分布式数据库在架构上提供了灵活的读写分离模式,在SQL上支持全局的order by, group by, limit操作,支持聚合函数,跨set节点的join、子查询、支持分布式事务,传统数据库所支持的大部分操作在分布式数据库中得到继承。分布式数据库是在传统数据库的基础之上发展起来的,对传统集中式的数据库有较好的兼容性,对SQL语句语法的使用上兼容大部分SQL1999,SQL2003标准,且对SQL的ACID特性都予以支持。分布式数据库在逻辑上是一个独立完整的数据库,但在架构上和物理上采用 多节点分片方式,经过内部算法将数据打散分布来到不同节点存储数据,对前端业务屏蔽后端的复杂架构,并且自身具备数据的最终一致性访问,可用性和分区容灾等特性的数据库。希望本次操作能给大家带来一些对分布式数据库TDSQL的一些认识和收获。
*禁止转载,可转发(转发文章请注明出处)
TDPub企业级分布式关系数据库
Q2: php mysql分布式数据库如何实现
当前做分布式的厂商有几家,我知道比较出名的有“华为云分布式数据库DDM”和“阿里云分布式数据库”,感兴趣可以自行搜素了解下。
分布式数据库的几点概念可以了解一下。
数据分库:
以表为单位,把原有数据库切分成多个数据库。切分后不同的表存储在不同的数据库上。
以表中的数据行记录为单位,把原有逻辑数据库切分成多个物理数据库分片,表数据记录分布存储在各个分片上。
路由分发:
在分布式数据库中,路由的作用即将SQL语句进行解析,并转发到正确的分片上,保证SQL执行后得到正确的结果,并且节约QPS资源。
读写分离:
数据库中对计算和缓存资源消耗较多的往往是密集或复杂的SQL查询。当系统资源被查询语句消耗,反过来会影响数据写入操作,进而导致数据库整体性能下降,响应缓慢。因此,当数据库CPU和内存资源占用居高不下,且读写比例较高时,可以为数据库添加只读数据库。
Q3: Think3.2.3怎么配置多个数据库连接
Think3.2.3配置多个数据库连接方法:
一、全局配置定义
常用的配置方式是在应用配置文件或者模块配置文件中添加下面的配置参数:
//数据库配置信息
'DB_TYPE' = 'mysql', // 数据库类型
'DB_HOST' = 'localhost', // 服务器地址
'DB_NAME' = 'thinkphp', // 数据库名
'DB_USER' = 'root', // 用户名
'DB_PWD' = '123456', // 密码
'DB_PORT' = 3306, // 端口
'DB_PREFIX' = 'think_', // 数据库表前缀
'DB_CHARSET'= 'utf8', // 字符集
数据库的类型由DB_TYPE参数设置。
下面是目前支持的数据库设置:
DB_TYPE设置 支持的数据库类型
mysql或mysqli mysql
pgsql pgsql
sqlite sqlite
mssql 或sqlsrv sqlserver
oracle oracle
ibase ibase
mongo mongo
PDO PDO支持的所有数据库
如果DB_TYPE使用PDO类型的话,数据库类型则由DB_DSN配置决定。
或者采用如下配置
'DB_DSN' = 'mysql://root:123456@localhost:3306/thinkphp#utf8'
使用DB_DSN方式定义可以简化配置参数,DSN参数格式为:
数据库类型://用户名:密码@数据库地址:数据库端口/数据库名#字符集
字符集设置需要3.2.1版本以上有效,字符集如果没有设置的话,默认为utf8。
如果两种配置参数同时存在的话,DB_DSN配置参数优先。
注意:如果要设置分布式数据库,暂时不支持DB_DSN方式配置。
如果采用PDO驱动的话,则必须首先配置DB_TYPE为pdo,然后还需要单独配置其他参数,例如:
//PDO连接方式
'DB_TYPE' = 'pdo', // 数据库类型
'DB_USER' = 'root', // 用户名
'DB_PWD' = '', // 密码
'DB_PREFIX' = 'think_', // 数据库表前缀
'DB_DSN' = 'mysql:host=localhost;dbname=thinkphp;charset=utf8'
注意:PDO方式的DB_DSN配置格式有所区别,根据不同的数据库类型设置有所不同,具体可以参考PHP手册。
配置文件定义的数据库连接信息一般是系统默认采用的,因为一般一个应用的数据库访问配置是相同的。该方法系统在连接数据库的时候会自动获取,无需手动连接。
可以对每个模块定义不同的数据库连接信息,如果开启了调试模式的话,还可以在不同的应用状态的配置文件里面定义独立的数据库配置信息。
二、模型类定义
如果在某个模型类里面定义了connection属性的话,则实例化该自定义模型的时候会采用定义的数据库连接信息,而不是配置文件中设置的默认连接信息,通常用于某些数据表位于当前数据库连接之外的其它数据库,例如:
//在模型里单独设置数据库连接信息
namespace Home\Model;
use Think\Model;
class UserModel extends Model{
protected $connection = array(
'db_type' = 'mysql',
'db_user' = 'root',
'db_pwd' = '1234',
'db_host' = 'localhost',
'db_port' = '3306',
'db_name' = 'thinkphp',
'db_charset' = 'utf8',
);
}
也可以采用DSN方式定义,例如:
//在模型里单独设置数据库连接信息
namespace Home\Model;
use Think\Model;
class UserModel extends Model{
//或者使用DSN定义
protected $connection = 'mysql://root:1234@localhost:3306/thinkphp#utf8';
}
如果我们已经在配置文件中配置了额外的数据库连接信息,例如:
//数据库配置1
'DB_CONFIG1' = array(
'db_type' = 'mysql',
'db_user' = 'root',
'db_pwd' = '1234',
'db_host' = 'localhost',
'db_port' = '3306',
'db_name' = 'thinkphp',
'db_charset'= 'utf8',
),
//数据库配置2
'DB_CONFIG2' = 'mysql://root:1234@localhost:3306/thinkphp#utf8';
那么,我们可以把模型类的属性定义改为:
//在模型里单独设置数据库连接信息
namespace Home\Model;
use Think\Model;
class UserModel extends Model{
//调用配置文件中的数据库配置1
protected $connection = 'DB_CONFIG1';
}
//在模型里单独设置数据库连接信息
namespace Home\Model;
use Think\Model;
class InfoModel extends Model{
//调用配置文件中的数据库配置1
protected $connection = 'DB_CONFIG2';
}
三、实例化定义
除了在模型定义的时候指定数据库连接信息外,我们还可以在实例化的时候指定数据库连接信息,例如: 如果采用的是M方法实例化模型的话,也可以支持传入不同的数据库连接信息,例如:
$User = M('User','other_','mysql://root:1234@localhost/demo#utf8');
表示实例化User模型,连接的是demo数据库的other_user表,采用的连接信息是第三个参数配置的。如果我们在项目配置文件中已经配置了DB_CONFIG2的话,也可以采用:
$User = M('User','other_','DB_CONFIG2');
需要注意的是,ThinkPHP的数据库连接的惰性的,所以并不是在实例化的时候就连接数据库,而是在有实际的数据操作的时候才会去连接数据库(额外的情况是,在系统第一次实例化模型的时候,会自动连接数据库获取相关模型类对应的数据表的字段信息)。
Q4: php能实现分布式数据库吗?
可以实现.
将数据库放在不同的服务器上,主页的不同模块可以单独访问自己所需要的数据库,以减轻单独一个服务器的压力.
既可以每个模块都是不同数据库,也可以同个模块不同数据库,但这样没什么意思.
实际上,现在网络带宽大,服务器性能也好,再加以磁盘阵列保证数据.如果吞吐量大得惊人,没必要用分布式的,必竟维护比较麻烦.
象很多网络游戏在线人数那么多,或者象天涯猫扑那样,才需要用分布式,普通网站就几乎都用集中式的.
php分布式数据库的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于php分布式部署、php分布式数据库的信息别忘了在本站进行查找喔。







