资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

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();

更多问题到问题求助专区()

php 分布式怎么开发

普通的Web开发,常用的模式就是用户登录之后,登录状态信息保存在Session中,用户一些常用的热数据保存在文件缓存中,用户上传的附件信息保存在Web服务器的某个目录上。这种方式对于一般的Web应用,使用很方便,完全能够胜任。但是对于高并发的企业级网站,就应付不了了。需要采用Web集群实现负载均衡。

使用Web集群方式部署之后,首要调整的就是用户状态信息与附件信息。用户状态不能再保存到Session中,缓存也不能用本地Web服务器的文件缓存,以及附件,也不能保存在Web服务器上了。因为要保证集群里面的各个Web服务器,状态完全一致。因此,需要将用户状态、缓存等保存到专用的缓存服务器,比如Memcache。附件需要保存到云存储中。

 Web负载均衡

Web负载均衡(Load Balancing),简单地说就是给我们的服务器集群分配“工作任务”,而采用恰当的分配方式,对于保护处于后端的Web服务器来说,非常重要。

 负载均衡的策略有很多,我们从简单的讲起。 

1. HTTP重定向 

当用户发来请求的时候,Web服务器通过修改HTTP响应头中的Location标记来返回一个新的url,然后浏览器再继续请求这个新url,实际上就是页面重定向。通过重定向,来达到“负载均衡”的目标。

 2. 反向代理负载均衡 

反向代理服务的核心工作主要是转发HTTP请求,扮演了浏览器端和后台Web服务器中转的角色。因为它工作在HTTP层(应用层),也就是网络七层结构中的第七层,因此也被称为“七层负载均衡”。可以做反向代理的软件很多,比较常见的一种是Nginx。

 Nginx是一种非常灵活的反向代理软件,可以自由定制化转发策略,分配服务器流量的权重等。反向代理中,常见的一个问题,就是Web服务器存储的session数据。

3. IP负载均衡

IP负载均衡服务是工作在网络层(修改IP)和传输层(修改端口,第四层),比起工作在应用层(第七层)性能要高出非常多。原理是,他是对IP层的数据包的IP地址和端口信息进行修改,达到负载均衡的目的。这种方式,也被称为“四层负载均衡”。常见的负载均衡方式,是LVS(Linux Virtual Server,Linux虚拟服务),通过IPVS(IP Virtual Server,IP虚拟服务)来实现。

php能实现分布式数据库吗?

可以实现.

将数据库放在不同的服务器上,主页的不同模块可以单独访问自己所需要的数据库,以减轻单独一个服务器的压力.

既可以每个模块都是不同数据库,也可以同个模块不同数据库,但这样没什么意思.

实际上,现在网络带宽大,服务器性能也好,再加以磁盘阵列保证数据.如果吞吐量大得惊人,没必要用分布式的,必竟维护比较麻烦.

象很多网络游戏在线人数那么多,或者象天涯猫扑那样,才需要用分布式,普通网站就几乎都用集中式的.

php mysql分布式数据库如何实现

当前做分布式的厂商有几家,我知道比较出名的有“华为云分布式数据库DDM”和“阿里云分布式数据库”,感兴趣可以自行搜素了解下。

分布式数据库的几点概念可以了解一下。

数据分库:

以表为单位,把原有数据库切分成多个数据库。切分后不同的表存储在不同的数据库上。

以表中的数据行记录为单位,把原有逻辑数据库切分成多个物理数据库分片,表数据记录分布存储在各个分片上。

路由分发:

在分布式数据库中,路由的作用即将SQL语句进行解析,并转发到正确的分片上,保证SQL执行后得到正确的结果,并且节约QPS资源。

读写分离:

数据库中对计算和缓存资源消耗较多的往往是密集或复杂的SQL查询。当系统资源被查询语句消耗,反过来会影响数据写入操作,进而导致数据库整体性能下降,响应缓慢。因此,当数据库CPU和内存资源占用居高不下,且读写比例较高时,可以为数据库添加只读数据库。


网站标题:php数据库分布式 php数据库分页是怎么实现的
标题网址:http://www.cdkjz.cn/article/ddshhjh.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220