Skip to content

System design

如何设计 server,使得能够接收多个客户端的请求 参考回答: 多线程,线程池,io 复用


https://draveness.me/redis-io-multiplexing/

与此同时也有其它的 I/O 多路复用函数 epoll/kqueue/evport,它们相比 select 性能更优秀,同时也能支撑更多的服务。

  1. non-blocking: 节省等待开销
  2. kernel copy data to user space in the "background"

死循环+来连接时新建线程的方法效率有点低,怎么改进?

参考回答:

提前创建好一个线程池,用生产者消费者模型,创建一个任务队列,队列作为临界资源,有了新连接,就挂在到任务队列上,队列为空所有线程睡眠。改进死循环:使用 select epoll 这样的技术


2、常用线程模型

1、Future 模型

该模型通常在使用的时候需要结合 Callable 接口配合使用。

Future 是把结果放在将来获取,当前主线程并不急于获取处理结果。允许子线程先进行处理一段时间,处理结束之后就把结果保存下来,当主线程需要使用的时候再向子线程索取。

Callable 是类似于 Runnable 的接口,其中 call 方法类似于 run 方法,所不同的是 run 方法不能抛出受检异常没有返回值,而 call 方法则可以抛出受检异常并可设置返回值。两者的方法体都是线程执行体。

2、fork&join 模型

该模型包含递归思想和回溯思想,递归用来拆分任务,回溯用合并结果。可以用来处理一些可以进行拆分的大任务。其主要是把一个大任务逐级拆分为多个子任务,然后分别在子线程中执行,当每个子线程执行结束之后逐级回溯,返回结果进行汇总合并,最终得出想要的结果。

这里模拟一个摘苹果的场景:有 100 棵苹果树,每棵苹果树有 10 个苹果,现在要把他们摘下来。为了节约时间,规定每个线程最多只能摘 10 棵苹树以便于节约时间。各个线程摘完之后汇总计算总苹果树。

3、actor 模型

actor 模型属于一种基于消息传递机制并行任务处理思想,它以消息的形式来进行线程间数据传输,避免了全局变量的使用,进而避免了数据同步错误的隐患。actor 在接受到消息之后可以自己进行处理,也可以继续传递(分发)给其它 actor 进行处理。在使用 actor 模型的时候需要使用第三方 Akka 提供的框架。

4、生产者消费者模型

生产者消费者模型都比较熟悉,其核心是使用一个缓存来保存任务。开启一个/多个线程来生产任务,然后再开启一个/多个来从缓存中取出任务进行处理。这样的好处是任务的生成和处理分隔开,生产者不需要处理任务,只负责向生成任务然后保存到缓存。而消费者只需要从缓存中取出任务进行处理。使用的时候可以根据任务的生成情况和处理情况开启不同的线程来处理。比如,生成的任务速度较快,那么就可以灵活的多开启几个消费者线程进行处理,这样就可以避免任务的处理响应缓慢的问题。

5、master-worker 模型

master-worker 模型类似于任务分发策略,开启一个 master 线程接收任务,然后在 master 中根据任务的具体情况进行分发给其它 worker 子线程,然后由子线程处理任务。如需返回结果,则 worker 处理结束之后把处理结果返回给 master。


IO 模型

  1. 阻塞 IO:调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必须等这个函数返回才能进行下一步动作
  2. 非阻塞 IO:非阻塞等待,每隔一段时间就去检测 IO 事件是否就绪。没有就绪就可以做其他事。
  3. 信号驱动 IO:信号驱动 IO:linux 用套接口进行信号驱动 IO,安装一个信号处理函数,进程继续运行并不阻塞,当 IO 时间就绪,进程收到 SIGIO 信号。然后处理 IO 事件。
  4. IO 复用/多路转接 IO:linux 用 select/poll 函数实现 IO 复用模型,这两个函数也会使进程阻塞,但是和阻塞 IO 所不同的是这两个函数可以同时阻塞多个 IO 操作。而且可以同时对多个读操作、写操作的 IO 函数进行检测。知道有数据可读或可写时,才真正调用 IO 操作函数
  5. 异步 IO:linux 中,可以调用 aio_read 函数告诉内核描述字缓冲区指针和缓冲区的大小、文件偏移及通知的方式,然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

https://hackernoon.com/top-10-system-design-interview-questions-for-software-engineers-8561290f0444


  1. 设计一个转账系统,简述如何解决分布式数据一致性问题
    1. 事务 ID 状态跟踪、回滚
    2. 分片
    3. idempotent operation
    4. consistent hashing

秒杀系统

  • 控流
    • 客户端
    • 后端
  • 读优化:缓存
  • 消息队列:排队处理,防止过载
  • 自动水平扩容
  • Redis 大约上万 PQS
    • 可能会有恶意搞缓存的 DDoS 请求
  • 降级、限流、熔断:考虑最坏的情况,控制损失
  • 流量机器:自动防止 DDoS

  • GFS, Bigtable, MapReduce
  • 订票系统
  • Collaborative Real-time Editing
  • Rate limiter & Data Dog
  • Video Stream System
  • IM System
  • Typeahead system
  • Web Crawler system
  • Location based service system
  • News feed system
  • Tiny URL system
  • Docker & k8s