技术选型之分布式数据库、ZooKeeper

发布于: 2020 年 07 月 14 日

分布式数据库

在分布式应用中,数据库必然要承担高并发的读与写,那我们如何来提高数据库读的能力,采取的方案读写分离,主库负责写,从库负责读。数据库的主从复制是根据binlog来进行复制的,binlog有三种模式:

  • row:记录每一行数据被修改的形式

  • statement:记录每一条会修改数据的sql

  • mix:前两种模式的结合

在实际的运用中,我们还会采用一主多从,即多个从服务器从主服务器复制数据,这样做就可以做到专机专用,分摊负载,比如大数据平台的数据采集可以到从A上拉数据,数据统计模块可以到从B上统计,业务模块可以在从C上查询数据,不同的业务场景用不同的从数据库,降低每台从服务器的负载。

复制只是提高了读的能力,那如何增加写的能力,采取的方案是数据分片,将数据分别存储到不同的数据库schema或者table中,这样就能将写的压力分散到不同的表中,例如用户A的数据写到schemaA的table1中,用户B的数据写到schemaB的table2中。但是这里存在一个问题,就是如何将用户A的数据路由到schemaA的table1中,用户B的数据路由到schemaB的table2中,这里有几种方案:

  • 硬编码的方式,直接在程序里算需要路由到哪个schema的那张表,好处就是简单,但是不通用。

  • JDBC代理,使用简单,无运维成本,性能更好。例如Sharding-JDBC

  • 分布式数据库中间件,对应用透明,就像操作单机数据库一样,需要额外的运维成本。

  • 映射表的方式,这种方案会需要两次查询,而且映射表的压力也会比较大。例如Mycat

数据分片也会带来很多问题,如:

  • 扩容:如果容量不够,就会涉及到数据迁移。解决方案:在分库分表初期就需要规划好分多少个schema,早期多个schema在一个库上,后期出现性能问题只需要按schema来进行迁移。

  • 分布式事务:当写操作涉及到多个库,就需要分布式事务来保证数据的一致性。例如Seata

  • join操作:如果中间件不支持,则需要自己在应用层实现。

  • 唯一ID:没有唯一的ID标识一条记录,需要分布式唯一ID生成器来生成唯一ID。

  • 数据统计,查询需求:如订单按买家ID进行路由,那卖家查询订单就会很困难,这时可以把数据异构到NoSQL存储系统里满足各种条件的查询需求。

zookeeper

脑裂:在一个分布式系统中,不同服务器获得了互相冲突的数据信息或者执行指令,导致整个集群陷入混乱,数据损坏。通俗点说就是一个系统中出现了多个master节点,为什么会发生这种情况,一般分布式系统为了保证高可用,一定会部署一个master以及一个slave,当master和slave的连接断了的时候,slave会认为master出问题,所以它把自己选成master,导致任务会提交到这两个master上执行,会导致执行冲突。这个时候就需要有一个系统来进行仲裁哪一个是唯一的master,而我们可以采用zookeeper来进行仲裁,但是zookeeper本质上也是一个分布式系统,它会不会发生脑裂呢?不会,它会通过过半机制来防止脑裂,也即超过半数的follower同意之后才会竞争到leader。

zookeeper是一个由多个 server 组成的集群,一个 leader,多个 follower以及observer,如下图:

  • leader:负责投票的发起和决议,更新系统状态。

  • follower:接收客户端请求,在选主的过程中参与投票。

  • observer:接收客户端请求,在选主的过程中不参与投票。

zookeeper提供了一个类似文件系统的数据组织方式和命名空间,如下图所示:

zookeeper的应用场景:

  • 动态配置管理:将配置文件放在zookeeper中,客户端watch这个配置,一旦配置被修改,所有客户端都能收到修改之后的配置。

  • 集群管理:服务上线时将节点信息注册到zookeeper中,下线时将节点信息从zookeeper中删除,调用方通过watch机制能随时感知到服务节点的变化情况。在RPC服务框架中经常会用到。

  • 分布式锁:集群环境下,定时任务只能由一台节点来执行(未用分布式调度),创建zookeeper节点成功的机器执行定时任务,不成功的则不执行。

发布于: 2020 年 07 月 14 日 阅读数: 8
用户头像

olderwei

关注

还未添加个人签名 2018.04.26 加入

还未添加个人简介

评论

发布
暂无评论
技术选型之分布式数据库、ZooKeeper