LeeYzero的博客

自强不息,厚德载物

0%

最近又看了一遍 End-To-End Argument In System Design,有一些新的思考,但都集中在一些点上,不够系统,在此先记录下来,后续有新的想法再做补充和整理。

核心观点

这篇论文在由MIT计算机科学实验室发表于1984年,是一篇非常经典的关于系统设计的论文。论文论证了分布式系统设计的一个事实:端到端的可靠通信只能由通信的两端(End-Point)来保证,而中间的媒介(如消息中间件、网关、路由器以及TCP协议栈等)只能提高通信效率,但无法保证通信两端的可靠性。

在一个系统设计中,系统设计师的主要工作是对功能进行合理抽象,明确定义功能边界。将功能职责进行合理划分的设计原则是系统设计师最重要的工具之一,端到端设计原则便是这样的工具,它在分布式系统设计中,对功能职责的划分起了一定的指导作用。

Read more »

文件同步是利用网络将多个电脑或移动设备之间的文件进行同步的网络服务。文件同步的本质是对比网络上两台设备之间的文件变更,然后将文件的不同部分通过网络进行传输,以达到文件同步的目的。本文介绍dropbox的文件同步实现原理。

基本概念

文件系统

在本地电脑上,一个文件可以用文件路径来标识。但对于dropbox需要支持共享目录,定义了名字空间(namespace)的概念,用于对传统文件系统的抽象。每一个共享目录有一个惟一的名字空间,每个用户有一个根名字空间,每个共享目录可以挂载(mount)到不同的用户根名字空间下。即对于dropbox的文件可以通过名字空间和相对路径<namespace,relative path>惟一标识。

文件格式

rsync算法的启发,dropbox把每个文件被分割成4MB的块(最后一个块小于等于4MB)。每个块通过计算出的SHA-256进行标识,对于每个文件内容,可以通过一个块列表blocklist引用。比如,文件video.avi大小了14MB,可以分割成4个块h1, h2, h3, h4,我们说文件video.avi的块列表blocklist是[h1, h2, h3, h4],如下图:

image

Read more »

最近关于B站在北邮校园招聘时,面试官对候选人打压的事件在知乎上讨论的很激烈。我并不想讨论这些言论的真假,但从这件事件反映出了B站面试官的不专业性。本文结合自身的一些招聘经验,从面试官角度谈谈应该如何面试候选人。

人才标准

每个公司或团队都有一个正式的或非正式的人才要求,即你想要雇用什么样的人?这是招聘的总体准则,这个准则因公司或团队而异,但可简单的概括为:聪明且会做事情的人

聪明和会做事情的人并不能划等号。有的人的确很聪明,但并没有将其聪明才智用到正确的地方,容易分散团队的精力;只会做事情的人往往缺乏自己的思考,容易人云亦云,很难有培养空间。

在面试的时候是可以区分出这两种类别的人的。聪明的人在沟通过程中比较顺畅,逻辑思维清晰,语言组织有条理,反映比较敏捷,对开放性的问题有自己独到的见解;会做事情的人通常需要从其过往学习、工作经验中进行考察,会做事情的人通常有始有终,对待工作认真尽责,有较强的团队合作能力。

Read more »

之前排查了一个服务hang死的线上故障,觉得这个问题比较有代表性,本文记录故障排查的经过,并做一些总结和思考。

现象

周末线上一个比较核心的服务(以下称为X服务)出现大量5xx报警。从客户端看到的现象是客户端请求X服务时,出现大量的链接被重置(connection reset by peer)的错误。

分析

从经验来看,90%以上的问题都是上线引入的。故障出现在周末,按规范来说,非特殊情况下,周末是不允许上线,跟相关角色确认后,本次故障不是上线引入。

观察线上流量,在出现故障时间点,流量的确有大幅上涨,从宏观分析来看,有可能流量突然上涨是一个诱因。

任意找了一台有问题的机器,发现了一个比较有意思的现象:服务X出现了大量CLOSE_WAIT状态的连接。从TCP的状态转换可知,CLOSE_WAIT是被动关闭一方在收到FIN并返回ACK后进入的状态。TCP状态机如下:

img

也就是说X服务在收到客户端请求后,客户端关闭连接,还服务端进程并没有关闭连接,分析了web server的框架代码,正常情况下,一个请求处理完后会关闭这个连接,出现这种情况可能是业务逻辑出现阻塞,导致服务端请求的连接一直不能关闭

查看了一下X服务打开的socket句柄数:

1
2
$ lsof | grep `ps -ef | grep x-service | grep -v 'grep' | awk '{print $2}'` | grep sock | wc -l
10231

发现X服务打开的连接数非常多,达到10231个,看下实例的句柄数上限:

1
2
$ unlimit -n
10240

句柄数像是已经被耗尽了,用strace看了下X服务的系统调用:

1
$ strace -p `ps -ef | grep x-service | grep -v 'grep' | awk '{print $2}'`

从系统调用日志中发现了一些关键信息:

发现大量accept调用报错,从日志信息可以看出,的确是系统的文件句柄数(FD)耗尽了,导致连接被reset掉,这也能说明为什么客户端侧看到了大量connection reset by peer错误了。

