插写一条数据库操作,请注意查收
一直对数据库分库分表什么都倍感niubility,让我们继续往下看。

分库分表目的

随着业务的增长,表数据的增加,查询一次所消耗的时间会变得越来越长,甚至会造成数据库的单点压力。当数据库已经成为系统性能的瓶颈,这时,通过分库分表,可以减小数据库的单库单表负担,提高查询性能,缩短查询时间,从而提升系统的响应速度。

数据库瓶颈

数据库连接数减少,导致业务类service无连接可用,从而引起并发、吞吐量出现问题,然后崩溃。
下面列举了几种场景对应不同数据库的操作:

IO瓶颈

第一种是磁盘读IO,热点数据太多,导致数据库缓存不够,每次查询都引起大量的IO操作 --》 解决方法:降低查询速度,采用分库和垂直分表操作。
第二种是网络IO瓶颈,请求的数据太多,网络带宽不够 --》 解决方法:分库

CPU瓶颈

第一种是SQL问题,比如sql中包含join、group by、order by、非索引字段条件查询等等,都增加了cpu的运算操作 --》解决方法:sql优化,建立合适的索引。就是sql优化层的操作。
第二种是单表数据量太大问题,查询时扫描的行太多,sql效率低下 --》解决方法:水平分表

分库分表(注意,拍黑板辣,别看错)

水平分

以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。注意是库,分数据库!!不是表,下个点再讲分表。

    1. 水平分库的结果:
      • 每个库的结构都一样
      • 每个库的数据都不一样,也就是没有交集
      • 所有库的并集(合起来)就是全量数据
    1. 场景
      • 系统并发量上来了。这个可以理解,水平分库相当于排队多了几个窗口,处理的数据不相同,但是都是同一类数据,这样就支持高并发量咧,emmm不是并行??可能得深入学学数据框架才能解答
      • 分表难以根本上解决问题,并且还没有明显的业务归属来垂直分库。虽然不明白这句话什么意思,mark下来占个位吧。
    1. 分析
      • 库多了,io和cpu的压力自然可以成倍缓解。(感觉学不下去了,理解无能)
        查了些资料,分库可以放在不同的物理机,避免竞争同一个物理机的CPU、内存、网络IO。是我着相了,继续。

水平分表

以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。

    1. 水平分表的结果:
      • 每个表的结构都一样
      • 每个表的数据都不一样,没有交集;
      • 所有表的并集是全量数据;(跟分库是一样的,只是粒度层面更细了点,从库到表)
    1. 场景
      单表数据量太大了,严重影响sql的执行效率,加重cpu负担。你想想,查一次数据得遍历所有的行才得出结果集,遇到几万甚至几十万行的表,吡。
    1. 分析
      表里数据少了,单次执行sql效率就提高,减轻cpu负担。

到目前为此水平分库和分表都很好理解。那么下面继续垂直分库分表。

垂直分库

基本的思路就是按照业务模块以及表的相关性来划分出不同的数据库,而不是像早期一样将所有的数据表都放到同一个数据库中。

    1. 场景
      系统绝对并发量上来了,并且可以抽象出单独的业务模块。
      随着业务的发展一些公用的配置表、字典表等越来越多,这时可以将这些表拆到单独的库中,甚至可以服务化。再有,随着业务的发展孵化出了一套业务模式,这时可以将相关的表拆到单独的库中,甚至可以服务化(详细看最后一章)。
    1. 分析
      数据库的 CPU、内存、磁盘 IO 、连接资源、网络带宽都是有限的,所以单个物理机上容易出现资源竞争和性能瓶颈。通过垂直分库,一方面,可以解决数据库单点压力过大的问题,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。另一方面,数据库层面的拆分们也有利于我们针对不同业务类型的数据进行“分级”管理、维护、监控、扩展等。因此,垂直分库是大型分布式系统中优化数据库架构的重要手段。

垂直分表

