做网站需要什么电脑,海口网站建设费用,京东网站网站建设是什么,搜书网站 怎么做在高并发系统当中#xff0c;分库分表是必不可少的技术手段之一#xff0c;同时也是BAT等大厂面试时#xff0c;经常考的热门考题。你知道我们为什么要做分库分表吗#xff1f;这个问题要从两条线说起#xff1a;垂直方向 和 水平方向。1 垂直方向垂直方向主要针对的是业务… 在高并发系统当中分库分表是必不可少的技术手段之一同时也是BAT等大厂面试时经常考的热门考题。你知道我们为什么要做分库分表吗这个问题要从两条线说起垂直方向 和 水平方向。1 垂直方向垂直方向主要针对的是业务下面聊聊业务的发展跟分库分表有什么关系。1.1 单库在系统初期业务功能相对来说比较简单系统模块较少。为了快速满足迭代需求减少一些不必要的依赖。更重要的是减少系统的复杂度保证开发速度我们通常会使用单库来保存数据。系统初期的数据库架构如下此时使用的数据库方案是一个数据库包含多张业务表。用户读数据请求和写数据请求都是操作的同一个数据库。1.2 分表系统上线之后随着业务的发展不断的添加新功能。导致单表中的字段越来越多开始变得有点不太好维护了。一个用户表就包含了几十甚至上百个字段管理起来有点混乱。这时候该怎么办呢答分表。将用户表拆分为用户基本信息表 和 用户扩展表。用户基本信息表中存的是用户最主要的信息比如用户名、密码、别名、手机号、邮箱、年龄、性别等核心数据。这些信息跟用户息息相关查询的频次非常高。而用户扩展表中存的是用户的扩展信息比如所属单位、户口所在地、所在城市等等非核心数据。这些信息只有在特定的业务场景才需要查询而绝大数业务场景是不需要的。所以通过分表把核心数据和非核心数据分开让表的结构更清晰职责更单一更便于维护。除了按实际业务分表之外我们还有一个常用的分表原则是把调用频次高的放在一张表调用频次低的放在另一张表。有个非常经典的例子就是订单表和订单详情表。1.3 分库不知不觉系统已经上线了一年多的时间了。经历了N个迭代的需求开发功能已经非常完善。系统功能完善意味着系统各种关联关系错综复杂。此时如果不赶快梳理业务逻辑后面会带来很多隐藏问题会把自己坑死。这就需要按业务功能划分不同领域了。把相同领域的表放到同一个数据库不同领域的表放在另外的数据库。具体拆分过程如下将用户、产品、物流、订单相关的表从原来一个数据库中拆分成单独的用户库、产品库、物流库和订单库一共四个数据库。在这里为了看起来更直观每个库我只画了一张表实际场景可能有多张表。这样按领域拆分之后每个领域只用关注自己相关的表职责更单一了一下子变得更好维护了。1.4 分库分表有时候按业务只分库或者只分表是不够的。比如有些财务系统需要按月份和年份汇总所有用户的资金。这就需要做分库分表了。每年都有个单独的数据库每个数据库中都有12张表每张表存储一个月的用户资金数据。这样分库分表之后就能非常高效的查询出某个用户每个月或者每年的资金了。此外还有些比较特殊的需求比如需要按照地域分库比如华中、华北、华南等区每个区都有一个单独的数据库。甚至有些游戏平台按接入的游戏厂商来做分库分表。2 水平方向水分方向主要针对的是数据下面聊聊数据跟分库分表又有什么关系。2.1 单库在系统初期由于用户非常少所以系统并发量很小。并且存在表中的数据量也非常少。这时的数据库架构如下此时使用的数据库方案同样是一个master数据库包含多张业务表。用户读数据请求和写数据请求都是操作的同一个数据库该方案比较适合于并发量很低的业务场景。2.2 主从读写分离系统上线一段时间后用户数量增加了。此时你会发现用户的请求当中读数据的请求占据了大部分真正写数据的请求占比很少。众所周知数据库连接是有限的它是非常宝贵的资源。而每次数据库的读或写请求都需要占用至少一个数据库连接。如果写数据请求需要的数据库连接被读数据请求占用完了不就写不了数据了这样问题就严重了。为了解决该问题我们需要把读库和写库分开。于是就出现了主从读写分离架构考虑刚开始用户量还没那么大选择的是一主一从的架构也就是常说的一个master一个slave。所有的写数据请求都指向主库。一旦主库写完数据之后立马异步同步给从库。这样所有的读数据请求就能及时从从库中获取到数据了除非网络有延迟。读写分离方案可以解决上面提到的单节点问题相对于单库的方案能够更好的保证系统的稳定性。因为如果主库挂了可以升级从库为主库将所有读写请求都指向新主库系统又能正常运行了。读写分离方案其实也是分库的一种它相对于为数据做了备份它已经成为了系统初期的首先方案。但这里有个问题就是如果用户量确实有些大如果master挂了升级slave为master将所有读写请求都指向新master。但此时如果这个新master根本扛不住所有的读写请求该怎么办这就需要一主多从的架构了上图中我列的是一主两从如果master挂了可以选择从库1或从库2中的一个升级为新master。假如我们在这里升级从库1为新master则原来的从库2就变成了新master的的slave了。调整之后的架构图如下这样就能解决上面的问题了。除此之外如果查询请求量再增大我们还可以将架构升级为一主三从、一主四从...一主N从等。2.3 分库上面的读写分离方案确实可以解决读请求大于写请求时导致master节点扛不住的问题。但如果某个领域比如用户库。如果注册用户的请求量非常大即写请求本身的请求量就很大一个master库根本无法承受住这么大的压力。这时该怎么办呢答建立多个用户库。用户库的拆分过程如下在这里我将用户库拆分成了三个库真实场景不一定是这样的每个库的表结构是一模一样的只有存储的数据不一样。2.4 分表用户请求量上来了带来的势必是数据量的成本上升。即使做了分库但有可能单个库比如用户库出现了5000万的数据。根据经验值单表的数据量应该尽量控制在1000万以内性能是最佳的。如果有几千万级的数据量用单表来存性能会变得很差。如果数据量太大了需要建立的索引也会很大从小到大检索一次数据会非常耗时而且非常消耗cpu资源。这时该怎么办呢答分表这样可以控制每张表的数据量和索引大小。表拆分过程如下我在这里将用户库中的用户表拆分成了四张表真实场景不一定是这样的每张表的表结构是一模一样的只是存储的数据不一样。如果以后用户数据量越来越大只需再多分几张用户表即可。2.5 分库分表当系统发展到一定的阶段用户并发量大而且需要存储的数据量也很多。这时该怎么办呢答需要做分库分表。如下图所示图中将用户库拆分成了三个库每个库都包含了四张用户表。如果有用户请求过来的时候先根据用户id路由到其中一个用户库然后再定位到某张表。路由的算法挺多的根据id取模比如id7有4张表则7%43模为3路由到用户表3。给id指定一个区间范围比如id的值是0-10万则数据存在用户表0id的值是10-20万则数据存在用户表1。一致性hash算法这篇文章就不过多介绍了后面会有文章专门介绍这些路由算法的。3 真实案例接下来废话不多说给大家分享三个我参与过的分库分表项目经历给有需要的朋友一个参考。3.1 分库我之前待过一家公司我们团队是做游戏运营的我们公司提供平台游戏厂商接入我们平台推广他们的游戏。游戏玩家通过我们平台登录成功之后跳转到游戏厂商的指定游戏页面该玩家就能正常玩游戏了还可以充值游戏币。这就需要建立我们的账号体系和游戏厂商的账号的映射关系游戏玩家通过登录我们平台的游戏账号成功之后转换成游戏厂商自己平台的账号。这里有两个问题每个游戏厂商的接入方式可能都不一样账号体系映射关系也有差异。用户都从我们平台登录成功之后跳转到游戏厂商的游戏页面。当时有N个游戏厂商接入了活跃的游戏玩家比较多登录接口的并发量不容小觑。为了解决这两个问题我们当时采用的方案是分库。即针对每一个游戏都单独建一个数据库数据库中的表结构允许存在差异。我们当时没有进一步分表是因为当时考虑每种游戏的用户量还没到大到离谱的地步。不像王者荣耀这种现象级的游戏有上亿的玩家。其中有个比较关键的地方是登录接口中需要传入游戏id字段通过该字段系统就知道要操作哪个库因为库名中就包含了游戏id的信息。3.2 分表还是在那家游戏平台公司我们还有另外一个业务就是金钻会员。说白了就是打造了一套跟游戏相关的会员体系为了保持用户的活跃度开通会员有很多福利比如送游戏币、充值有折扣、积分兑换、抽奖、专属客服等等。在这套会员体系当中有个非常重要的功能就是积分。用户有很多种途径可以获取积分比如签到、充值、玩游戏、抽奖、推广、参加活动等等。积分用什么用途呢退换实物礼物兑换游戏币抽奖说了这么多其实就是想说一个用户一天当中获取积分或消费积分都可能有很多次那么一个用户一天就可能会产生几十条记录。如果用户多了的话积分相关的数据量其实挺惊人的。我们当时考虑了水平方向的数据量可能会很大但是用户并发量并不大不像登录接口那样。所以采用的方案是分表。当时使用一个积分数据库就够了但是分了128张表。然后根据用户id进行hash除以128取模。需要特别注意的是分表的数量最好是2的幂次方方便以后扩容。3.3 分库分表后来我去了一家从事餐饮软件开发的公司。这个公司有个特点是在每天的中午和晚上的就餐高峰期用户的并发量很大。用户吃饭前需要通过我们系统点餐然后下单然后结账。当时点餐和下单的并发量挺大的。餐厅可能会有很多人每个人都可能下多个订单。这样就会导致用户的并发量高并且数据量也很大。所以综合考虑了一下当时我们采用的技术方案是分库分表。经过调研之后觉得使用了当当网开源的基于jdbc的中间件框架sharding-jdbc。当时分了4个库每个库有32张表。4 总结上面主要从垂直和水平两个方向介绍了我们的系统为什么要分库分表。说实话垂直方向即业务方向更简单。在水平方向即数据方向上分库和分表的作用其实是有区别的不能混为一谈。分库是为了解决数据库连接资源不足问题和磁盘IO的性能瓶颈问题。分表是为了解决单表数据量太大sql语句查询数据时即使走了索引也非常耗时问题。此外还可以解决消耗cpu资源问题。分库分表可以解决 数据库连接资源不足、磁盘IO的性能瓶颈、检索数据耗时 和 消耗cpu资源等问题。如果在有些业务场景中用户并发量很大但是需要保存的数据量很少这时可以只分库不分表。如果在有些业务场景中用户并发量不大但是需要保存的数量很多这时可以只分表不分库。如果在有些业务场景中用户并发量大并且需要保存的数量也很多时可以分库分表。好了今天的内容就先到这里。是不是有点意犹未尽没关系其实分库分表相关内容挺多的本文作为分库分表系列的第一弹作为一个开胃小菜吧分享给大家。在文章末尾顺便提几个问题分库分表的具体实现方案有哪些分库分表后如何平滑扩容分库分表后带来了哪些问题如何在项目中实现分库分表功能欢迎关注敬请期待我的下一篇文章。最后说一句(求关注别白嫖我)如果这篇文章对您有所帮助或者有所启发的话帮忙扫描下方二维码关注一下您的支持是我坚持写作最大的动力。求一键三连点赞、转发、在看。往期推荐MySQL 性能优化的 9 种姿势面试再也不怕了高并发下秒杀商品必须知道的9个细节面试官怎么解决MySQL中的死锁问题