系统设计的几个场景问题

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: 《基础》

怎么设计一个大文件上传的功能?

首先如果是大文件上传,考虑到网络不稳定容易造成上传失败,或者需要做断点续传功能,是不是对整个文件直接进行上传的。

1.计算hash

首先是让前端对大文件计算hash值,主要是用于后端去判断这个文件在服务器上是否已经存在,其次是这个hash值可以作为上传文件的一个标识。 如果是直接对整个文件计算hash值,文件过大时,可能会比较慢,通常是对文件进行抽样计算。根据hash值判断文件是否在后端已经存在,已存在就不进行上传了。

影分身Hash

就是把文件切分成2M的分片,然后对首文件+中间每个文件的首中尾取2个字节+尾文件,进行合并,计算合并文件的MD5值,作为文件的hash值。

如果这个hash值在后端存在: 说明这个文件可能存在也可能不存在。准确性不是100%。

如果这个hash值在后端不存在: 说明这个文件一定不存在。准确性是100%。

通过这种方式判断的思路跟布隆过滤器比较像。

2.分片上传

上传时不能一窝蜂地把所有分片文件发给后端,是把每个分片包装成一个网络请求,使用异步线程对从队列里面每次取一个分片进行上传。 每个分片文件都有一个唯一标识,就是hash值+分片编号。这样如果上传中断了,下次再进行上传时,后端可以知道哪些分片已经上传,把未上传的分片唯一标识返回给前端,前端只需要上传上次未上传的分片,这也就是断点续传。

https://zhuanlan.zhihu.com/p/104826733

3.合并请求

有两种方案,一种是后端记录所有分片的上传状态,当所有分片全部上传完毕后,自动合并文件。另外一种就是前端发现传完所有文件后,调用接口通知后端去合并。

谈一谈分布式ID生成方案的了解?

首先ID生成方案的技术考虑点: 唯一性:不能重复。 趋势递增:保证id作为主键时,插入数据库时的顺序性,避免随机插入。 单调递增:满足某些特殊业务的要求,保证后一秒请求生成的id比前一秒的大。 信息安全性:不要像UUID一样泄露mac地址,也不要像数据库主键ID自增完全连续,泄露每日id生成数据量。

1.UUID模式

太长,占用存储空间过大 id是字符串类型,查询成本高于数字类型 如果是包含mac地址的UUID会泄密

2.单机数据库主键自增模式

id生成的量受限于单机MySQL数据库的性能 强依赖于数据库,主从切换时容易导致重复发号 容易泄露id生成量

3.多机数据库主键自增模式

主要是将每个数据库的步长设置为一样,但是起始值不一样,以此错开生成的id,不便于扩展。

4.Leaf号段模式模式

就是数据库存储一个maxId代表已经发放的id最大值,每次将maxId更新为max+step,取step数量的id发放。 优点: 1.便于扩展,发号性能取决于step,可以动态调整。(Leaf做了Step动态调整策略,一个号段使用时间<15分钟,就让号段拥有的id量step翻倍(直到最大阀值100万),一个号段使用时间>30分钟,step减半(直到最低阀值,初始号段id量)。) 2.即便主节点的宕机,短时间Leaf也能继续提供服务,其次是主从切换时影响较小。 缺点: 1.当号段里面的id用完时,会去数据库取新的号段,此时如果来了获取id的请求会需要进行等待。(Leaf做了双Buffer优化,使用了双Buffer各存储一个号段,当一个号段使用量达到10%后,就触发另一个号段去数据库取新号段进行更新,以便于当一个号段使用完时,可以直接切换到未使用的号段。) 2.id是连续的,容易泄密。(可以自定义抛弃策略,取号段时的时候抛弃一些id,或者定时抛弃掉一些id。)

5.Leaf-snowflake模式

就是沿用了snowflake原本的位数分配算法,1标志位+41位毫秒时间戳+10位机器位+12位序列号。使用zookeeper作为注册中心,id生成服务启动时,去指路径下获取所有节点的列表,判断当前ip+port是否有对应的workid存在,有就使用,没有就往插入一个新的永久顺序节点,序号则为workId(并且会将workid缓存到本地磁盘上)。运行期间每过3s,都会上报最新的时间戳到zookeeper。 时钟回滚的处理:启动时: zookeeper里面会存上次生成id的时间戳,如果上次存储的时间戳>当前系统时间戳,那么就抛出异常,启动失败。 运行时: 如果获取id时,发现上次生成id时的时间戳>当前系统时间戳,那么说明运行时发生了时钟回滚,如果回滚的时间差<5ms,就调用wait()方法等待10ms,然后再获取id,时间差>5ms,就抛出异常。

优点:

时钟回滚优化

1.对时钟回滚做了特殊处理。

zookeeper弱依赖

