Neo's Blog

不抽象就无法深入思考
不还原就看不到本来面目!

0%

问题:

从300万字符串中找到最热门的10条搜索的输入信息是一个字符串,统计300万输入信息中的最热门的前10条,我们每次输入的一个字符串为不超过255byte,内存使用只有1G。请描述思想,写出算法(c语言),空间和时间复杂度。

答案:

300万个字符串最多(假设没有重复,都是最大长度)占用内存3M*1K/4=0.75G。所以可以将所有字符串都存放在内存中进行处理。

可以使用key为字符串(事实上是字符串的hash值),值为字符串出现次数的hash来统计每个字符串出现的次数。

并用一个长度为K的堆来的数组/链表存储目前出现次数最多的10个字符串。

设计要点:

长链接接入网关

  • 接入层:如何做负载均衡(基于IP 还是 基于7层的用户唯一标识)
  • 就近接入
  • 接入层如何升级:尽量减少升级,拆分为负责连接的进程与负责处理业务的进程,两者之间通过共享内存通信
Read more »

设计一个带有有效时间TTL的KV存储系统,包含set(key,value,ttl)、get(key)方法、怎么优化

首先是KV存储,可以使用levelDB作为我们的存储引擎;

另外,需要考虑数据的复制与分片、去中心化等

把TTL当作value,当进行compaction时,过期的数据会被忽略。

设计要点:

  1. 业务接入:频率限制、quota管理
  2. 接入队列:分队列,按照优先级、重要性等进行隔离
  3. 客户端接入:维护与客户端的长链接
  4. 用户状态的识别与路由:是否在线、是否获取、第三方接入等
  5. 调用第三方时的频率控制
  6. 接入安全:数据的加密
  7. 心跳保活
  8. 推模式,拉模式,推拉结合

如何才能更好地理解秒杀系统呢?

一个秒杀系统的架构,包括CDN,反向代理,session共享,由于分布式数据库我不熟,所以数据一致性那部分没有解决。

10wQPS量级架构

主要技术点:

(1)缓存

(2)独立秒杀系统、独立集群

(3)验证系统,防秒杀器

100wQPS量级架构

主要技术点:

(1)动静分离

(2)本地缓存

(3)热点隔离

权衡点:要想获得极致性能,必然会牺牲通用型、易用性等

动静分离

“动态数据”和“静态数据”的主要区别就是看页面中输出的数据是否和 URL、浏览者、时间、地域相关,以及是否含有 Cookie 等私密数据

第一,你应该把静态数据缓存到离用户最近的地方。

第二,静态化改造就是要直接缓存 HTTP 连接。

第三,让谁来缓存静态数据也很重要。(一般是web服务器来做,而不是应用服务器)

URL 唯一化;分离浏览者相关的因素;分离时间因素;异步化地域因素;去掉 Cookie

动态内容的处理通常有两种方案:ESI(Edge Side Includes)、CSI(Client Side Include)

实体机单机部署方案

Cache 分成若干组,是希望能达到命中率和访问热点的平衡。Hash 分组越少,缓存的命中率肯定就会越高,但短板是也会使单个商品集中在一个分组中,容易导致 Cache 被击穿,所以我们应该适当增加多个相同的分组,来平衡访问热点和命中率的问题。

不容易运维;浪费CPU

统一Cache 层

网卡瓶颈、丢失数据

CDN部署

CDN:失效问题、命中率问题、发布更新问题

二级cache是指cdn设置了多级回源机制,就是如果缓存没有命中再到二级缓存中去取,而不是直接回服务端来请求。本质是减少回源的请求量

二八原则:有针对性地处理好系统的“热点数据”

热点:热点操作(读操作、写操作)、热点数据(静态热点数据、动态热点数据)

热点发现:对于静态热点(人工标识、大数据统计计算),以及实时热点发现方案

动态热点发现系统

热点处理:

(1)优化:缓存、LRU

(2)限制:hash分桶,避免相互影响

(3)隔离:从上到下三个层次,业务隔离、系统隔离、数据隔离

流量削峰

常见做法:

(1)排队-对发出来的请求进行缓冲(消息队列、文件缓存、内存队列、线程池加锁等)

(2)答题-少发请求(两个功效:防止秒杀器;延缓请求,将请求峰值按照时间分片-从1s延长到2~10s)

(3)分层过滤-不符合条件的请求进行过滤(交易性的写请求)

分层过滤

分层校验的目的是:在读系统中,尽量减少由于一致性校验带来的系统瓶颈,但是尽量将不影响性能的检查条件提前,如用户是否具有秒杀资格、商品状态是否正常、用户答题是否正确、秒杀是否已经结束、是否非法请求、营销等价物是否充足等;在写数据系统中,主要对写的数据(如“库存”)做一致性检查,最后在数据库层保证数据的最终准确性(如“库存”不能减为负数)。

极致优化

首先是“发现短板”,比如考虑以下因素的一些限制:光速(光速:C = 30 万千米 / 秒;光纤:V = C/1.5=20 万千米 / 秒,即数据传输是有物理距离的限制的)、网速(2017 年 11 月知名测速网站 Ookla 发布报告,全国平均上网带宽达到 61.24 Mbps,千兆带宽下 10KB 数据的极限 QPS 为 1.25 万 QPS=1000Mbps/8/10KB)、网络结构(交换机 / 网卡的限制)、TCP/IP、虚拟机(内存 /CPU/IO 等资源的限制)和应用本身的一些瓶颈等。

