分布式数据分布及数据库分库分表

分布式需求:

1、流量需求:
随着数量的变大,要求系统的性能和内存也会变高,最简单的方法就是需要一台性能超级强悍能抗上千万并发,能存储千亿级别的数据,但是这是不可能的,就算可能也是需要昂贵的成本,所谓一个诸葛亮锤不过三个臭皮匠,分布式就应运而生了。主从复制分离读写、负载均衡分散流量、垂直扩容纵向扩容、消息队列缓冲流量、缓存、限流削峰等手段实现大流量的承载
2、分布式一致性需求:
针对以上的需求,所以最简单的方法就水平扩展机器,利用增加机器的方式,集群处理。一匹马拉不动就一群马拉,这个就是分布式要达到的目的,但是分布式就要涉及数据的分布,事务的一致性等诸多问题,就如同如何训练好马群的方向和整体方向一致,避免马群不能同心协力马都向不一样的方向跑的尴尬局面。

分布式一致性主要有:2PC、3PC、基于XA的事务、ZAB协议、基于消息性事务、TCC事务补偿等
数据分布式主要有:哈希取模、一致性哈希、虚拟节点、顺序分布等


分布式的数据分布方法

分布式分布主要方法有两个:哈希分布和顺序分布

一、哈希分布

哈希分布就是将数据计算哈希值之后,按照哈希值分配到不同的节点上。例如有 N 个节点,数据的主键为 key,则将该数据分配的节点序号为:hash(key)%N

哈希分布算法存在一个问题:当节点数量变化时,也就是 N 值变化,那么几乎所有的数据都需要重新分布,将导致大量的数据迁移。

解决方案:

1、节点翻倍扩展

翻倍扩展节点,差不多只需要50%的数据需要迁移,减少迁移的数据量
缺点:但是这个方案的迁移的数据量50%,如果是数据规模特别大的应用,这个方案也就不适合了

2、一致性哈希算法

  • 1.将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1,整个哈希空间环就是下图中的黑色圆环

  • 2.对每个服务器的唯一识别标志(IP或者主机名)求hash值,将得到的值放入第一步的圆环中对应的位置。如下图的node1 node2 node3 node4

  • 3.对要保存的数据的key求hash值,将得到的值落入圆环中,就是下图的黄色圆圈,然后在圆环中顺时针找到最近的node(服务器的唯一识别标志(IP或者主机名)求hash值落在圆环中所在的点),该数据就存储在该node中

这时增加了一个节点node5,通过hash后落在了如图的位置,这时我要迁移的数据就只是,由于这个环要符合顺时针的顺序,所以需要迁移的数据只是node1节点和node5节点之间的数据,而不会影响其他的节点的数据

缺点:
1、一致性哈希解决了数据迁移量大的问题,但只是减轻了插入节点顺时针开始遇到的第一个机器负担,对于其他的节点并未起到减轻负载的作用。
2、服务节点太少时,数据分布不够均匀,容易因为节点分部不均匀而造成数据倾斜问题。

3、虚拟节点算法

这个主要是解决了一致性哈希的负载性差,数据分布不够均匀的问题,是一致性哈希的改进

假设我们部署了cache A 节点和 cache C节点 。现在我们将cache A 节点虚拟成如图的cache A1和cache A2,将cache C节点虚拟成如图的cache C1和cache C2,一共存在 4 个虚拟节点, hash(objec1)=key1->cache C2 ;hash(objec2)=key2->cache A1 ; hash(objec3)=key3->cache C1 ; hash(objec4)=key4->cache A2 ;因此对象 object4 和 object2 都被映射到了 cache A 上,而 object3 和 object1 映射到了 cache C 上。由于节点虚拟后节点相对分散,因此负载性和数据分布均匀性得到了提升

二、顺序分布:

顺序分布的数据划分为多个连续的部分,按一定顺序分布到不同节点上,可支持顺序访问。

缺点:数据的分布均匀性,容易造成节点的数据倾斜。例如:按照上面的例子,顺序分布假设每个节点最多存33个数字,那么此时需要4个节点,节点1存数字1~ 33,节点2存数字34 ~ 66,节点3存数字67 ~ 99,节点4存数字100.

哈希分布与顺序分布的区别特点

数据库的分库分表

主从数据库主要是分担了数据库的读压力,分库分表主要解决数据库写的压力,基于分布的横行扩展对数据库进行架构的拆分包括:垂直分库、水平分库、垂直分表、水平分表。

一、分库:

使用MyCat其实会更有效率,并且能解决分库后的路由问题,下面的分库的原理

垂直分库:

可以把多个表按业务耦合度归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同时能提高整体架构的业务清晰度,不同的业务库可根据自身情况定制优化方案。但是它需要解决跨库带来的所有复杂问题(一般使用MyCat)。

如图主要讲一个数据库的表分散到不同的节点上

