Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

  • 计算机基础

  • 框架|中间件

  • 架构

    • 分布式

    • 高并发

      • 如何设计一个高并发架构
      • 讲座预约高并发方案
      • 分库分表
        • 为什么要分库分表?
        • 如何对数据库如何进行垂直拆分或水平拆分的?
        • 分库分表的方式
        • 分库分表后 id 主键如何处理
    • 高可用

    • 架构

  • 后端
  • 架构
  • 高并发
Marvel
2022-08-22
目录

分库分表

# 分库分表

# 为什么要分库分表?

分库分表的原因:数据量太大、并发太大

分表

当单表数据达到几百几千万时,由于单表数据量太大,会极大影响 sql 执行的性能,即使能够运行也会非常慢。一般情况,当单表达到几百万的时候就得分表了。

分表就是把一个表的数据放到多个表中,然后查询的时候就查询对应的表。比如可以按照用户id来分表。

分库

一般而言,一个数据库的并发量达到 2000 就一定要扩容了,而且一个健康的单库并发量最好保持在每秒 1000 左右,不要太大。如果当并发量太大时,就可以拆分成多个库,访问的时候就访问一个库。

分库分表前 分库分表后
并发支撑情况 MySQL 单机部署,扛不住高并发 MySQL 从单机到多机,能承受的并发增加了多倍
磁盘使用情况 MySQL 单机磁盘容量几乎撑满 拆分为多个库,数据库服务器磁盘使用率大大降低
SQL 执行性能 单表数据量太大,SQL 越跑越慢 单表数据量减少,SQL 执行效率明显提升

# 如何对数据库如何进行垂直拆分或水平拆分的?

水平拆分:把一个表的数据分到多个库的多个表中,但每个表结构都相同,只不过每个表库放的数据不同,所有库表的数据加起来就是全部数据。水平拆分的意义就是将数据均匀放到更多的库里,然后用多个库来抗住更高的并发,同时也提高了存储容量。

database-split-horizon

垂直拆分:把一个很多字段的表给拆分成多个表或者多个库,每个表的结构不一样,每个表库都包含部分字段。一般会将较少的访问频率较高的字段放在一个表里,将较多的访问频率较低的字段放到另一个表里。

image-20221114152933539

# 分库分表的方式

range 分,扩容简单,给每个月都准备一个库就可以了,到了一个新的月份就会写到新的库;缺点,大部分数据都是访问最新的数据,实际使用需要看场景。

hash 分,平分配每一个库的数据量和请求压力;缺点时扩容比较麻烦,需要数据迁移,之前的数据需要重新计算 hash 值后重新分配到不同的库或表。

# 分库分表后 id 主键如何处理

🔶 数据库自增 Id

设置数据库 sequence 或者表自增字段步长,每个数据表有一个不同的 起始 ID,有多少个节点,自增步长就是多少。这种方案实现起来比较简单,也能达到性能目标。但是服务节点固定,步长也固定,将来如果还要增加服务节点,就不好搞了。

🔶 UUID

本地生成,不需要基于数据库。缺点,UUID 太长且占空间,作为主键性能太差。更重要的是,UUID 不具备有序性,会导致 B+ 树索引在写的时候有过多的随机写操作。

🔶 雪花算法

snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数时间戳,用 10 bits 作为工作机器 id,12 bits 作为序列号。

  • 1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
  • 41 bits:表示的是时间戳,单位是毫秒。41 bits 可以表示的数字多达 2^41 - 1 ,也就是可以标识 2^41 - 1 个毫秒值,换算成年就是表示 69 年的时间。
  • 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024 台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表 2^5 个机房(32 个机房),每个机房里可以代表 2^5 个机器(32 台机器)。
  • 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 2^12 - 1 = 4096 ,也就是说可以用这个 12 bits 代表的数字来区分同一个毫秒内的 4096 个不同的 id。
编辑 (opens new window)
上次更新: 2023/08/20, 21:21:52
讲座预约高并发方案
高可用

← 讲座预约高并发方案 高可用→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式