X服务打开了大量socket文件句柄,且绝大多数连接状态都是CLOSE_WAIT,如果业务逻辑有阻塞的确可能会出现把句柄数数打满。

分析了一下业务逻辑,业务逻辑本身不复杂,只有一次IO网络请求,是从数据库查询数据,从日志中发现了一些端倪:

Read more »

最近排查一个线上接口耗时上涨的问题,其中用到排查思路和相关工具有一定借鉴作用,在此做个记录,同时供网友参考。由于涉及到一些敏感信息,所以本文会对一些名称进行模糊化。

现象

监控发现对外接口的整体耗时上涨了近100ms,涨了近50%,甚至有少部分接口出现超时现象,已经影响到部分业务的用户体验。

分析

宏观分析

对比故障发生的时候点,检查对应时间结点是否内部服务有上线,通常情况下,90%以上的故障都是由上线引起的。但排查后,业务侧并未上过线,排除是业务上线引入的故障。

对比不同机房,服务部署在三个机房,记为机房A,机房B和机房C,发现耗时主要发生在机房A,机房B和机房C并不存在这个问题,怀疑是机房的网络链路问题。

联系负责机房的同学一起排查,未发现网络链路问题。将某个接口所有的流量从机房A切到机房B,发该接口的耗时恢复到之前的水平,看起来的确像是出现机房A网络存在问题。但OP同学再三确认,未发现异常。

Read more »

Code Review是保障代码和产品质量的重要手段,但却被绝大部分公司所忽略。本文主要基于Google对Code Review的实践,结合自身的经验谈谈团队中该如何做Code Review。

1. 什么是Code Review

Code Review是代码评审人(Code Reviewer)对代码提交者(Code Committer)做审查(Review)的过程。

2. 为什么要做Code Review

  • 提升代码/产品质量
  • 团队工程师文化传承
  • 团队成员间知识/经验分享
Read more »

搭建环境是一件很无聊的事情,最近换了一个较新的系统,少了很多系统级的依赖环境问题。本文简单记录搭建hexo环境的步骤,以便后续查阅。

系统环境

CentOS 8.x

安装依赖环境

至少10.13,建议12.0或更高版本。建议使用二进制方式安装

1
$ sudo yum install git-core

安装Hexo

  • 使用npm安装hexo
1
$ npm install hexo
  • 添加环境变量
1
$ echo 'PATH="$PATH:/path/to/node_modules/.bin"' >> ~/.profile
  • 测试
1
$ hexo version

参考资料

[1] hexo官方文档
[2] Nodejs官方文档

周末大清早就被报警短信吵醒,故障表现为离线存储集群流量突增,集中在热点分片,而且流量越来越大,系统吞吐、稳定性均在降低。最终发现是因为实例间时区不一致触发一个隐藏的BUG导致。这个问题在分布式系统中很具有代表性,在此做个记录以备忘。

症状

  • 离线存储集群流量突增,集中在热点分片;
  • 消息系统中消息在持续积压;
  • 消息系统收到大量重复ACK;
  • 业务worker消费到大量重复的消息;
Read more »

RAII作为C++资源管理的一种惯用法,是每一位C++程序员都应该掌握的基本技能。在google上搜索关键字RAII, 有二百多万条搜索结果。说明这个话题在网上已经被讨论过无数次,也发现了一些好文章给我不少启发,这篇文章主要是做个总结并谈谈自己的理解。

什么是RAII

资源获取即初始化(Resource Acquisition Is Initialization),即RAII。RAII是一种C++编程技术。它利用栈对象在离开作用域后自动析构的语言特点,将受限资源的生命周期绑定到该对象上,当对象析构时以达到自动释放资源的目的。 这里说的资源都是指的受限资源,比如堆上分配的内存、文件句柄、线程、数据库连接、网络连接等。

Read more »

在计算机中,锁是用于解决资源竞争问题。在单机(单进程)环境下, 锁可以使用操作系统提供的同步原语实现。 但在分布式环境下,操作系统提供的同步原语就失效了, 需要一个分布式锁。其原理是需要一个分布式锁管理器[1],提供进程级别访问共享资源的互斥性。本文主要讨论基于Redis实现的分布式锁。

分布式锁的使用场景

Martin Kleppmann 在他的博客 How to do distributed locking[2] 中对分布式锁的使用场景做了非常好的概括。从一个更高层次来讲,在一个分布式应用中,使用分布式锁主要有两个原因:效率和正确性。

  • 效率:获取分布式锁可以避免相同的任务被处理两次。如果锁失败,带来的结果就是对某一个子任务多做了一次,其影响完全取决于具体业务场景。比如为了提高消息PUSH效率,需要按用户进行分片,然后每个任务获取一个锁后处理对应的分片,如果锁失败,会造成重复给用户PUSH。
  • 正确性:获取分布式锁是为了防止进程对分布式系统中的资源并发访问而导致系统的状态出现混乱。如果锁失败,两个节点并发的访问同一个共享资源,可能造成数据的不一致性,如文件损坏或数据丢失等。
Read more »