1. 首页
  2. >
  3. 架构设计

高并发架构-分库分表

为什么要分库分表(高并发系统的时候,数据库层该如何设计)?

分库分表提高高并发


有哪些分库分表中间件?

如cobar、TTDL、Atlas、

Sharding-jdbc 是client层方案,不需要单独部署,项目依赖jar包;

mycat 是proxy层方案,需要部署,对各个项目透明;


如何进行垂直拆分或水平拆分?

水平拆分就是把一个表的数据给弄到多个库的多个表里去,每个表的结构都一样,但是每个库表里面存放的数据不同,所有库表的数据加起来才是全部数据。

垂直拆分是把一个有很多字段的表拆分成多个表,或者多个库上去。每个库表的结构都不一样,每个库表只包含部分字段。一般把访问频率很高的字段放到一个表里面去,将较多的访问频率很低的字段放到另一个表里面。数据库缓存,让频率高的行字段少,缓存里面可以存更多行,性能也相应地高了。

分库分表的方式分2种:按range分,如时间范围;按某个字段的hash值来分(常用);


现有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态换到分库分表上?

双写迁移方案

对线上系统,除了对老库增删改,都加上对新库的增删改,就是老库和新增的库同时写。

对于老数据不一样的,用程序自动检测更新到新库。


如何设计可以动态扩容缩容的分库分表方案?

最初设计数据库时,就设计为32个库,每个库32张表,总共1024张表。第一次分库分表就给他分够,对于一般规模企业是足够的。假设每一个库并发1000,那么32个库也有32000的写并发,再加上mq进行肖峰,足以可以应对。

根据某个id先和32取模路由到库( id%32) ,然后再32取模路由到表里面(id/32%32),最开始可以建逻辑表在一个数据库服务器里面,然后根据实际情况进行拆分到多台服务器上部署的数据库上,按2倍数扩容。


分库分表后,id主键如何处理?

uuid程序生成,不依赖数据库。但uuid太长,占空间,作为主键性能太差;uuid不具有序性,会导致B+树索引在写的时候有过多的随机写操作(连续的id可以产生部分顺序写),由于在写的时候不能产生有顺序的append操作,需要进行insert操作,将会读取整个B+树节点到内存,在插入这条记录后会将整个节点写回磁盘,这操作在数据占用空间比较大情况下,性能下降明显。


snowflake雪花算法

每秒几万并发


如何实现mysql读写分离?

基于主从复制架构,一个主库负责写并同步到从库,挂多个从库负责读


mysql主从复制原理?

主库将变更写入binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入relay中继日志中。接着从库有一个sql线程会从中继日志读取binlog,然后执行binlog日志中内容,也就是在自己本地再执行一遍sql,这样就可以保证从库和主库数据同步。

由于从库同步主库数据的过程是串行化的,即主库上并行的操作,在从库上是串行操作。所以从库从主库拷贝日志以及串行执行sql特点,会在高并发情况下使从库的数据读取时有延迟。另外就是如果主库突然宕机,那么从库可能会出现同步未完成数据丢失。

半同步复制,指主库写入binlog日志后,会强制立即将数据同步到从库,从库将日志写入relay log后,返回一个ack给主库,主库接收到至少一个从库的ack才会认为写操作成功。

并行复制,指从库开启多个线程,并行读取relay log中不同库的日志,然后并行重复不同库的日志,是库级别并行。


如何解决mysql主从同步延时问题?

分库,把主库拆分为多个主库,每个主库的写并发减少,从而使主从同步延迟减小;

开启并行复制,多个库并行复制。当mysql写并发达到2000每秒,那么并行复制无意义。

代码上注意 插入数据时,不会立即会查询到数据。


高并发系统设计?

系统拆分;

缓存;

消息队列;

分库分表;

读写分离;

Es搜索引擎;