精华内容
下载资源
问答
  • 数据库如何分库分表

    万次阅读 2019-04-29 21:09:52
    刚开始我们只用单机数据库就够了,随后面对越来越多的请求,我们将数据库的写操作和读操作进行分离, 使用多个从库副本(Slaver Replication)负责读,使用主库(Master)负责写, 从库从主库同步更新数据,保持数据...

    数据库架构演变

    刚开始我们只用单机数据库就够了,随后面对越来越多的请求,我们将数据库的写操作和读操作进行分离, 使用多个从库副本(Slaver Replication)负责读,使用主库(Master)负责写, 从库从主库同步更新数据,保持数据一致。架构上就是数据库主从同步。 从库可以水平扩展,所以更多的读请求不成问题。

    但是当用户量级上来后,写请求越来越多,该怎么办?加一个Master是不能解决问题的, 因为数据要保存一致性,写操作需要2个master之间同步,相当于是重复了,而且更加复杂。

    这时就需要用到分库分表(sharding),对写操作进行切分。

    分库分表前的问题

    任何问题都是太大或者太小的问题,我们这里面对的数据量太大的问题。

    用户请求量太大

    因为单服务器TPS,内存,IO都是有限的。 解决方法:分散请求到多个服务器上; 其实用户请求和执行一个sql查询是本质是一样的,都是请求一个资源,只是用户请求还会经过网关,路由,http服务器等。

    单库太大

    单个数据库处理能力有限;单库所在服务器上磁盘空间不足;单库上操作的IO瓶颈 解决方法:切分成更多更小的库

    单表太大

    CRUD都成问题;索引膨胀,查询超时 解决方法:切分成多个数据集更小的表。

    分库分表的方式方法

    一般就是垂直切分和水平切分,这是一种结果集描述的切分方式,是物理空间上的切分。 我们从面临的问题,开始解决,阐述: 首先是用户请求量太大,我们就堆机器搞定(这不是本文重点)。

    然后是单个库太大,这时我们要看是因为表多而导致数据多,还是因为单张表里面的数据多。 如果是因为表多而数据多,使用垂直切分,根据业务切分成不同的库。

    如果是因为单张表的数据量太大,这时要用水平切分,即把表的数据按某种规则切分成多张表,甚至多个库上的多张表。 分库分表的顺序应该是先垂直分,后水平分。 因为垂直分更简单,更符合我们处理现实世界问题的方式。

    垂直拆分

    • 垂直分表

    也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。
    一般是针对那种几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。

    • 垂直分库

    垂直分库针对的是一个系统中的不同业务进行拆分,比如用户User一个库,商品Producet一个库,订单Order一个库。
    切分后,要放在多个服务器上,而不是一个服务器上。为什么?
    我们想象一下,一个购物网站对外提供服务,会有用户,商品,订单等的CRUD。没拆分之前,全部都是落到单一的库上的,这会让数据库的单库处理能力成为瓶颈。按垂直分库后,如果还是放在一个数据库服务器上,随着用户量增大,这会让单个数据库的处理能力成为瓶颈,还有单个服务器的磁盘空间,内存,tps等非常吃紧。
    所以我们要拆分到多个服务器上,这样上面的问题都解决了,以后也不会面对单机资源问题。

    数据库业务层面的拆分,和服务的“治理”,“降级”机制类似,也能对不同业务的数据分别的进行管理,维护,监控,扩展等。数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。
    数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。

    水平拆分

    • 水平分表

    针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。
    但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。

    • 水平分库分表

    将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

    水平分库分表切分规则

    1. RANGE

    从0到10000一个表,10001到20000一个表;

    1. HASH取模

    一个商场系统,一般都是将用户,订单作为主表,然后将和它们相关的作为附表,这样不会造成跨库事务之类的问题。
    取用户id,然后hash取模,分配到不同的数据库

    上。

    1. 地理区域

    比如按照华东,华南,华北这样来区分业务,七牛云应该就是如此。

    1. 时间

    按照时间切分,就是将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据被查询的概率变小,所以没必要和“热数据”放在一起,这个也是“冷热数据分离”。

    分库分表后面临的问题

    事务支持

    分库分表后,就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价; 如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。

    多库结果集合并(group by,order by)
    跨库join

    分库分表后表之间的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表, 结果原本一次查询能够完成的业务,可能需要多次查询才能完成。 粗略的解决方法: 全局表:基础数据,所有库都拷贝一份。 字段冗余:这样有些字段就不用join去查询了。 系统层组装:分别查询出所有,然后组装起来,较复杂。

    展开全文
  • UUID使用Java自己生成的64位的序列码。数字字母混合,无顺序。很难重复 无序的id做为主键给索引重建带来了性能浪费 snowFlake 算法 根据时间戳 + 服务器号 + 自增序列号生成全局一致性id 优点: 毫秒数在高位,...

    自增主键

    拆分了多少张表就使自增主键的自增跨度是多少,这样就是每台机器的Id都是固定的唯一的一套等差数列

    缺点就是不能随意扩容,扩容起来很麻烦

    UUID

    UUID使用Java自己生成的64位的序列码。数字字母混合,无顺序。很难重复

    无序的id做为主键给索引重建带来了性能浪费

    snowFlake 算法

    根据时间戳 + 服务器号 + 自增序列号生成全局一致性id
    在这里插入图片描述
    优点:

    1. 毫秒数在高位,符合递增规则
    2. 不依赖三方数据库
    3. 配置方便

    缺点:
    每台服务器的时间强一致性

    leaf

    有一个单独的服务器对应一张表,表字段包含了当前的号码号段以及每次号段增长的增幅,以及当前的号码使用情况

    程序使用加锁 synchronized 保证每次只能有一个请求去拿号,拿到号之后会对比当前的号码还在不在号码段内,还在号码段内就直接返回,不在号码段内的话就在生成一个号码段,将号码使用情况在填充上

    在这里插入图片描述
    弱依赖zk

    在这里插入图片描述

    展开全文
  • 2、分表后如何实现全局的分页场景? 直接使用 merge 引擎的确很方便,但性能和不分表没什么区别....还是要自己在业务层实现并发检索子表来凸显分表的优势么? 百度的我都看过,测试过就不用发链接了。想...
  • 如何透明化分库分表所带来的影响,让使用方尽量像使用一个数据库一样使用水平分片之后的数据库集群。我们需要解决这个问题。 我们在开发的时候使用了 ShardingSphere 的客户端中间件,sharding-jdbc

    最近工作的重心是容量规划,当系统数据量上来之后。对系统就需要使用分库分表了,分库分表选型的是 apache sharding jdbc,他是通过客户端来对数据源进行分库分表的。

    1、遇到问题

    但是在分库分表之后,不管是开发还是测试,当遇到问题需要查询数据库的时候面对多个库多个表那就比较痛苦了。

    在这里插入图片描述
    如何透明化分库分表所带来的影响,让使用方尽量像使用一个数据库一样使用水平分片之后的数据库集群。我们需要解决这个问题。

    我们在开发的时候使用了 ShardingSphere 的客户端中间件,sharding-jdbc 来开发。当我们需要查询数据的时候可以使用它里面的另外一个中间件,基于服务端的中间件 sharding-proxy。

    2、sharding proxy

    ShardingSphere-Proxy是ShardingSphere的第二个产品。 它定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前先提供MySQL/PostgreSQL版本,它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat等)操作数据,对DBA更加友好。

    • 向应用程序完全透明,可直接当做MySQL/PostgreSQL使用。
    • 适用于任何兼容MySQL/PostgreSQL协议的的客户端。
      在这里插入图片描述
    ~ ShardingSphere-JDBC ShardingSphere-Proxy ShardingSphere-Sidecar
    数据库 任意 MySQL/PostgreSQL MySQL/PostgreSQL
    连接消耗数
    异构语言 仅Java 任意 任意
    性能 损耗低 损耗略高 损耗低
    无中心化
    静态入口

    ShardingSphere-Proxy的优势在于对异构语言的支持,以及为DBA和测试人员提供可操作入口。

    3、安装和配置

    可以通过 官方下载路径 下载最新的 sharding-proxy 目录。
    在这里插入图片描述
    不过我们可以在本地从 github下载 sharding-sphere 项目.sharding-proxy 包含这个项目当中。在本地进行调试好了再把配置上文件上放置到 sharding proxy 里面这样就特别方便。因为 sharding proxy 是基于 spring boot 的项目,它可以很方便的进行启动。

    3.1 sharding proxy 项目结构

    下面就是 sharding proxy 的项目结构,其实和下载的启动配置类似,只不过这个是以 spring boot 的形式启动,而它是以 bat 或者 shell 文件启动。

    sharding-proxy
    	--sharding-proxy-bootstrap
    		--src
    			--main
    				--java
    					--org.apache.shardingsphere.shardingproxy.Bootstrap // 启动类
    				--resources
    					-conf
    						--config-xxx.yaml // 配置分库分表规则
    						--server.yaml       // 配置服务器信息
    				
    

    3.2 分片配置

    下面是分库分表规则,这里只配置了从库,没有配置主库,因为在分片库里面的 id 都是基于数据库的自增生成的。当我们通过 navicat 进行修改数据的时候是通过 Id 修改的,所以当修改一个数据的时候其实是修改了很多数据。如果你的 ID 能够保证全局唯一可以配置主从规则。

    config-pay-engine.yml

    schemaName: pay-engine
    
    dataSources:
      pay_engine_0:
        url: jdbc:mysql://localhost:3306/pay_engine_0?characterEncoding=utf8&useSSL=false
        username: carl
        password: 123456
        connectionTimeoutMilliseconds: 30000
        idleTimeoutMilliseconds: 60000
        maxLifetimeMilliseconds: 1800000
        maxPoolSize: 50
      pay_engine_1:
        url: jdbc:mysql://localhost:3306/pay_engine_1?characterEncoding=utf8&useSSL=false
        username: carl
        password: 123456
        connectionTimeoutMilliseconds: 30000
        idleTimeoutMilliseconds: 60000
        maxLifetimeMilliseconds: 1800000
        maxPoolSize: 50
    
    shardingRule:
      tables:
        tb_collect_pay_order:
          actualDataNodes: pay_engine_${0..1}.tb_collect_pay_order_${0..49}
          databaseStrategy:
            complex:
              shardingColumns: pay_order_no,request_no
              algorithmClassName: cn.carl.pay.engine.sharding.rule.CollectPayOrderModuloShardingDatabaseAlgorithm
          tableStrategy:
            complex:
              shardingColumns: pay_order_no,request_no
              algorithmClassName: cn.carl.pay.engine.sharding.rule.CollectPayOrderModuloShardingTableAlgorithm
    

    sharding-proxy 的分库分表规则可以 sharding-proxy 官网配置手册。因为它的分片规则 demo 只是使用了 hint 分片,所以如果你遇到其它分片算法的话还需要参考 sharding-jdbc 官网配置手册

    3.3 服务端配置

    server.yml

    authentication:
      users:
        root:
          password: root
        sharding:
          password: sharding
    props:
      executor.size: 16
      sql.show: true
    

    通过 sharding proxy 对分库分表的数据源进行代理之后,DBA 或者 测试人员连接代理服务器只会看到一个库一张表了。

    服务端配置同样要参考 sharding-proxy 官方配置手册

    3.4 本地启动

    本地启动成功之后可以使用 navicat 连接服务器。

    在这里插入图片描述
    连接数据源发现只会存在一个库一张表:

    在这里插入图片描述

    4、服务器启动

    其实服务器启动和本地启动类似,你可以把你本地启动的 sharing-proxy 打包成 jar 文件然后通过 java -jar sharding-proxy.jar 启动。

    同时也可以使用 sharding-proxy 官方下载的压缩包启动,在 linux 上是以 shell 脚本启动的。只需要把我们刚才测试好的配置文件写入到:

    • 下载ShardingSphere-Proxy的最新发行版。
    • 解压缩后修改conf/server.yaml和以config-前缀开头的文件,如:conf/config-xxx.yaml文件,进行分片规则、读写分离规则配置
    • Linux操作系统请运行bin/start.sh,Windows操作系统请运行bin/start.bat启动ShardingSphere-Proxy。如需配置启动端口、配置文件位置

    如果后端连接PostgreSQL数据库,不需要引入额外依赖。
    如果后端连接MySQL数据库,需要将mysql-connector-java-5.1.47.jar拷贝到 {shardingsphere-proxy}\lib目录。
    如果算法类需要自己实现,也需要把算法类打成 jar 包拷贝到 {shardingsphere-proxy}\lib目录。

    启动服务

    使用默认配置项

    ${shardingsphere-proxy}\bin\start.sh
    

    配置端口

    ${shardingsphere-proxy}\bin\start.sh ${port}
    

    引用文章:

    展开全文
  • 当团队对系统业务和数据库进行了细致的梳理,确定了切分方案,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架...

    推荐:博主历时三年倾注大量心血创作的大数据平台架构与原型实现:数据中台建设实战一书已由知名IT图书品牌电子工业出版社博文视点出版发行,真诚推荐给每一位读者!点击重磅推荐:建大数据平台太难了!给我发个工程原型吧!了解图书详情,扫码进入京东手机购书页面!

     

    当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架还是自主开发,都会面临一个在哪一层上实现sharding逻辑的问题,本文会对这一系列的问题逐一进行分析和考量。本文原文连接: http://blog.csdn.net/bluishglc/article/details/7766508 转载请注明出处!
     

    一、sharding逻辑的实现层面

     

    从一个系统的程序架构层面来看,sharding逻辑可以在DAO层、JDBC API层、介于DAO与JDBC之间的Spring数据访问封装层(各种spring的template)以及介于应用服务器与数据库之间的sharding代理服务器四个层面上实现。

     

    图1. Sharding实现层面与相关框架/产品

    • 在DAO层实现

    当团队决定自行实现sharding的时候,DAO层可能是嵌入sharding逻辑的首选位置,因为在这个层面上,每一个DAO的方法都明确地知道需要访问的数据表以及查询参数,借助这些信息可以直接定位到目标shard上,而不必像框架那样需要对SQL进行解析然后再依据配置的规则进行路由。另一个优势是不会受ORM框架的制约。由于现在的大多数应用在数据访问层上会依赖某种ORM框架,而多数的shrading框架往往无法支持或只能支持一种orm框架,这使得在选择和应用框架时受到了很大的制约,而自行实现sharding完全没有这方面的问题,甚至不同的shard使用不同的orm框架都可以在一起协调工作。比如现在的java应用大多使用hibernate,但是当下还没有非常令人满意的基于hibernate的sharding框架,(关于hibernate hards会在下文介绍),因此很多团队会选择自行实现sharding。

     

    简单总结一下,在DAO层自行实现sharding的优势在于:不受ORM框架的制约、实现起来较为简单、易于根据系统特点进行灵活的定制、无需SQL解析和路由规则匹配,性能上表现会稍好一些;劣势在于:有一定的技术门槛,工作量比依靠框架实现要大(反过来看,框架会有学习成本)、不通用,只能在特定系统里工作。当然,在DAO层同样可以通过XML配置或是注解将sharding逻辑抽离到“外部”,形成一套通用的框架. 不过目前还没有出现此类的框架。

    • 在ORM框架层实现

    在ORM框架层实现sharding有两个方向,一个是在实现O-R Mapping的前提下同时提供sharding支持,从而定位为一种分布式的数据访问框架,这一类类型的框架代表就是guzz另一个方向是通过对既有ORM框架进行修改增强来加入sharding机制。此类型的代表产品是hibernate shard. 应该说以hibernate这样主流的地位,行业对于一款面向hibernate的sharding框架的需求是非常迫切的,但是就目前的hibernate shards来看,表现还算不上令人满意,主要是它对使用hibernate的限制过多,比如它对HQL的支持就非常有限。在mybatis方面,目前还没有成熟的相关框架产生。有人提出利用mybatis的插件机制实现sharding,但是遗憾的是,mybatis的插件机制控制不到多数据源的连接层面,另一方面,离开插件层又失去了对sql进行集中解析和路由的机会,因此在mybatis框架上,目前还没有可供借鉴的框架,团队可能要在DAO层或Spring模板类上下功夫了。

    • 在JDBC API层实现

    JDBC API层是很多人都会想到的一个实现sharding的绝佳场所,如果我们能提供一个实现了sharding逻辑的JDBC API实现,那么sharding对于整个应用程序来说就是完全透明的,而这样的实现可以直接作为通用的sharding产品了。但是这种方案的技术门槛和工作量显然不是一般团队能做得来的,因此基本上没有团队会在这一层面上实现sharding,甚至也没有此类的开源产品。笔者知道的只有一款商业产品dbShards采用的是这一方案。

    • 在介于DAO与JDBC之间的Spring数据访问封装层实现

    在springd大行其道的今天,几乎没有哪个java平台上构建的应用不使用spring,在DAO与JDBC之间,spring提供了各种template来管理资源的创建与释放以及与事务的同步,大多数基于spring的应用都会使用template类做为数据访问的入口,这给了我们另一个嵌入sharding逻辑的机会,就是通过提供一个嵌入了sharding逻辑的template类来完成sharding工作.这一方案在效果上与基于JDBC API实现的方案基本一致,同样是对上层代码透明,在进行sharding改造时可以平滑地过度,但它的实现却比基于JDBC API的方式简单,因此成为了不少框架的选择,阿里集团研究院开源的Cobar Client就是这类方案的一种实现。

    • 在应用服务器与数据库之间通过代理实现

    在应用服务器与数据库之间加入一个代理,应用程序向数据发出的数据请求会先通过代理,代理会根据配置的路由规则,对SQL进行解析后路由到目标shard,因为这种方案对应用程序完全透明,通用性好,所以成为了很多sharding产品的选择。在这方面较为知名的产品是mysql官方的代理工具:Mysql Proxy和一款国人开发的产品:amoeba。mysql proxy本身并没有实现任何sharding逻辑,它只是作为一种面向mysql数据库的代理,给开发人员提供了一个嵌入sharding逻辑的场所,它使用lua作为编程语言,这对很多团队来说是需要考虑的一个问题。amoeba则是专门实现读写分离与sharding的代理产品,它使用非常简单,不使用任何编程语言,只需要通过xml进行配置。不过amoeba不支持事务(从应用程序发出的包含事务信息的请求到达amoeba时,事务信息会被抹去,因此,即使是单点数据访问也不会有事务存在)一直是个硬伤。当然,这要看产品的定位和设计理念,我们只能说对于那些对事务要求非常高的系统,amoeba是不适合的。

    二、使用框架还是自主开发?

    前面的讨论中已经罗列了很多开源框架与产品,这里再整理一下:基于代理方式的有MySQL Proxy和Amoeba,基于Hibernate框架的是Hibernate Shards,通过重写spring的ibatis template类是Cobar Client,这些框架各有各的优势与短板,架构师可以在深入调研之后结合项目的实际情况进行选择,但是总的来说,我个人对于框架的选择是持谨慎态度的。一方面多数框架缺乏成功案例的验证,其成熟性与稳定性值得怀疑。另一方面,一些从成功商业产品开源出框架(如阿里和淘宝的一些开源项目)是否适合你的项目是需要架构师深入调研分析的。当然,最终的选择一定是基于项目特点、团队状况、技术门槛和学习成本等综合因素考量确定的。

     

     

     

    相关阅读:

    数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案

     

     

     

    数据库分库分表(sharding)系列(四) 多数据源的事务处理

    数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量

     

    数据库分库分表(sharding)系列(二) 全局主键生成策略

     

    数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示

     

    关于垂直切分Vertical Sharding的粒度

    数据库Sharding的基本思想和切分策略

     

     

     

     

     

     

     

    展开全文
  • 16 数据库如何做分库分表,读写分离 宝剑锋从磨砺出,梅花香自苦寒来。 ——佚名 引言 2016年第一次接触分布式微服务项目,我在简历上写了我使用了微服务、分库分表技术,那么问题来了,面试官说接...
  • 文章目录前言配置镜像配置文件server.xml 服务配置文件,包含登录用户配置schema.xml 逻辑表配置rule.xml 分片规则将这三个配置文件放置到固定的位置,方便后面使用启动docker composedocker compose 启动测试 ...
  • 系统里每次得到一个id,往一个库的一个表中插入一条没什么含义的数据,获取到数据库自增的id,将这个id向对应的分库分表中写入。 (2)UUID 本地生成,但是UUID过于长,占用空间大,作为主键性能太差了。且UUID不...
  • 今天来给大家介绍下如何使用JDBC Request跨数据库查询引用查询的结果作为下一个JDBC Request的入参! 因为我现在所测的系统模块中部分表在不同的数据库中,所以在用JDBC Request查询数据的时候遇到了这么一个跨...
  • ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并不适合在Innodb中来作为...
  • 1、分库分表后带来的问题 查询的时候必须带着分区键字段 一个聚合类查询性能比较差,需要考虑使用计数器等其他的解决方案 主键的全局唯一性问题 2、数据库中的主键要如何选择 数据库中的每一条记录都需要有一个...
  • 从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL 协议的的Server,前端用户可以把它看作是一个数据库代理,用MySQL 客户端工具和命令行访问,而其端可以用MySQL 原生(Native)协议与多个...
  • 在实际开发中,数据库的扩容和不同的分库分表规则直接相关,今天我们从系统设计的角度,抽象了一个项目开发中出现的业务场景,从数据库设计、路由规则,以及数据迁移方案的角度进行讨论。 从业务场景出发进行讨论 ...
  • 当团队对系统业务和数据库进行了细致的梳理,确定了切分方案,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 152
精华内容 60
关键字:

数据库分表后如何使用