php分布式数据库架构 php 分布式架构

leftjoin怎么拆成单表Copyright ? 1999-2020, CSDN.NET, All Rights Reserved
分库分表
打开APP
ActionTech
关注
分布式 | Global 表 Left Join 拆分表实现原因探究 原创
2020-06-29 16:53:37
ActionTech
码龄4年
关注
作者:郭奥门
爱可生 DBLE 研发成员,负责分布式数据库中间件的新功能开发,回答社区/客户/内部提出的一般性问题 。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源 。
本文关键字:JOIN、原理解析、分库分表
问题
前几天,社区交流群一个小伙伴提出这样一个问题:
小伙伴说:全局表和分片表的左连接能否支持 – 目前测试 mycat 结果不对 。
很显然是想要脱坑的 mycat 用户 , 急需找个替代品 , 主要的是他也找到了,哈哈哈 。
场景重现
首先我们创建一个全局表和一个拆分表 , 各自设置两个分片节点,全局表在两个节点数据一致,拆分表 id=1、2 的在一个节点,id=5000001 的在另一个节点,其中 id=1 和 id=2 的只有 id 字段值不同、codecontent 字段值都一样 。
mycat 场景重现
以上准备工作完成,接下来我们通过 a.id、b.code 将两张表左连接查询,结果如小伙伴所言:mycat 结果不对 。
dble 场景重现
以上准备工作完成 , 接下来我们通过 a.id、b.code 将两张表左连接查询,结果如下所示;显而易见实际得到的结果符合预期想要的结果 。
结果探究
根据以上使用 mycat 和 dble 进行 global left join 拆分表查询得到不同的结果,我们尝试着使用 explain 查看同一种类型的查询在执行计划上会有什么不同?
mycat 执行计划
根据上图执行计划,我们简单分析一下 。
mycat 会将 sql 原封不动的交由分片配置的所有实例去执行,然后根据执行结果进行合并 , 这里合并只是简单的对结果进行累加,很显然这样的计划显示 mycat 内部处理逻辑是错误的 。因为全局表在每个配置的节点都会存储相同的数据,如果将每个节点和拆分表 left join 的结果进行简单的 union all 合并,会造成数据的重复 , 不能保证数据的准确性 。有些小伙伴可能猜想 union 不是会保证数据不重复吗?如果用 union 是否可行?同样分析一下 。
上述结果仍然得不到我们想要的结果,因为 union 只是解决数据重复的问题,不适用于因为分片而导致的数据重复问题;试想一下,如果 DBLE 未来通过某种算法可以对各个节点的结果集做一个准确的合并 , 那么这样的问题也就迎刃而解,也会性能方面有个整体的提升 。
实际上我们想象中的 X 算法还没有一个良好的实现和证明,但现在又要解决查询正确性的问题,那么 dble 是怎么做的呢?下面我们来看下 dble 的执行计划:
从上面执行计划来看 , 简单分析下流程:
dble 内部对于这种查询作出了一些区分:全局表只会下发一个实例,拆分表都会下发,然后针对结果做合并,这种处理逻辑肯定是没有错误的,只不过执行计划看起来相对复杂一些,这也代表在 dble 内部实现层面上下了不少功夫,但是这也是为了保证数据准确性而作出的一些牺牲吧 。
文章知识点与官方知识档案匹配
云原生入门技能树首页概览
8118 人正在系统学习中
打开CSDN , 阅读体验更佳
最新发布 clickhouse--join操作汇总【semi、anti、any、asof、global、colocate、cross】
clickhouse--join操作汇总【semi、anti、any、asof、global、colocate、cross】
继续访问
PHP与JSON的一些常用操作
PHP把数据写入JSON文件 ?php // 生成一个PHP数组 $data = https://www.04ip.com/post/array (); $data ["fruit"] = "apple" ; $data ["animal"] = "tiget"; // 把PHP数组转成JSON字符串,写入文件 $json_string = json_encode( $data ); ? PHP读取JSON数据? ?php // 从文件中读取数据到PHP变量 $str = file_get_contents ( 'one
继续访问
clickhouse的left join、any right join、any left join实验
drop table jiakai.testJoin1 CREATE TABLE jiakai.testJoin1( id String , b String ) ENGINE = MergeTree ORDER BY id SETTINGS index_granularity = 8192 CREATE TABLE jiakai.testJoin2( id String , b String ...
继续访问
记住left join最简单的方式
参考 简单粗暴如下: 表a aid adate 1a1 2a2 3a3表b bid bdate 1b1 2b2 4b4 select * from a left join b on a.aid = b.bid结果 1a1b1 2a...
继续访问
mycat分片JOIN , 分片规则
mycat 支持跨分片join,主要有四种方法: 1、全局表 字典表(变动不频繁,数据量总体变化不大 , 数据规模不大很少超过10W条记录)可以做为全局表 特性: 1)全局表的插入,更新操作会实时在所有节点上执行,保持各个分片的数据一致性 2)全局表查询只从一个节点获取 3)全局表可以和任何一个表进行JOIN操作 配置: 不用写rule规则,要在所有节点为执行DDL语句 2、ER
继续访问
clickhouse多表join和子查询的出现错误修复
1,因业务需要,需要对多张表进行join , 但是进行子查询是出现问题,通过问题排查,发现在子查询需要把两张表的join进行别名处理 。1.1 错误代码如下: select a.dd,a.sourcetype ,count(distinct a.imei) pv ,countDistinct(a.imei) uv ,countDistinct(a.user_id) uv2 ,countDistinct(case when a.click='是' then a.imei end) pv_click ,cou
继续访问
mysql的join适合拆分_MySQL在LEFT JOIN查询中拆分左表以提高性能
我有以下的MySQL查询:SELECT pool.usernameFROM poolLEFT JOIN sent ON pool.username = sent.usernameAND sent.campid = 'YA1LGfh9'WHERE sent.username IS NULLAND pool.gender = 'f'AND (`location` = 'united states' O...
继续访问
ClickHouse查询分布式表LEFT JOIN改RIGHT JOIN的大坑
ClickHouse查询分布式表LEFT JOIN改RIGHT JOIN的大坑 由一个慢查询衍生出的问题 我们线上有一个ClickHouse集群, 总共6个服务器, 配置均为16C 64G SSD, 集群配置为三分片两副本 有两个表这里称为small_table和big_table. 都是ReplicatedMergeTree引擎(三个分片两个副本). small_table有79w数据, big_table有5亿数据(数据在之后的示例中没有任何变化), 在下文中small_table和big_table都
继续访问
sqlserver leftjoin出现重复数据_分布式 | Global 表 Left Join 拆分表实现原因探究
作者:郭奥门爱可生 DBLE 研发成员,负责分布式数据库中间件的新功能开发 , 回答社区/客户/内部提出的一般性问题 。本文来源:原创投稿*爱可生开源社区出品,原创内容未经授权不得随意使用 , 转载请联系小编并注明来源 。本文关键字:JOIN、原理解析、分库分表问题前几天,社区交流群一个小伙伴提出这样一个问题:小伙伴说:全局表和分片表的左连接能否支持 -- 目前测试 Mycat 结果不对 。很显然是想要脱坑的 ...
继续访问
ClickHouse sql优化技巧
1.使用分区 clickhouse的表,走索引和非索引效率差距很大,在使用一个表进行查询时,必须限制索引字段 。避免扫描全表 确定索引分区字段 , 可以用show create table default.ods_user,查看本地表的建表语句,partition by 的字段就是分区字段 。如果需要限制的时间和分区字段不是同一个字段时,可以扩大分区字段取数区间,然后再过滤 2.distinct 和 group by 优先使用group by , distinct满足不了的情况 , 可以使用group by, 如果c
继续访问
【ClickHouse系列】分布式下的IN/JOIN及GLOBAL关键字
分布式下的IN/JOIN 如果是在单机情况下,涉及到IN/JOIN时是没有什么问题的,但是在分布式情况下就不一样了,ClickHouse是支持多分片多副本的,创建表也提供了友好的ON CLUSTER [name]的方式 , 所以就是建议使用者将数据进行分片处理增加读的效率,但也随之产生了单节点数据不完整的问题 。如果SQL中涉及子查询就不得不有特殊的处理方式 。ClickHouse中的分布式子查询 在ClickHouse中为了方便做分布式查询,特意提供了Distributed表引擎,这个表引擎实际上是不存储数据的
继续访问
clickhouse SQL查询语句 【译自Github 英文文档】
内容有缩减,原文请点击这里创建数据库CREATE DATABASE [IF NOT EXISTS] db_name创建表CREATE TABLE可以有几种形式 。创建一张表 , 最好指定引擎结构CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATER...
继续访问
Sql中Left Join、Right Join、Inner Join的区别
【原创】猿人谷2019-06-12 10:49:52 left join(左联接):返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接):返回包括右表中的所有记录和左表中联结字段相等的记录 inner join(等值连接): 只返回两个表中联结字段相等的行 举例如下: 表A记录如下: aID aNum 1 a2005011...
继续访问
【php分布式数据库架构 php 分布式架构】ClickHouse Join篇
join: 1.Alter table mt drop partition '' 可删除本地分区 集群表的分区需要依次删本地表 alter table dwd_dms_msg_detial_di drop partition ('201912','20191226') 2.join 减少列,临时表不能起别名 , 只能更改字段名 避免冲突模糊不清 3.普通join数据发到远程服务器形成右表 gl...
继续访问
Clickhouse 分布式子查询——global in/join(慎用慎用)
@羲凡——只为了更好的活着 Clickhouse 分布式子查询——global in(慎用慎用) 不能一味的追求查询效率,将分布式子查询都改成global in,一定要结合业务逻辑 假设:有一个分布式表,字段班级、姓名、年龄 , ck集群有两个分片 class name age 102 EEE 10 102 GGG 10 103 DDD 8 103 BBB 9 103 AAA 10 103 CCC 10 103 GGG 11 1、建表语句 CREATE TABLE t
继续访问
【数据库】HIVE SQL -left join (on 和 where条件放置的区别)
在使用left join的过程中,总是遇到一个问题,就是将条件放在on中还是where条件中 。在查过一些资料和实际操作后,总结了一下: 在多张表连接时 , 都会生成一张中间表,然后再将这张临时表返回给用户 。在用left join中,on和where条件的区别如下: (1)on条件是在生成中间表时使用的条件,它不管on中的条件是否为真,都会返回左表中的记录 。...
继续访问
热门推荐 数据库多表查询之 where和INNER JOIN
在多表查询中 , 一些SQL开发人员更喜欢使用WHER...
继续访问
Apache Doris和ClickHouse的深度分析
背景介绍Apache Doris是由百度贡献的开源MPP分析型数据库产品,亚秒级查询响应时间,支持实时数据分析;分布式架构简洁,易于运维,可以支持10PB以上的超大数据集;可以满足多种数据分析需求 , 例如固定历史报表,实时数据分析,交互式数据分析和探索式数据分析等 。ClickHouse是俄罗斯的搜索公司Yandex开源的MPP架构的分析引擎 , 号称比事务数据库快100-100...
继续访问
SQL 多表查询之 where和INNER JOIN
SQL多表查询之 where和INNER JOIN【基础查询和效率分析】 转载Michaelwubo最后发布于2018-07-05 10:40:47阅读数 18057收藏-...
继续访问
JOIN
php能实现分布式数据库吗?可以实现.
将数据库放在不同的服务器上,主页的不同模块可以单独访问自己所需要的数据库,以减轻单独一个服务器的压力.
既可以每个模块都是不同数据库,也可以同个模块不同数据库,但这样没什么意思.
实际上,现在网络带宽大,服务器性能也好,再加以磁盘阵列保证数据.如果吞吐量大得惊人,没必要用分布式的,必竟维护比较麻烦.
象很多网络游戏在线人数那么多,或者象天涯猫扑那样,才需要用分布式,普通网站就几乎都用集中式的.
php mysql分布式数据库如何实现当前做分布式的厂商有几家,我知道比较出名的有“华为云分布式数据库DDM”和“阿里云分布式数据库”,感兴趣可以自行搜素了解下 。
分布式数据库的几点概念可以了解一下 。
数据分库:
以表为单位 , 把原有数据库切分成多个数据库 。切分后不同的表存储在不同的数据库上 。
以表中的数据行记录为单位,把原有逻辑数据库切分成多个物理数据库分片,表数据记录分布存储在各个分片上 。
路由分发:
在分布式数据库中,路由的作用即将SQL语句进行解析,并转发到正确的分片上,保证SQL执行后得到正确的结果,并且节约QPS资源 。
读写分离:
数据库中对计算和缓存资源消耗较多的往往是密集或复杂的SQL查询 。当系统资源被查询语句消耗,反过来会影响数据写入操作,进而导致数据库整体性能下降 , 响应缓慢 。因此,当数据库CPU和内存资源占用居高不下,且读写比例较高时,可以为数据库添加只读数据库 。
.PHP和.NET的优缺点是什么?php有点是移植性好,在windows、linux都可以使用 , 专门用于开发网站的 。缺点嘛就是太多配置的地方,不同的程序可能需要单独配置下php.ini,这样一台服务器放很多站点就可能存在不兼容 。
.net可以用于做网站 , 也可以做软件 , 仅支持windows,优点是有很多模块,开发速度很快,缺点就是和系统过度集成,安全性不是很好 。
php的memcached分布式hash算法,如何解决分布不均?crc32这个算法没办法把key值均匀的分布出去memcachedphp分布式数据库架构的总结和分布式一致性hash
当前很多大型的web系统为了减轻数据库服务器负载php分布式数据库架构,会采用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),其php分布式数据库架构他位置(包括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.totalWeightfor ( int i = 0; ithis.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; iservers.length; i) {
// 计算当前server的权重
int thisWeight = 1;
if ( this.weights != nullthis.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; jfactor; 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 ; h4; 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.totalWeightfor ( int i = 0; ithis.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; iservers.length; i) {
// 计算当前server的权重
int thisWeight = 1;
if ( this.weights != nullthis.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; jfactor; 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 ; h4; 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分布式数据库架构和php 分布式架构的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。

    推荐阅读