系统设计- 参考
几本书:
设计数据密集型应用-Data-Intensive Application
https://github.com/donnemartin/interactive-coding-challenges
应用部分:
- 常见分布式应用系统设计图解(一):即时消息系统
- 消息数据库,RDB 往往不太适合,因为消息数量太大,对于一组对话(thread)的展示,需要找到该对话 N 条最近的记录,行数据库效率较低,可以考虑列数据库,比如 HBase。这种方式下,同一 thread 下的消息都是按时序存放在一起的,读的效率非常高,写因为基本是 append,也很方便。
- 常见分布式应用系统设计图解(二):Feed 流系统
- 推拉。双向的就推,关系少。twitter主要是拉,可以粉丝特别多。
- 只推活跃用户
- 常见分布式应用系统设计图解(三):Top K 系统
- 近似的排行榜,count min stretch or Lossy Counting
- 总的异步计算排行榜
- 近一小时的分片排行榜,一小时分成60分钟 60个分片。
- 常见分布式应用系统设计图解(四):输入建议系统
- 前缀树,内存计算,降低延迟,浏览器也需要放缓存合并。
- 常见分布式应用系统设计图解(五):Proximity 系统
- 打车系统。 geohash / R树
- 常见分布式应用系统设计图解(六):流媒体系统
- 类似爱奇艺。 视频存在HDFS 这样基于 block 的分布式文件系统
- 常见分布式应用系统设计图解(七):爬虫搜索系统
- 常见分布式应用系统设计图解(八):文件同步分享系统
- 文件实际的数据按照块的形式组织,存放在分布式文件系统中。大文件拆分成小的块,这样如果某一个块的校验码(checksum)不匹配,重传该块即可,不需要重传整个文件。
- 常见分布式应用系统设计图解(九):协同编辑系统
- 常见分布式应用系统设计图解(十):电商秒杀系统
- 常见分布式应用系统设计图解(十一):数据监控系统
- 常见分布式应用系统设计图解(十二):证券交易系统
- 实时行情每3s推一次,一台机器3万个长连接。
- 交易和购物一样,但延迟要求低。
- 同个股票最新数据按照时间 价格大小进行撮合定价。因此在内存中操作。
- 机器要有备用的。zk监控心跳
- 常见分布式应用系统设计图解(十三):短网址系统
- 常见分布式应用系统设计图解(十四):日志系统
- 常见分布式应用系统设计图解(十五):支付系统
- 隔出了 3 列,最左边是用户,中间是电商系统(比如 Amazon),右边是 Payment Service Provider(PSP,比如 PayPal)。支付操作需要保证幂等性,从而在重试的过程中保证不会被重复扣钱。
- 图中用户在 checkout page 结账页面,store 向 PSP 发送一个 registration 请求,得到一个 token,这个 token 就可以后续用来查询支付信息。再根据这个 token 生成一个跳转到 PSP 网页的 URL,于是这个 URL 重定向用户的请求到了 PSP 的支付页面。一并带过去的,除了 token,还可能会有一个回调 URL,用以支付成功以后跳转回 store 的成功页。
基础设施部分:
- 常见分布式基础设施系统设计图解(一):分布式文件系统
- 常见分布式基础设施系统设计图解(二):分布式数据库
- 常见分布式基础设施系统设计图解(三):分布式消息队列
- 常见分布式基础设施系统设计图解(四):分布式工作流系统
- 常见分布式基础设施系统设计图解(五):分布式流控系统
- 常见分布式基础设施系统设计图解(六):分布式 MR 系统
- 常见分布式基础设施系统设计图解(七):分布式实时流处理系统
- 常见分布式基础设施系统设计图解(八):分布式键值存储系统
主从挂了切主中间数据恢复怎么办?
- 多主架构,写入时自动找可写入的主写入。多对一。要是冲突就就用冲突检测合并,类似在线文档。
- 多主架构,写修复,先写到一个备用的主,然后故障的主恢复时,就从备用的主上拉数据进行恢复。