其次是减少数据。事实上,有两个地方特别影响性能,一是服务端在处理数据时不可避免地存在字符到字节的相互转化,二是 HTTP 请求时要做 Gzip 压缩,还有网络传输的耗时,这些都和数据大小密切相关。

再次,就是数据分级,也就是要保证首屏为先、重要信息为先,次要信息则异步加载,以这种方式提升用户获取数据的体验。

最后就是要减少中间环节,减少字符到字节的转换,增加预处理(提前做字符到字节的转换)去掉不需要的操作。

此外,要做好优化,你还需要做好应用基线,比如性能基线(何时性能突然下降)、成本基线(去年双 11 用了多少台机器)、链路基线(我们的系统发生了哪些变化),你可以通过这些基线持续关注系统的性能,做到在代码上提升编码质量,在业务上改掉不合理的调用,在架构和调用链路上不断的改进。

防超卖

减库存的三种时机:

(1)下单后

优点:体验好,不超买

不足:恶意下单

(2)支付后

优点:不会被人恶意刷单

不足:存在付款后超卖的情况

(3)预扣库存(为用户保留一段时间)

优点:一定程度上缓解上面的问题

不足:没有根治,需要结合风控策略来综合考虑

解决大并发读问题,可以采用 LocalCache(即在秒杀系统的单机上缓存商品相关的数据)和对数据进行分层过滤的方式。

像减库存这种大并发写无论如何还是避免不了,这也是秒杀场景下最为核心的一个技术难题

一般的电商系统,通常采用第三种减库存的方式;

而对于秒杀系统,我们更多的采用第一种方式。原因在于:

(1)秒杀系统的商品对库存都有比较严格的管控

(2)下单后不支付的概率比较小

秒杀商品和普通商品的减库存还是有些差异的,例如商品数量比较少,交易时间段也比较短,因此这里有一个大胆的假设,即能否把秒杀商品减库存直接放到缓存系统中实现,也就是直接在缓存中减库存或者在一个带有持久化功能的缓存系统(如 Redis)中完成呢?

应用层做排队。按照商品维度设置队列顺序执行,这样能减少同一台机器对数据库同一行记录进行操作的并发度,同时也能控制单个商品占用数据库连接的数量,防止热点商品占用太多的数据库连接。

数据库层做排队。应用层只能做到单机的排队,但是应用机器数本身很多,这种排队方式控制并发的能力仍然有限,所以如果能在数据库层做全局排队是最理想的。阿里的数据库团队开发了针对这种 MySQL 的 InnoDB 层上的补丁程序(patch),可以在数据库层上对单行记录做到并发排队。

在活动开始之前一段时间,把商品库存放在Redis中。

手段:通过Redis来抗,Lua脚本来完成CAS操作

https://www.yuque.com/chenboxue/kb/gmy24m

高可用建设

高可用建设

运行时:
体验降级:牺牲了一部分次要的功能和用户的体验效果
限流
拒绝服务,避免打死长时间无法恢复
熔断

网站的高可用建设是基础,可以说要深入到各个环节,更要长期规划并进行体系化建设,要在预防(建立常态的压力体系,例如上线前的单机压测到上线后的全链路压测)、管控(做好线上运行时的降级、限流和兜底保护)、监控(建立性能基线来记录性能的变化趋势以及线上机器的负载报警体系,发现问题及时预警)和恢复体系(遇到故障要及时止损,并提供快速的数据订正工具等)等这些地方加强建设,每一个环节可能都有很多事情要做。

设计难点

解决秒杀这种特定业务场景,可以使用 CDN 的边缘结点来扛流量,然后过滤用户请求(限流用户请求),来保护数据中心的系统,这样才让整个秒杀得以顺利进行。

Read more »

有些时候,确认需求比思考方案更加重要、更加困难。

在设计一个短网址系统时,我们需要考虑:

  • 重定向方式:301 还是 302

302(临时重定向)更合适。永久重定向的话,浏览器会缓存重定向结果,造成某些依赖重定向的统计结果不准。

Read more »

不得不说的随机

拿音乐播放器的随机播放举一个例子,一般音乐播放器的随机播放分两种:

  • 播放当前歌曲时才随机生成下一首,即完全随机(称为Random算法)
  • 将当前的list打乱顺序,然后依次播放,也就是大家所说的伪随机(称为Shuffle算法)

对我们的Shuffle算法进行下抽象:

一个从1到n的序列,随机打乱,保证每个数出现在任意一个位置的概率相同。

Read more »

地图最短路径

  1. 建模:有向有环图,带权重,权重不为负数
  2. 选择合适的单源最短路算法(Dijkatra、BellmanFord)

唯一ID的用途

  • 作为业务数据的唯一标识,用该ID来进行分库分表
  • 使用绝对自增的ID作为绝对时钟的模拟

业务系统对ID号的要求

概括下来,那业务系统对ID号的要求有哪些呢?

  • 全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。

  • 趋势递增:可以作为排序字段

  • 单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。
  • 信息安全(防逆向):如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。
  • 一般会将该ID用作索引,为性能考虑考虑的话,一般使用64位整数。如果允许用字符串的话,用上面的UUID即可。
  • 实际项目中,我们更有可能使用53位整数作为唯一ID(主要考虑是JS等语言或者JSON协议等对int64的支持不好,其限制在于仅支持float)
Read more »