数据库分片以及schema概念

目录

前言

一,为什么需要分库分表

二,分库分表的最好方式

三,schema的存在

四,多shard会产生的问题


前言

这部分是数据库相关,思路是从数据库分库分表需求思路求解到一个数据库概念中很难懂的部分--schema。这两部分本来是不大相关,这里努力从逻辑上贯通便于更好地去理解schema存在的意义,并且尽量从业务上涵盖这种逻辑的发展趋势及痛点。

同时,有些是老生常谈的话题,甚至在我之前的blog也有提及很多,这里重新做一次归纳。

一,为什么需要分库分表

数据库两大瓶颈:IO和CPU

其中IO瓶颈就是读写,处理请求的网路带宽不够或者热点数据太多,缓存放不下,导致所有的数据请求打到数据库,每一次查询产生大量IO降低查询速度;CPU指执行层我们数据处理的问题,比如SQL大量join,order by,非索引字段查询会带来大量CPU负荷,单表数据量过大也会导致CPU利用率过高。

这两大瓶颈会直接造成数据库可用连接数减少,用户的角度感觉就是后台崩了(服务不可用)。

针对不同瓶颈都要有切实可行的方案去解决或者缓解流量压力,就算你再人傻钱多,也肯定要做合理的解决方案,否则就会出现某个节点跪了,重要业务取不出来导致全局不可用的情况。以后别人说某app后台崩了,你就可以知道这其实是业务层压力过大IO和CPU瓶颈限制导致的部分业务不可用,请求数据发不出来而造成的系统延迟或者服务失灵。

分库分表的逻辑也很简单,你数据多搞跨服务器是吧,我把业务数据合理分散管理,最大限度利用硬件资源提供数据服务就好。


二,分库分表的最好方式

这里小标题取得有点大,用意是以探讨地方式考虑数据库上云这一概念,从分库分表说起。

曾几何时我们以为这样的形式是最好的框架:

                                    fig.1微服务架构

但数据层的割裂必定导致业务层需要更高的复杂度去弥补,再加上数据的流动,维护成本可能更多,所以架构的选择只能是因业务而已,微服务架构以现在的是叫看肯定不是未来的架构。

我们所需要的是这样的数据库:

                              fig.2 数据库改进

这个数据库可以合OLTP和OLAP引擎为一身,做数据的弹性调度,甚至可以感知业务特点智能地去调度数据产生数据消化数据,这一部分智能在数据层比业务层更有理有效,云能力的加持更突出数据库有能力是未来技术潮流的代表,数据层的智能化运维才能真正意味着强人工智能落地的信号,在通讯条件腾飞的未来推进科技的发展。

扯远回到现实,那么基础中的基础,把一个数据库合理分库分表的基本概念就很重要。

水平分库

概念:以某一字段为依据,按照一定策略把一个库中的数据拆分到多个库中。

注意是一库分多库,每个库都不一样,库数据的合集是整个数据。这么做数据库变多,肯定会缓解io和CPU瓶颈。一般人的想法就是这个,不过热点数据固定在表里,service层就很难做,业务变化可能要不断调整策略避免跨数据库查询,表数据过大就要水平分表

水平分表

概念:以字段为依据,按照一定策略将一个表的数据拆分到多个表上。

和水平分库一样,可以防止单个数据库读写过多,但这么做会把压力给到sql优化上,毕竟一次join的消耗是很高的。

垂直分库

概念:以表为依据,按照业务归属不同,将不同的表分到不同的库中。

每个库的结构会不一样,数据也不一样,有点像fig.1的按照不同业务分库,但有时候同一业务不同数据用途的划分也叫垂直分库,一些公用的配置表可以拆分到单独的库甚至服务化。

垂直分表

概念:以字段为依据,按照业务归属不同,将不同的字段拆到不同的表中。

同一张表,热点数据和主键在一起做热点数据表可以放到缓存,非热点数据和外键放在一起作为扩展表,要想获得所有数据就要关联两个表获取数据。

市面上有很多分库分表中间件工具jar包,一般原理都是根据容量评估分库或分表个数,选key执行分表规则,并可以进行扩容


三,schema的存在

schema到底是什么?

如果查百度知乎,他们会告诉你:

schema是数据库的组织和结构,模式中包含了schema对象,可以是表(table)、列(column)、数据类型(data type)、视图(view)、存储过程(stored procedures)、关系(relationships)、主键(primary key)、外键(foreign key)等。数据库模式可以用一个可视化的图来表示,它显示了数据库对象及其相互之间的关系。

其实打开mysql benchmark你会找到用可视化的图来表示的数据库模式:

                                      fig.3 mysql schema