2.为了减轻了zookeeper的弱依赖,实现在zookeeper挂了的情况下,id生成服务也能启动,每次启动后,在本地也缓存workid配置,一旦启动时,发现zookeeper连接不上,就通过从本地缓存配置中读取workid。(但是这样也有问题,本地缓存配置只存了workid,没有存上次生成id的最大时间戳,所以一旦启动前发生了时钟回滚,或者是修改了系统时间,这样从本地缓存配置中读取workid生成的id就可能是重复的。)

时间差优化

3.做了时间差优化,就是默认的时间戳是从1970年开始的,leaf是自己选定了2010年的一个时间点,以此来计算时间戳,这样可以在时间位数固定的情况下,增长服务最大运行时间。在毫秒时间戳为41位的情况下,时间差最大是69年,如果以1970年为起点,那么最大时间就是1970+69年,如果以2010年为起点就是2010+69年。

序列号优化

4.为了防止生成的id的序列号部分都是从0开始,导致插入数据库时,有数据倾斜的问题,所以每次用新的毫秒时间戳时,序列号不是从0开始,而是计算一个0到100之间的随机数作为起点。

缺点:

1.注册中心只支持Zookeeper

2.潜在的时钟回拨问题

3.时间差过大时,生成id为负数。

6.百度的uid-generator模式

默认模式

每次启动时向数据库插入一条数据,这行数据的主键是自增的,主键id就是workId,

因为默认是snowflake算法是1标志位+41位时间戳+10位机器号+12位序列号

因为百度的是每次启动都获取新的机器号,所以它修改了这些位数配比,是

1标志位+28位的秒级时间差+22位的机器号+13位的序列号,所以总共支出2的22次方次启动,也就是400万次启动。最大服务支持时间是228次方,也就是8.7年。(优化点是修改位数分配,让服务时间更长,我们的位数分配是*30位秒级时间差+16位机器号+7位序列号**,最长服务时间支持34年,6.5w次机器启动,每个机器每秒128个并发,总共位数没有用到64位,只用到53位,这样生成的id转化为10进制更小。)

解决时间回拨问题:

  • 启动时时间回拨

因为是每次都用新的机器号,所以当前机器号都是之前没有的,所以即便时间戳回拨也不影响。

  • 运行时时间回拨

会使用lastSecond来记录上次生成id的时间戳,如果当前时间戳比lastSecond还小,就抛出异常。(优化点就是回拨时间差较小时进行等待,较长时再抛出异常。)

缺点:

1.默认的最大服务年限太短,只有8年。

2.回拨时间差较小时也是抛出异常,没有额外的判断逻辑。

3.没有像Leaf一样做序列号优化,可能生成的id序列号部分都是从0开始的多一些,可能会存在数据倾斜的问题。

缓存模式

主要继承自默认模式,只是用一个环形数组来存储生成好的id,每次去环形数组中去,默认大小是2的13次方,8192。这种模式使用的时间取得不是实时的系统时间,而且使用启动时的时间,每次生成一组id时,对之前保存的时间+1。

阀值检测预填充:取id时,发现可用id数小于阀值50%时,就对后面已经使用的id进行再填充。

定期填充:每5分钟定期会去检查环形数组中id使用情况,然后生成一组最大序列号个数的id(默认是8192个),然后进行填充,多的直接丢弃掉。

缺点

1.id只有在定期填充时,会丢弃掉一些id,其他情况下,id是完全连续的。假如每次使用量比较大,大部分时候都是5分钟内能用掉50%的话,那么就就不会触发定期填充,也没有id丢弃,导致id会一直连续,容易泄露数据信息,所以最好自定义丢弃逻辑。

2.其次是id跟生成id时系统的时间戳无关了,可能无法满足一些特殊业务的需求。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
6月前
|
存储 消息中间件 算法
软件体系结构 - 系统分析与设计(1.结构化方法)
【4月更文挑战第5天】软件体系结构 - 系统分析与设计(1)
136 0
|
4月前
|
数据库
系统分析与设计问题之什么是软件分析和软件设计
系统分析与设计问题之什么是软件分析和软件设计
|
6月前
|
C++
车辆管理系统设计(C++)
车辆管理系统设计(C++)
55 2
|
6月前
|
开发者 数据格式
【软件设计师备考 专题 】设计系统功能:系统结构和子系统
【软件设计师备考 专题 】设计系统功能:系统结构和子系统
159 0
|
存储 安全 算法
系统设计的端到端原则
系统设计的端到端原则
69 0
|
运维 监控 安全
|
存储 监控 安全
垃圾处理厂SCADA系统设计与开发
垃圾处理厂SCADA系统设计与开发
|
算法 NoSQL 数据库
CMMI流程之系统设计
CMMI流程之系统设计
197 1
|
存储 算法 安全
【系统设计】系统设计基础:速率限制器
【系统设计】系统设计基础:速率限制器
|
存储 SQL 缓存
用户系统设计
注册、登录、查询、用户信息修改,哪个需求量最大? 支持100M DAU。注册,登录,信息修改 QPS 约 100M * 0.1 / 86400 ~ 100 0.1 = 平均每个用户每天登录+注册+信息修改 Peak = 100 * 3 = 300
196 0