面经-场景题

一、数据流查找数据

 

1. 找中位数

1.1 有限数据文件

建立一个大根堆,一个小根堆,每次加入数据保证了两个堆数量相等。大根堆保存较小数,小根堆保存较大数。

LeetCode数据流中的中位数

1.2 超大数据文件

100GB数据,查找中位数,内存只有512MB

100GB数据按照大小分解成200个小文件(根据内存大小分),这些文件中分别存放数字大小在一定范围中的数字,同时统计每个小文件中元素的个数,这样就能知道中位数在哪个文件中以及中位数在该文件中的第K个数,然后查找该文件中的第K大数即可。

2. 找最大K个数

构建大小为K的小顶堆heap,如果当前数字num>heap.top(),先push将该书加入到堆中,然后pop删除一个数,如果num

二、设计一个秒杀系统(转载)

1. 秒杀系统场景特点

  • 秒杀一般是访问请求数量远远大于库存数量,只有少部分用户能够秒杀成功
  • 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增
  • 秒杀业务流程比较简单,一般就是下订单减库存

2. 秒杀架构设计理念

  1. 限流: 鉴于只有少部分用户能够秒杀成功,所以要限制大部分流量,只允许少部分流量进入服务后端秒杀程序。
  2. 削峰:对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。高峰值流量是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有前端添加一定难度的验证码后端利用缓存和消息中间件等技术。
  3. 异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。
  4. 内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。
  5. 可拓展:当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。

3. 架构方案

一般的秒杀系统架构

4. 设计思路

  1. 将请求拦截在系统上游,降低下游压力:秒杀系统特点是并发量极大,但实际秒杀成功的请求数量却很少,所以如果不在前端拦截很可能造成数据库读写锁冲突,甚至导致死锁,最终请求超时
  2. 充分利用缓存:利用缓存预减库存,拦截掉大部分请求 
  3. 消息队列:这是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理

5. 前端方案

  1. 页面静态化:将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。 
  2. 禁止重复提交:用户提交之后按钮置灰,禁止重复提交 
  3. 用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流

6. 后端方案

服务端控制器层(网关层)

  • 限制uid(UserID)访问频率:我们上面拦截了浏览器访问的请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率。

服务层

上面只拦截了一部分访问请求,当秒杀的用户量很大时,即使每个用户只有一个请求,到服务层的请求数量还是很大。比如我们有100W用户同时抢100台手机,服务层并发请求压力至少为100W。

  1. 把需要秒杀的商品的主要信息以及库存初始化到redis缓存中
  2. 做请求合法性的校验(比如是否登录),如果请求非法,直接给前端返回错误码,进行相应的提示
  3. 进行内存标识的判断(true 已经秒杀结束,false 未秒杀结束,下面第4步会写入),如果内存标识为true,直接返回秒杀结束
  4. redis中使用decr 进行预减库存操作,判断:如果decr后库存量小于0,则把内存标记置为true(已经秒杀结束,第3步会用到),且返回秒杀结束
  5. 用redis的布隆过滤器来判断是否已经秒杀到了(下面第7步会写入),防止重复秒杀,如果重复秒杀,直接返回重复秒杀的错误码。具体做法是:先用redis的布隆过滤器来判断是否秒杀过,如果布隆过滤器判断已经秒杀过了, 则再次查库确认是否秒杀过了,之所以再次查库确认是因为布隆过滤器对可能存在的数据是有误判率的;但是它对不存在的数据的判断是百分百准确的,所以如果redis的布隆过滤器判断没秒杀过,就直接放过去进行秒杀
  6. 发送成功秒杀到的MQ消息给相应的业务端进行处理,并给用户端返回排队中,如果客户端收到排队中的消息,则自动进行轮询查询,直到返回秒杀成功或者秒杀失败为止
  7. 相应的业务端进行处理:真正处理秒杀的业务端,再次进行校验(比如秒杀是否结束,库存是否充足等)、将用户和商品id作为key存入redis的布隆过滤器来标识该用户秒杀该商品成功(第5步会用到)、减库存(这里的是真正的减库存,操作数据库的库存)、生成秒杀订单、返回秒杀成功
  • 注意:就算请求走到了真正处理业务的这一端,也有可能秒杀失败,比如秒杀结束,库存不足,真正减库存失败,秒杀单生成失败等等,一旦失败,则返回秒杀结束
  • 优化:将秒杀接口隐藏:用户点击秒杀按钮的时候,根据用户id生成唯一的加密串存入缓存并返回给客户端,然后客户端再次请求的时候带着加密串过来,后端进行校验是否合法,若不合法,直接返回请求非法;
  • 限制某个接口的访问频率:可以用拦截器配合自定义注解来实现,这么做可以和具体的业务分离减少入侵,使用起来也非常方便

数据库层

  • 数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧
  • 为防止秒杀出现负数订单数大于真正的库存数,所以在真正减库存,update库存的时候应该加上where 库存>0,而且需要给秒杀订单表加上用户id和商品id联合的唯一索引

三、微服务架构

面经-场景题_第1张图片

监控 - 发现故障的征兆

面经-场景题_第2张图片

 定位问题 - 链路跟踪

面经-场景题_第3张图片

面经-场景题_第4张图片

分析问题 - 日志分析

面经-场景题_第5张图片

网关 - 权限控制,服务治理 

面经-场景题_第6张图片

 服务注册于发现 - 动态扩容

面经-场景题_第7张图片

熔断、服务降级、限流 

熔断

面经-场景题_第8张图片

 服务降级

限流

面经-场景题_第9张图片

测试

面经-场景题_第10张图片 面经-场景题_第11张图片

 四、服务降级

五、负载均衡(转载)

六、 场景题一般套路

1. 缓存

(1. 缓存读写过程

(2. 缓存种类

Redis

(3. 淘汰算法

LRU

2. hash

(1. 哈希算法

(2. 减少哈希存储

Bitmap

(3. 解决哈希冲突

1. 普通哈希:一次哈希,二次哈希,拉链法

问题:拉链法怎么解决桶元素过多的问题?

2. Bitmap:布隆过滤器

七、udp实现可靠传输(知乎)

1. 流控机制

2. 超时机制

3. 重传机制

4. 重排机制

你可能感兴趣的:(面试复习,数据库)