水平分库:

可以把一个表的数据(按数据行)分到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能。它不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(一般使用MyCat)

水平分库全局还要解决的就是全局的自增id,全局自增id就是需要被hash计算的那个值,这个值需要保证不重复,可以使用redis生成,也可以使用MyCat解决

水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。

二、分表

当表的数据量达到一定量级后需要对表进行垂直拆分和水平拆分

垂直分表:

垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。

通常我们按以下原则进行垂直拆分原则:

  • 1、把不常用的字段单独放在一张表;
  • 2、把text,blob等大字段拆分出来放在一张表中;
  • 3、把经常组合查询的字段放在一张表中;
  • 4、拆分的表要一对一关系

水平分表:

水平拆分是为了解决单表数据量过大的问题,表的行数超过百万行时,再完美的优化也是无济于事,这时可以把一张的表的数据拆成多张表来存放。
方法:hash(id)%N
通常是对表中的id进行hash运算,然后进行取模,拆成多少个表就取多少模,例如将表拆成5个,就是hash(id)%5

MyCat垂直分库演示

条件有限,下面是截取慕课教程视频的图,需求就是把node1的imooc_db这个库进行垂直分库,将其分散到下面到下面的node2的order_db库,node3的product_db库,node4的customer_db库去,分库后数据库的逻辑库名依旧是imooc_db,这里Mycat服务器和node1同一个服务器
  • 1、下面先配置各个节点的逻辑库和逻辑表,在schema.xml文件配置

    进入MyCat的conf文件夹修改schema.xml,先配置物理节点的地址<dataHost>和<dataNode>数据库节点的名称,及各个库的用户名密码逻辑库名称可以和数据库名称不一样(一般和原来的那个一样,这样代码中的sql就不用修改),配置逻辑表,逻辑表的名字要和节点上的数据库的表名一样
  • 2、配置MyCat的端口、用户、密码加密、逻辑数据库名称,在server.xml中配置

    在server.xml中配置
  • 3、启动MyCat

    利用mysql登录MyCat查看逻辑库
    查询时都是通过MyCat,用起来和没分库之前是没什么区别的
  • 4、全局表创建:但是MyCat的跨分区能力很差,通常像字典表这样关联查,跨分区非常不友好,我们需要建立全局表,在原来的schema.xml中加上这个配置

MyCat水平分库演示

需求是把MyCat服务器设置在node1中,需要对订单表order_master水平分库到node2的order01和order02,node3的order03和order04
  • 1、schema.xml中配置物理节点的地址<dataHost>和用户名密码,这里为什么要把MyCat所在的节点也配进去呢,主要是用于后面用MyCat提供的数据库方式的全局自增id功能

    配置要分片的库填写逻辑表及分片规则的名称,这个一般和垂直分库混合配
  • 2、水平分片时才需要配置算法。配置分片算法,根据在schema.xml配置的算法名称,配置rule.xml文件,算法是MyCat提供的类<class>,<count>分多少个库就配多
  • 3、server.xml和垂直分库的时候一样的,先对MyCat的密码进行加密,然后填写MyCat启动端口、用户名密码,逻辑库名称等,但是sequnceHandlerType需要改,

    sequnceHandlerType有四值如下:

0 为本地文件方式,1 为数据库方式,2 为时间戳序列方式,3 为分布式ZK ID 生成器,4 为 zk 递增 id 生成。

现在通过数据库方式生成全局id,创建一个数据库mycat

一般在MyCat所在的节点数据库创建,然后在conf中找到dbseq.sql文件,将其导入mycat数据库dbseq.sql文件是创建了MYCAT_SEQUENCE表和4个函数mycat_seq_setval、mycat_seq_nextvals、mycat_seq_nextval、mycat_seq_currval,这个表是用于全局自增id的在schema.xml中增加一个节点配置

然后修改配置文件sequence_db_conf.properties,这里是我们刚刚配置的节点名称叫mycat:执行sql插入要自增的字段的配置,并且是从1开始将schema.xml中的分片表标签添加autoIncrement="true":
  • 4、重启mycat,利用mysql登录MyCat,插入数据,然后查询用起来是和没分片是没有什么区别的,插入两条数据然后对id 2808验证,利用函数对2808进行hash取模发现得0,意思是这个数据是实际插入到了order01的库中
  • 5、

    又是跨分片的关联需要解决,分片表一般比较大,使用全局表一般会插入比较频繁,所以需要建立er分片,需要在所有的节点上创建关联的表,这里我们关联的是order_detail表各个分片都创建一次这个order_detail表修改schema.xml中的配置,将之前order_detail节点的信息去除,在order_master节点中添加子节点order_detail节点:再次修改配置文件sequence_db_conf.properties添加order_detail节点

    执行SQL插入要自增的字段配置,刚刚我们配置了ORDER_DETAIL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章