读加速

答题流程
看看这个先 link
高可用,主要以下几个方面:
- 数据持久化
- 主从复制
- 自动故障恢复
- 集群化
问面试官问题,即便很清晰也要问,将问题重新定义。
- Users: who will use, how the system will be used?
- Scale: qps, tps等
- Performance: the delay of write-to-read
- Cost
需求重新定义:这里不需要问面试官
对于功能模块: 定义api: name以及req, resp
对于非功能需求: 规模、性能、可用性。
数据Model
scalability, performance, availability(灾备、无单点)
consistency, cost
一个大模块就组织出来了。
数据模型,来存储。
各有什么优缺点。
SQL是否可以满足,如何满足的,这块Nosql满足的话成本是不是更少。
处理服务 processing service
画图 有数据流 和 控制流。
时间分配
以40分钟的面试时间来算(掐头去尾除去自我介绍问问题),我面试的大概流程如下。
- 【3分钟】理解需求 (询问系统的商业目的 + 询问系统的功能和技术需求 + 定义成功)
- Functional Requirements
- 用户是否需要登录
- 仅仅上传图片,不需要上传视频
- 图片保存有效期
- Non-functional Requirements
- 基本可用性
- 交互流畅、低延迟
- 是否支持某个动作反馈有一定延迟
- Functional Requirements
- 【0-5分钟】资源估算(optional)(计算需要多少台机器,需要多少内存硬盘和CPU的能力)
- Capacity 可能非核心内容加上时间有限,做个大致计算估计的方法。
- Traffic
- qps xx times per day, xx times per second
- tps, 按读写比10:1
- peak qps: qps * 5
- Storage
- add data xx per day, xx per year
- cache xx..
- Traffic
- Capacity 可能非核心内容加上时间有限,做个大致计算估计的方法。
【5分钟】接口设计
【5分钟】数据结构与存储
【5分钟】High-level diagram
- 划分模块
【10分钟】核心子服务设计
【5分钟】扩展性,容错性,延迟要求
架构扩展性:
- 关注: 存储数据量, 存储吞吐量; 解决方案:存储拆分、单体吞吐低可以batch,多级缓存。
- 服务: 吞吐压力: 先尝试扩容,无状态服务。否则降级: 保障核心服务,关闭弱依赖。
- 伸缩性: 无状态,可横向扩容
- 高峰期流量过高: mq削峰
业务可扩展性
搞多app矩阵的支持,增加namespace, appId
类型增加,增加ItemType
容错性
- 数据库挂了怎么办
- 主从灾备
- 接口挂了怎么办
- 失败重试,缓存队列
- 防止雪崩,要熔断
- 降级、熔断
- 异步
- 消息队列 削锋
- 数据库挂了怎么办
- 【2-7分钟】专题 deep dive
- 用户scope变大
- 多机房同步
- 多语言
- 某个时间点流量特别大了怎么办
- 降级、熔断
- 异步
- 缓存
- 大V设计
- 用户scope变大
- User case. Func, Non-Func
- Scale: QPS, 多少条数据每天
- High level
- 可用性、扩展性
系统设计时间和性能估算
1天86400s
每个字符占用 2 个字节
bit 是位,1 byte == 8 bits
B=byte, 1M = 1024byte
读写比默认10:1
数据类型的空间占用: 在很多系统中,Boolean 占用 1 个字节,字符占用 2 个字节,Integer/Float 是 4 个字节,Long/Double 则是 8 个字节。
时间数量级
Jeff Dean 十年前有一个著名的分享,介绍了他认为重要的系统的数值。我觉在讨论多数系统来说,有这样几个关于时间的数值(参考数量级)比较常见(注意时间单位的关系:1 秒 = 1000 毫秒 (millisecond) = 1,000,000 微秒 (microsecond) = 1,000,000,000(nanosecond)):
- CPU 访问(包括 CPU 缓存):10 纳秒
- 内存访问:100 纳秒
- HDD 磁盘访问:10 毫秒,如果是 SSD 大约快 100 倍
- HDD 磁盘吞吐量:100 MB/s,如果是 SSD 则高几倍
- 同机房网络时延:1 毫秒
- 异地网络时延:10 毫秒
- 国际网络时延:100 毫秒
单机吞吐量上限
- Web 服务器的 QPS:1000
- RDB 单机 QPS:1000
- NoSQL DB 磁盘单机 QPS:10K
- 内存访问单机 QPS:1M
并发估算
一般应用来说,并发估算公式如下:
qps = 5 * 日pv / 86400
5是通用峰值倍数,如果你有高峰值特性自行调整,比如秒杀功能。
pv是访问次数,比如你每天数据库访问次数是100万,可估算峰值qps为60左右,比如数据库qps可达3000,那么可估算你的服务器还能撑同等场景50倍增长。
本质上就是访问次数除以时间,这就是qps每条访问次数的定义了。
1、抢购和活动场景
按照80%的访问量集中在20%的时间内
qps=pv*80%/86400*20%
2、白天提供业务的场景(例如政务查询系统等)
按照一半时间去计算4w秒
qps=pv/40000
3、全天后无明显波峰场景
qps=pv/86400
存储延迟和性能
以下可用性都在99.95%左右
redis 2ms 百万qps
elastic search 简单查询20-30ms, 复杂几t的可能秒级
rocksDB 10ms
mysql 20ms 千万以上基本就要分库分表了。读支持50w qps, 写大概在几千
mongo 20ms
MQ 性能
rocketmq 几十万tps
kafka 百万 tps
存储考虑点, 对数据库的需求有:
| 需求 | 是否必须 |
|---|---|
| 低延迟 | 必须 |
| 支持CP模型 | 必须 |
| 支持非结构化数据存储 | 必须 |
| 有亿级数据的存储方案 | 必须 |
| 有成熟的扩容方案 | 必须 |
| 冷热数据 | 非必须 |
系统设计常用算法
- Bloom filter
- count-min sketch bloom filter基础上增加计数,以最小那个hash计数为值
- Frugal Streaming
- Frugal Streaming uses only one unit of memory per group to compute a quantile for each group
- Geohash / S2 Geometry 地理位置
- Leaky bucket / Token bucket 限流器
- Lossy Counting ,top k频繁 hashmap不停轮换清counter为0的
- Operational transformation 操作转换,类似于google doc多人编辑时
- Quadtree / Rtree ☑️
- 四叉树是一种数据结构,每一个节点有四个孩子。一般需要用到四叉树的情况往往是二位平面,通过把区域分成四个区块来定义。
- 应用:比如确定并显示一条曲线的具体位置时
- R树 vs Geohash
- Ray casting ☑️
- Reverse index ✅
- Rsync algorithm ✅
- Trie algorithm ✅
二维地址查询
- 一种是使用 QuadTree,就是说把地图上任意一个区域都划分成四个子区域,每个区域如果节点超过一个阈值,就继续划分。
- 第二种是使用 Geohash,本质上就是降维。降维的原因是,一维的数据管理和查找起来要容易得多,二维的数据要做到高效查找比较困难。我们的查找条件是基于经纬度的,而不是一个单值;我们存储的数据也都是一个个经纬度形成的点,因此,Geohash 的办法就是把查找条件和存储的数据全部都变成一个个单值,这样就可以利用我们熟悉的一维数组区域查找的技术来高效实现(比如把它索引化,而索引化其实是可以通过 B+树来实现的,因此 Geohash 的查询时间复杂度和 QuadTree 是可以在同一个数量级的,都是 log n)。
Geohash 是一种空间数据编码方法,将地理坐标(经度、纬度)转换为一个短字符串,通常是字母和数字的组合。它的基本原理是将地球表面分割成网格,并将每个网格用一个唯一的标识符表示。随着精度的提高,Geohash 编码的长度会增加。
R 树 是一种自适应的多维空间索引树结构,特别适用于二维或多维数据的快速查询。每个节点在 R 树中都包含了一个最小的边界矩形(Bounding Box,简称 MBR),这些矩形覆盖了树中的对象。R 树的每个分支表示一组空间数据的最小边界,可以通过逐级遍历来进行范围查询或邻近查询。
- Geohash 适合用于地理位置的简单编码和索引,主要通过编码简化了地理数据的存储和查询。
- R 树 是更为复杂的空间索引结构,适用于需要高效处理多维空间数据和复杂空间查询的场景。它能更好地处理空间对象的重叠和查询效率。
两者可以结合使用,比如将 Geohash 用于初步的地理区域划分,再用 R 树处理更细粒度的空间数据。
R树需要数据库支持,如果没有相应存储就还是Geohash吧。
Bloom filter
Bloom Filter 是由一个长度为 m 的比特位数组(bit array)与 k 个哈希函数(hash function)组成的数据结构。位数组均初始化为 0,所有哈希函数都可以分别把输入数据尽量均匀地散列。
当要插入一个元素时,将其数据分别输入 k 个哈希函数,产生 k 个哈希值。以哈希值作为位数组中的下标,将所有 k 个对应的比特置为 1。
当要查询(即判断是否存在)一个元素时,同样将其数据输入哈希函数,然后检查对应的 k 个比特。如果有任意一个比特为 0,表明该元素一定不在集合中。如果所有比特均为 1,表明该元素有(较大的)可能性在集合中。为什么不是一定在集合中呢?因为一个比特被置为 1 有可能会受到其他元素的影响,这就是所谓“假阳性”(false positive)。相对地,“假阴性”(false negative)在 Bloom Filter 中是绝不会出现的。
优点:
- 不需要存储数据本身,只用比特表示,因此空间占用相对于传统方式有巨大的优势,并且能够保密数据;
- 时间效率也较高,插入和查询的时间复杂度均为O(k);
- 哈希函数之间相互独立,可以在硬件指令层面并行计算。
缺点:
- 存在假阳性的概率,不适用于任何要求 100% 准确率的场景;
- 只能插入和查询元素,不能删除元素,这与产生假阳性的原因是相同的。我们可以简单地想到通过计数(即将一个比特扩展为计数值)来记录元素数,但仍然无法保证删除的元素一定在集合中。
所以,Bloom Filter 在对查准度要求没有那么苛刻,而对时间、空间效率要求较高的场合非常合适,本文第一句话提到的用途即属于此类。另外,由于它不存在 假阴性 问题,所以用作“不存在”逻辑的处理时有奇效,比如可以用来作为 缓存系统(如Redis)的缓冲,防止缓存穿透。
Lossy Counting Method
算法本身的作用是找出长度为 N 的数据流中出现频率超过 s % 的元素,保证误差小于 a %。其中 s 与 a 是传入的参数,a 一般设定为 s 的十分之一。此算法从数学上保证:
- 在数据流中,出现频率高于 s * N 的元素最后都会输出。
- 在数据流中,如果出现频率低于 ( s - a ) * N 的元素不会被输出。
- 估算的出现次数与实际次数的差距不会高于 a * N。
算法实现起来也相对简单,只有三步:
- 把现有的数据分成 N 个窗口,每个窗口的大小为 1 / a。
- 按顺序统计每一个窗口里面元素出现的个数并减去 1。
- 把剩下的值加起来并且返回所有大于 (s-a) * N 的值。
优点:
- 容易实现以及修改,能够控制元素频率以及误差。
- 快速高效,建立哈希表 V 只需要遍历一遍数据即可。
- 这个算法也适用于“如何设计一个显示最热门的 100个 标签的系统“这类场景。
缺点:
- 这个算法适用于玩家分布比较集中的情况,也就是说有很多玩家的分数是相同的。如果玩家的分数都不同,或者分布零散的话,哈希表 V 需要内存维护大量元素,会退化成桶排序。
- FindRank需要在哈希表 V 中遍历所有比该分数大的桶。
Frugal Streaming
Geohash / S2 Geometry 地理位置
Leaky bucket / Token bucket 限流器
Lossy Counting ,tok频繁 hashmap不停轮换请counter为0的
Operational transformation 操作转换,类似于google doc多人编辑时
Quadtree / Rtree ☑️
- 四叉树是一种数据结构,每一个节点有四个孩子。一般需要用到四叉树的情况往往是二位平面,通过把区域分成四个区块来定义。
应用:比如确定并显示一条曲线的具体位置时
Ray casting ☑️
Reverse index ✅
Rsync algorithm ✅
- Trie algorithm ✅
常见题目
系统设计参考1 Done
系统设计参考2 差不多,图片都失效了。
分布式ID生成器
发号器产生的 ID 一般都是 64 位整数,这样对数据库比较友好,容量也能满足业务需求
核心需求
- 全局唯一(unique)
- 按照时间粗略有序(sortable by time)
- 尽可能短
雪花算法:
- 4个字节表示的Unix timestamp,
- 3个字节表示的机器的ID
- 2个字节表示的进程ID
- 3个字节表示的计数器
时间在前面可保证有序
使用mysql自增id, 比如8台机器,每个机器每次+8。
不用进程ID就可以保证单调递增,但依赖时间。 雪花算法几乎可以是非常完美了,但它有一个致命的缺点 —— 强依赖机器时间。 如果机器上的系统时间回拨,即时间较正常的时间慢,那么就可能会出现发号重复的情况。对于这种情况,我们可以在本地维护一个文件,写入上次的时间戳,随后与当前时间戳比较。如果当前时间戳小于上次时间戳,说明系统时间出了问题,应该及时处理。
- 比如 让程序等待一段时间(如等待到
last_timestamp对应的时间后),保证生成的 ID 是单调递增的。 - 维护一个逻辑时间(
logical_timestamp),如果检测到时间回拨,则使用last_timestamp + 1作为时间戳,以避免回拨带来的影响。
前面加namespace, appId这样区分,分业务。
- 时间戳可以变成HLC时间戳,它是物理时钟 + 逻辑时钟,同时定时ping pong取最大值,每个物理时钟的逻辑时钟重新加一。
- 提前缓存生成的id到本地内存。
其它实现: mysql自增主键, redis自增。
短网址系统
需求
- 足够短
网上链接大概45亿,长度7的字符串足够了,每个元素是大小写字母+数字
用分布式id生成器生成短链,用Nosql kv来存, 短网址-> 长网址
使用302临时重定向。
id生成器是数字,再变成62进制这样变成字符串。
信息流
定时任务调度器
API限速
设计线程安全的hashmap
hashmap可以拉链法,也可以java8一样,不是拉链,而是个红黑树,解决了hash冲突后的问题。
可以像concurrentHashMap一样采用分段锁保护。
实时输出最近一个小时内访问频率最高的10个IP
3600s,3600个hashmap,存储每一秒的每个ip的访问次数。
同时还要新建一个固定大小为10的小根堆,用于存放当前出现次数最大的10个IP。堆顶是10个IP里频率最小的IP。
每次来一个请求,就把该秒对应的HashMap里对应的IP计数器增1,并查询该IP是否已经在堆中存在,
- 如果不存在,则把该IP在3600个HashMap的计数器加起来,与堆顶IP的出现次数进行比较,如果大于堆顶元素,则替换掉堆顶元素,如果小于,则什么也不做
- 如果已经存在,则把堆中该IP的计数器也增1,并调整堆
需要有一个后台常驻线程,每过一秒,把最旧的那个HashMap销毁,并为当前这一秒新建一个HashMap,这样维持一个一小时的窗口。
每次查询top 10的IP地址时,把堆里10个IP地址返回来即可。
如果内部存不下,可以使用redis等,同时时间跨度长的话还可以桶塌缩,近似统计。
设计一个负载均衡
负载均衡策略需要将请求均匀分配到各个服务节点,避免出现请求集中在某一点上的情况。有时会考虑节点权重,会话粘连等需求
服务端节点列表存储下来,定时探活。
随机:数组存储列表,随机数字。
无权重轮询:移动cursor,数组
有权重轮询:移动cursor,数组。权重分别为1,2,3的3该节点A,B,C,会先请求A一次,再请求B两次,再请求C三次
有权重的平滑权重轮询
所谓平滑, 即在一定的时间内, 不仅服务器被选择的次数分布和权重一致,满足权重要求,且调度算法还能比较均匀的选择节点分配请求
totalWeight:保存所有节点的权重和,该值在后续流程中保持不变
nodeOriginWeight:保持每个节点的原始权重,在后续流程中也保持不变
nodeCurWeights:保存每个节点的当前权重,该数组在后续每次计算请求应该分配到哪个节点时都会发生变化,初始化为每个节点的权重
每次选择节点,都会执行以下3步
- 选出当前权重中,值最大节点a
- 将a的当前权重值减去totalWeight
- 将每个当前权重加上每个节点的原始权重
原理:若某个节点增长越快,则越有概率被选中,而增长的速度和权重大小成正比,因此节点权重越大,越有概率被选中。相反或节点权重越小,增长成为最大当前权重节点的速度越慢,被选中的概率较低,从而达到按权重分配请求的效果
当每个节点被选中后,减去的值都相等,由于减去了一个较大的值(所有节点原始权重总和),使得该节点在下几次请求中,被选中的概率较低,因为恢复成为最大值需要时间。从而达到平滑的效果
最小活跃数:按活跃数排序,可以是avl树、跳表等。每次请求+1
一致性hash:参考个人blog,如数组二分查找、红黑树等,虚拟节点,hash个数字。
配置中心
配置中心的核心作用是 存储和管理系统的配置信息,并 确保所有服务获取到的配置数据是正确的。如果配置数据不一致,可能会导致 系统故障、服务异常、甚至宕机,因此 一致性比可用性更重要。 如果选择 AP,可能在分区期间读取到旧数据,导致配置回滚或者错误行为。
配置信息存储之后,需要考虑如何将配置的变更推送给服务端,这样就可以实现配置的动态变更,也就是说不需要重启服务器就能让配置生效了。
一般会有两种思路来实现变更推送:一种是轮询查询的方式;一种是长连推送的方式。
比较是否变化,可以比较MD5值,来降低全部拉取的带宽压力。 由于配置中心里存储的配置项变化的几率不大,所以使用这种方式后,每次轮询请求就只是返回一个MD5值,可以大大地减少配置中心服务器的带宽。
另一种长连的方式,它的逻辑是在配置中心服务端保存每个连接关注的配置项列表。这样,当配置中心感知到配置变化后,就可以通过这个连接,把变更的配置推送给客户端。这种方式需要保持长连,也需要保存连接和配置的对应关系,实现上要比轮询的方式复杂一些,但是相比轮询方式来说,能够更加实时地获取配置变更的消息。
配置服务中存储的配置变更频率不高,所以对于实时性要求不高,但是期望实现上能够足够简单,所以如果选择自研配置中心的话,可以考虑使用轮询的方式。
可用性:
- 配置存储是分级的,有公共配置,有个性的配置,一般个性配置会覆盖公共配置,这样可以减少存储配置项的数量;
- 配置中心可以提供配置变更通知的功能,可以实现配置的热更新;
- 配置中心关注的性能指标中,可用性的优先级是高于性能的,一般我们会要求配置中心的可用性达到99.999%,甚至会是99.9999%。
- 在配置中心的客户端上,增加两级缓存:第一级缓存是内存的缓存;另外一级缓存是文件的缓存。
Metrics 监控系统
使用时序数据库存储数据。

