太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己( 五 )

数据库模块
数据库主要是使用一个ArrayBlockingQueue来暂存有可能成功的用户请求 。
package seckill;import java.util.concurrent.ArrayBlockingQueue;/**    * DB应该是数据库的唯一接口.    */public class DB {      public static int count = 10;      public static ArrayBlockingQueue<BidInfo> bids = new ArrayBlockingQueue<BidInfo>(10);      public static boolean checkReminds() {          // TODO          return true;      }      // 单线程操作      public static void bid() {          BidInfo info = bids.poll();          while (count-- > 0) {              // insert into table Bids values(item_id, user_id, bid_date, other)              // select count(id) from Bids where item_id = ?              // 如果数据库商品数量大约总数 , 则标志秒杀已完成 , 设置标志位reminds = false.              info = bids.poll();          }      }}数据库设计
基本概念
概念一“单库”:

太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
概念二“分片”:
太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
分片解决的是“数据量太大”的问题 , 也就是通常说的“水平切分” 。一旦引入分片 , 势必有“数据路由”的概念 , 哪个数据访问哪个库 。路由规则通常有3种方法:
1、范围:range
  • 优点:简单 , 容易扩展
  • 缺点:各库压力不均(新号段更活跃)
2、哈希:hash 【大部分互联网公司采用的方案二:哈希分库 , 哈希路由】
  • 优点:简单 , 数据均衡 , 负载均匀
  • 缺点:迁移麻烦(2库扩3库数据要迁移)
3、路由服务:router-config-server
  • 优点:灵活性强 , 业务与路由算法解耦
  • 缺点:每次访问数据库前多一次查询
概念三“分组”:
太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
分组解决“可用性”问题 , 分组通常通过主从复制的方式实现 。互联网公司数据库实际软件架构是:又分片 , 又分组(如下图) 。
太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
设计思路
数据库软件架构师平时设计些什么东西呢?至少要考虑以下四点:
1、如何保证数据的可用性?
解决可用性问题的思路是=>冗余如何保证站点的可用性?
复制站点 , 冗余站点如何保证服务的可用性?
复制服务 , 冗余服务如何保证数据的可用性?
复制数据 , 冗余数据数据的冗余 , 会带来一个副作用=>引发一致性问题(先不说一致性问题 , 先说可用性) 。
2、如何保证数据库“读”高可用?冗余读库:
太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
冗余读库带来的副作用?读写有延时 , 可能不一致 。上面这个图是很多互联网公司MySQL的架构 , 写仍然是单点 , 不能保证写高可用 。
3、如何保证数据库“写”高可用?冗余写库:
太傻了!下次二面再回答不好“秒杀系统“设计原理,我就捶死自己

文章插图
 
采用双主互备的方式 , 可以冗余写库带来的副作用?双写同步 , 数据可能冲突(例如“自增id”同步冲突) , 如何解决同步冲突 , 有两种常见解决方案:


推荐阅读