以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。通常就是建立“扩展表”,将不经常使用或者长度较大的字段拆分出去放到“扩展表”中

    1. 垂直分表
      • 每个表的结构都不一样;
      • 每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
      • 所有表的并集是全量数据;
        怎么跟垂直分库是一样的。
    1. 场景
      表中字段多,并且热点数据和非热点数据在一起,单行数据所需的存储空间较大。以至于数据库缓存的数据行减少,查询时会去读磁盘数据产生大量的随机读IO,产生IO瓶颈。
    1. 分析
      可以用列表页和详情页来帮助理解。垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。
      这样更多的热点数据就能被缓存下来,进而减少了随机读IO。拆了之后,要想获得全部数据就需要关联两个表来取数据。但记住,千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。

垂直拆分,其实就是“大表拆小表”,把表的列字段进行拆分,即一张字段比较多的表拆分为多张表,这样使得行数据变小。一方面,可以减少客户端程序和数据库之间的网络传输的字节数,因为生产环境共享同一个网络带宽,随着并发查询的增多,有可能造成带宽瓶颈从而造成阻塞。另一方面,一个数据块能存放更多的数据,在查询时就会减少 I/O 次数。

分库工具

    1. sharding-sphere:jar,前身是sharding-jdbc;
    1. TDDL:jar,Taobao Distribute Data Layer;
    1. Mycat:中间件。

分库分表步骤

根据容量(当前容量和增长量)评估分库或分表个数 -> 选key(均匀)-> 分表规则(hash或range等)-> 执行(一般双写)-> 扩容问题(尽量减少数据的移动)。

切分策略

水平分表策略

这个操作可以归结为两个操作方法,随机分表和连续分表。
比如说取模切分、hash切分就属于随机分表;
按时间维度,id范围切分就属于连续切分。

  • 连续切分
    连续切分可以快速定位到表进行查询,大多数情况下是可以避免跨表查询的。但是连续分表可能存在数据热点问题,有些表可能别频繁查询而造成较大压力。

  • 随机切分

总结

    1. 分库分表,首先得知道瓶颈在哪里,然后才能合理地拆分(分库还是分表?水平还是垂直?分几个?)。且不可为了分库分表而拆分。
    1. 选key很重要,既要考虑到拆分均匀,也要考虑到非partition key的查询。
    1. 只要能满足需求,拆分规则越简单越好。

服务化

服务化:说是这几年比较火的概念,(emmmmmmm完全没听过,这里贴一下查到的资料)。
很多人把一个dubbo接口、一个rpc调用当作服务化,但也有人认为这样理解是非常错误的。
服务和需要的几点:

  • 服务化无关远程,本地,没有Dubbo,RPC,也一样要有服务化。
  • 业务边界清晰
  • 高内聚,低耦合
  • 服务可复用

就拿很多老代码来说,就跟记流水账一样,一个servlet或者一个action把所有需要处理的东西都处理完了,这样同样的业务逻辑假设在另外一个入口需要的时候,基本上就是把代码COPY过去,导致维护起来非常麻烦,当业务需求变动的时候常常需要改动非常多的点,工作量变的非常大,甚至遗漏一些点导致故障。

为了避免这些问题的产生,所以有了服务化的概念,简单的来说,服务化就是一个SERVICE层,都知道SERVICE其实是分好多层的,有封装dao层的service(为了一个数据的整体性,比如一对多的数据获取),还有业务service,其中业务service又因为不同的业务粒度,拆分成更多的service,但是这些service都需要RPC化么?答案当然是否定的,我们要对外暴露的SERVICE其实是最顶层的SERVICE,将我们底层的SERVICE细节给隐藏起来,并不是所有的service都需要对外暴露的,也不要将所有的细节都暴露给第三方。

那么有了服务化后有那些好处?

  • 业务入口统一,修改业务的时候就会非常简单。
  • 服务可扩展性强。
  • 剃除冗余代码。

怎么感觉就跟dubbo什么的功能差不多,都提供接口吡

参考:
https://crazyfzw.github.io/2018/07/29/database-sharding/
https://mp.weixin.qq.com/s/i2eXbU1xrqJY51ETIPs0dw