- Metrics Source 指标来源,应用服务,数据库,消息队列等。
- Metrics Collector 指标收集器。
- Time series DB 时序数据库,存储指标数据。
- Query Service 查询服务,向外提供指标查询接口。
- Alerting System 告警系统,检测到异常时,发送告警通知。
- Visualization System 可视化,以图表的形式展示指标。
Flink 适用于任何需要处理实时、大规模数据流的应用,特别是在对低延迟和高吞吐量要求较高的场景下。常见的应用领域包括金融、互联网、物联网、智能城市、企业监控等。
下采样是把高分辨率的数据转换为低分辨率的过程,这样可以减少磁盘使用。由于我们的数据保留期是1年,我们可以对旧数据进行下采样,这是一个例子:
- 7天数据,不进行采样。
- 30天数据,下采样到1分钟的分辨率
- 1年数据,下采样到1小时的分辨率。


ELK海量日志收集
ELK 是三个开源软件的缩写,分别表示:Elasticsearch、Logstash、Kibana,其中还没有提到轻量级的日志收集工具 Filebeat。以下是这几个组件的简介:
- Filebeat,轻量级的日志收集处理工具
- Logstash,主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。一般工作方式为 c/s 架构,client 端安装在需要收集日志的主机上(这里用 Filebeat 代替),server 端负责将收到的各节点日志进行过滤、修改等操作存储到 ES 或者其他存储系统上。
- Elasticsearch,是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。
- Kibana,提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。
权限系统设计
- 认证 (Authentication): 你是谁。
- 授权 (Authorization): 你有权限干什么。
系统权限控制最常采用的访问控制模型就是 RBAC 模型 。
什么是 RBAC 呢? RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。
简单地说:一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,这样就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系。