概念其实也很清楚了,schema就是用作表示数据库对象及其相互之间的关系。但这个概念其实远远不止于此,在使用过程中show/create/drop schema和show/create/drop databases的SQL语句相同,这就更迷惑了,那么schema和database的区别是什么?

然后大家会告诉你schema的定义取决于数据库供应商,每个数据库供应商提供的内部schema定义以及实现是不同的:

比如MySQL的文档中指出,在物理上,模式与数据库是同义的,所以,模式和数据库是一回事;Oracle的文档却指出,某些对象可以存储在数据库中,但不能存储在schema中。 因此,模式和数据库不是一回事;SQL Server的schema是内部的一个独立的实体。

所以说schema是数据库供应商为了某些原因创造出服务于整体数据库的一个概念,那么这个原因是什么,为什么都要设定schema这个概念呢?这就回到了上边说的分库分表的问题。

我们在划分物理数据库和表的时候,往往称为分片(shard),导致后端数据库往往有两种类型,一种为多Shard,一种为单Shard,Shard数量满足2的整数次幂。这样就导致了,假如有两张表,一张表为分区表用于分表,而另外一张表为普通表不需要分表,则需要在建表是显式的将两者分到不同的database中,分区表分到多Shard的database中,而普通表分到单Shard的database中。

然而这样分片就导致了我前边提到的问题,一个业务请求的数据可能会影响到不同数据库,跨库操作会很影响性能。在mysql中,Schema就是一种解决方案,其实是为了区分物理database和逻辑database的。面对分片,对上层隐藏database的概念,转而用Schema进行代替(注意,因为要对外隐藏整个database,这边的Schema不仅要代表Schema,还要代表Database,show databases和show schemas是一个结果。)


以下是例子,用于理解概念,具体数据库要具体结合schema分析

如下图我们在两个物理数据库k1 shards和k2 shards中执行分片,k1被分为了4片,每一片对应一个逻辑上的database和其对应 的tables;k2被分为两片,每一个shard对应一个逻辑上的database和其对应的tables。

k1 shards

database

tables

k2 shards

database

tables

shard_1_1     shard_2_1    
shard_1_2     shard_2_2    
shard_1_3        
shard_1_4          

当我们在k1创建schema db1时对应存储如下,在新建一个schema后,会在所有的shard上新建一个数据库,为k1_db1,这个主要是为了schema之间的隔离,因为不同的schema中可能存在同名的表,如果恰巧在同一个shard,同一个数据库中,就会发生冲突,而在外部看来是不应该冲突的,所以在每个shard上用数据库进行隔离。

k1 shards

database

tables

k2 shards

database

tables

shard_1_1 k1_db1   shard_2_1 k2_db1  
shard_1_2 k1_db1   shard_2_2 k2_db1  
shard_1_3 k1_db1      
shard_1_4 k1_db1        

此时再use db1 创建一个普通表a1和创建一个分片表b1就会如下:

k1 shards

database

tables

k2 shards

database

tables

shard_1_1 k1_db1 a1,b1 shard_2_1 k2_db1  
shard_1_2 k1_db1 b1 shard_2_2 k2_db1  
shard_1_3 k1_db1 b1    
shard_1_4 k1_db1 b1      

所以你在外面看到的database其实是封装好的schema,你真正用到的物理上的keyspace和逻辑上的database以及在内部完整转化了,其中用到的就是上边的分库分表原理。

再次声明,每个数据库可能设计的分片算法有所不同,以上只是例子去引导如何理解schema这个概念。


四,多shard会产生的问题

首先说,当然还有一系列缓存数据库做流量分持,使用缓存数据库又会有许许多多的不一致和迁移问题,这里不做利弊判断。

第一,分多shards必定造成数据库研发上的困难,其实这么多概念及优化都是为了能合理解决瓶颈问题,多shard的初衷在此,研发难度自然会提升。

第二,除了研发,运维人员也要合理使用数据库。众所周知很多公司的数据库研发可能其实是DBA,分片提高运维人员的门槛,比如普通表可能只在某个shard上出现,有些表在所有的keyspace上的database都有,有些表是特殊表要怎么存,多shard情况下怎么使用索引(二级索引?),怎样避免跨两个物理库去操作等等

第三,SQL下发策略的制定,对原来数据库中的一切概念多一层Schema的重映射可能性更高,而且每个厂家可能设定策略不同,后边的研发路径就更不相同,“借鉴”就很困难。

总结一下,总体来看,分片之路任重道远,需要投入大量人力物力去开发,而不分片又会导致流量过大瓶颈限制而造成的服务不可用,各大厂商为了合理设计数据库引入schema等一系列概念去做内层设计,外层只暴露sql指令给service使用。

猜你喜欢

转载自blog.csdn.net/wannuoge4766/article/details/105597682