后端场景设计第二弹

设计一个短链系统

什么是短链

类似一个完整的地址,容易写错,如:中国浙江省杭州市西湖区文三路778号,就需要使用一种简单的方法,如邮政编码A12345用来表示这个地址,邮局收到A12345就知道要寄到这里。短链系统即为这种重定向到真实完整地址的系统。

设计方案

后端存储短链和长链的对应关系,当往数据库传入一条长链时,这条数据的对应id即可作为短链返回。

设计一个订单超时取消功能

方案一:用定时任务

  • 隔一分钟轮询一次订单表,查询每个订单是否超时
  • 缺点是时间不准确,订单量大时对数据库压力比较大

方案二:用消息队列

  • RocketMQ有提供延迟消息功能,类似闹钟一样,下单的时候设置一下十分钟后发来一条取消订单的消息

方案三:redis的zset

  • 使用zset存储订单ID,score为过期时间
  • 定时扫描过期的订单进行处理

设计一个分布式单例对象

分布式单例即多进程中保证仅有一个的对象。

实现方案

  1. 需要加分布式锁:多个进程竞争一个分布式锁,谁抢到锁谁就可以用
  2. 外部存储:使用序列化的方式存储单例对象,使用完后要写回外部存储
  3. 分布式锁和外部存储都可以用redis实现

商家想要知道自己店铺卖的最好的Top50商品,如何实现?

实现方案

  1. 首先排除数据库查询:不可能卖一个东西就对数据库排一次表
  2. 使用redis中的zset:score是数量,value是商品ID
  3. 查询方式:商家查看的时候直接查看zset里面的0-50就行
  4. 更新方式:增加订单的时候直接改zset对应score+1即可

朋友圈点赞功能如何实现

需要涉及的功能点

  1. 存储点赞信息
  2. 取消点赞
  3. 点赞列表

实现方案:使用redis的zset

  • key是此条朋友圈的id
  • score是点赞时间
  • value是点赞人id

如何实现分布式锁

实现方案

  1. 使用redis的setNX:设置成功表示获取锁成功
  2. 使用ZooKeeper的临时有序节点:创建节点成功表示获取锁成功

如何统计每个接口每分钟的调用次数

实现方案

直接存内存的哈希表,key为接口名+时间戳,value为调用次数。

如何设计一个文件上传系统

主要核心点

  1. 超大文件上传

    • 前端分块传输,避免局部失败导致全部失败
    • 下载的时候后端按照顺序分块发给前端
  2. 如何避免重复文件传输

    • 不应该使用文件名判重
    • 可以使用哈希摘要,判断两个文件的哈希摘要是否一致
    • 哈希摘要也可用于判断文件是否被篡改
  3. 如何限流

    • 限制文件最大大小、发送频次等

如何设计一个分布式id发号器

分布式id本质上是全局唯一id,如UUID,但UUID不适合作为组件,因为太长了。

常见两种实现

  1. 雪花算法

    • 可以生成一个64bit的id
    • 前41个是时间戳,之后10个是机器号,保证了同一时间内由不同机器产生的uid不同
    • 缺点是依赖时钟,若时钟回拨会发生重复
  2. 基于数据库实现

    • 使用mysql的bitTag作为唯一索引,保证每个机器的初始位置不同
    • 如两个数据库就一个1,3,5,7,一个为2,4,6,8