- 用户表
- 角色表
- 菜单表
设计文件系统
系统核心功能:上传文件和下载文件
背景知识:
- 一个文件的数据主要由两部分组成:元数据和具体的文件数据
- 元数据描述了文件的基本信息,如文件名称,大小,格式.
- 元数据的访问频率远高于具体的文件数据,我们会查看文件夹里的内容,但不会每个文件都打开,因此元数据和文件数据一般是分开存储的
- one master + chunk servers
- master 存储文件元信息和文件chunk所在服务器信息
- chunkserver存储具体的文件chunk
上传: 客户端需要先将大文件分片
- 客户端发送文件名(文件ID)和chunk编码
- 服务端返回该chunk应该写在哪个哪台服务器上
- 客户端传上传具体的分片数据
- 返回写入成功
订单撮合系统
分为交易控制(包含订单校验),撮合和清算,分别做成三个微服务。
撮合不涉及账户余额与持仓, 那是交易系统或者清算该考虑的事。 清算偏离线计算
首先放到内存里,崩的场景非常小,其次如果崩了,不可能没有主从、双主、也可以保证无缝切换,这样也能保证事务,重启的时候,就像redis的aof,肯定有操作日志的保存的,再执行一遍就行了
撮合模块,我们的撮合和回报流程选用了netty websocket进行推送,分布式异步无阻塞处理,内存撮合,写操作采用交易日志同步写,数据库持久化采用异步线程操作的方式,总体性能还可以,吞吐量可以达到每秒2W笔左右,单笔延迟100ms左右
对于撮合交易系统,交易吞吐量和延时永远都是最核心的指标
评论系统设计
评论可能会盖楼,分为一层、两层
评论上记录item_id 和parent_id。parent_id 不为空就是二层的。
按照时间排序。每个评论读时过滤可见性。
设计Key-Value存储引擎
大数据
对账
对账的核心即为两边数据的对比,因此如上所示会存在4种比对情况。
我方有银行无、银行有我方无、双方有但金额不一致、双方有且金额一致。
火车票订票系统
