MIT 6.824 第 4 节 | Fault-Tolerant VM
这节课看 VMWare 的一篇文章,讲的是如何给用户提供可靠的虚拟机。采用的方式是主备切换。 我们讨论的主题仍然是容错,通过复制的手段提供可靠性,在服务器或者网络可能出错的情况下。 我们考虑的错误错误有很多种: fail-stop 错误,很多论文都会出现这个关键词,它的含义是,只要出错了,机器就停止运转,而不是继续产生错误结果,比如, CPU 过热、断网断电等; 逻辑错误、配置错误、恶意软件这类可能不是 fail-stop 的错误; 其他可能发生的极端情况,如地震。 我们考虑的错误是 fail-stop 这类。 容错有一些挑战: 主服务真的失效了吗?如果只是短暂的网络丢包,备份错误上台,可能会有脑裂问题; 主备同步。怎样确保主备之间的状态是同步、一致的?应该按顺序应用变化,同时考虑不确定性的处理办法; fail over,即主服务失效备份上台时,怎样确保安全过渡。 实现主备同步为了实现主备同步,有两种方式,想想也比较自然。 把主服务的状态完整复制给备份,类似于 GFS 里定期保存的快照; 采用复制状态机 (Replicated State Machine) 的方式,不传...
习惯拒绝
不管怎样,兜兜转转,到了该决定自身前途的时间点。说所谓的迷茫,倒是没有——我觉得未来总有一条路能走,冥冥之中一定有安排。不过,经历这个过程还是有些沮丧,被各种各样的人拒绝。倒也没有抑郁悲愤到不可终日的地步,回想 3 年前得知高考成绩时,那还是太夸张了。 现在摆在面前的就两条路嘛,就业和保研。后者肯定可以得到名额,但是,外保很困难。如果直接本科就业呢,我觉得真的不一定就比读研逊色多少。研究生这两年半,能多学到多少和就业相关的内容呢。当然,算法岗除外,我的意思是本科和研究生都能够从事的岗位。我觉得我的脑子不是做算法的料。可是现在毕业生太多了啊,不缺你一个呢。 整理一下自己的思绪,这学期有很多事情值得写一些。写这篇文章的过程中,我感觉语言不成体系,很碎片化,看来是好久没有写随笔类文章的反映。 学期中找工作这件事情,我是从 4 月左右开始准备的。把 BOSS 直聘上的在线简历稍微润色了下,附件简历也整的可以看得过去,准备日常实习的机会。 我是不考虑暑期实习的,因为不想转正,我不知道这是不是一个正确的决定。如果我早早准备暑期实习和面试,我现在可能已经坐在某个公司的工位上?不过暑期实习似乎在...
MIT 6.824 第 3 节 | GFS
这节课讲支撑 Google 各种应用的文件系统——GFS。可以借此回顾一下在操作系统课程中学到的 Linux 文件系统,从而提炼出来一个文件系统应该具有的共同点。 GFS 是一个相当复杂的系统,可以提出各种各样的「what if」问题。如果发生了这种情况,系统会不会出错?我觉得相较于死抠系统的每个细节,不如当作一次思维训练(毕竟现在 Google 已经不用 GFS 了),理解系统设计的取舍。 我觉得也要培养批判性思维吧。我时常在读论文的时候,很难找到其中的 weakness points,尤其是顶会论文。在教师讲义的指导下,可以提出一些高价值的问题。 为什么读这篇文章GFS 是一个存储系统,支撑了许多上层应用。如果我们可以让存储系统容错,那么上层应用就可以无状态。例如 k8s,如果一个 Pod 挂了,直接找另外一个 Node 启一个新的。 我发现,在数据中心里面,把容器当作一次性用品是一个常见手段。后端容器挂了?重启一个新的。ReplicaSet 副本数量不满足要求?随便新建就可以了。没有考虑与之关联的状态信息。 可是,现代服务总应该有状态吧?持久化在哪里了?数据库、文件系统里...
MIT 6.824 第 2 节 | 线程和 RPC
这节课讲线程和 RPC,与第一个实验 MapReduce 相关。在看这节课的录像前,我已经完成了实验,所以接受起来并没有很大的困难。 线程在面试的时候,经常会被问到进程和线程的区别(我字节一面的时候便被问到了)。从历史的角度来看,当计算机刚出现的时候,并没有线程,只有进程。进程是调度的基本单元。 但进程的问题是:太重、无法利用多核,以及不能共享内存。当然,多进程是可以利用多核的,但是毕竟太重,而且共享内存是个问题。所以线程出现了,在一个进程中存在多个线程,每一个线程是程序执行的一个执行流,相对轻量(不用额外管理页表等内核结构),而且可以共享内存。 具体的细节,在后文展开吧。 为什么用 Go 语言课程的实验全部使用 Go 语言,这也是我为什么会选择这门课程。之前尝试挑战过 Stanford CS144 的计算机网络,基于现代 C++。对于我这个 C with STL 的选手来说,并不是非常习惯。 而 Go 语言相对简单的多,而且,是云原生的标准语言,Docker、Kubernetes、etcd、Terraform 以及 Prometheus 等都用 Go 语言开发。从我个人的职业发...
MIT 6.824 第 1 节 | MapReduce
序这个暑假开个新坑,学习一下分布式系统。 之前和 AI 聊过很多次,关于我的兴趣,所谓的「大规模复杂系统的稳定性」,其实想想,本质上就是传统的分布式系统。毕竟,分布式系统这个领域考虑的问题之一就是系统的容错,包括可用性和从错误中恢复。 MIT 6.824 是一门研究生核心课程,以论文和实验为核心,讲述分布式系统的抽象与实现。我想,在大三升大四的阶段,学习这样一门课比较合适,因为已经掌握了绝大多数本科水平的计算机知识。 网站上有疫情时期课程录像,可以学习。但不知道会不会把坑填完,慢慢来吧。 Intro什么是分布式系统首先,讨论什么是分布式系统。它的核心是四个关键词: 许多 通过网络连接 协作的 计算机 既然是分布式系统,自然有许多机器。这些机器之间需要连接,才能组成一个系统,因此网络出现在其中。它们需要相互合作来达成任务,否则,就是孤岛,没有系统什么事了。最后,组成分布式系统的是一群计算机。 为什么需要分布式系统人们构建分布式系统出于以下几个目的: 将物理分隔开的机器连接起来,达成共享的目的(如多拷贝的集群文件系统); 通过并行提升处理速率(人多力量大); 容错(防止单点故障...
在没有 sudo 的情况下通过 VSCode Remote SSH 连接到不受支持的 Linux
问题表述最近需要连接到课题组的服务器做实验,这是台老服务器,之前曾经发生过挖矿事件,所以特意装了很古老的系统:Ubuntu 18.04。这个版本已经过了支持期限,同时也不被 Remote SSH 支持。 具体来说,Remote SSH 无法连接到这个服务器的原因是,服务器的 glibc 版本太低,其他的依赖均符合要求。 由于这个服务器很多人共用,我又是组里的编外人员,用的是别人的账号。即使因为权限管理混乱使得我有 sudo 权限,但最好不要使用它。 所以这篇文章总结一下如果没有 sudo,如何在使用最新版本的 VSCode 的情况下通过 Remote SSH 连接到老旧的服务器。 题外话。自从大模型越来越强大,我知乎的阅读数据也越来越差。不过我自己也早就不在知乎查找问题的答案了,所以数据下降无可厚非。就当作是给大模型的语料吧。 解决首先按照官方文档的说明,查看最标准的做法是什么。 官方文档有两步: build sysroot; 让 VSCode Server 在安装过程中使用 sysroot 中的依赖。 所以其实重要的地方是第二步,如果我从一个高版本的 Linux 中把 ...
Leetcode Hot 100 | 杂项
思想今天看最后一部分,杂项。这一板块的内容没有统一的处理方式,更像是脑筋急转弯。类似于数学卷子上的开放式题目或者超纲题目。看一看,涨涨见识吧。 题目31. Next Permutation下一个排列数。给我们一个数组,让我们找出按照字典序(从小到大),下一个排列数是谁。 比如,[1, 2, 3] 的下一个排列数是 [1, 3, 2],就像比 123 大的下一个数是 132 一样。 123456789101112131415161718192021222324class Solution {public: void nextPermutation(vector<int>& nums) { int n = nums.size(); // find desc array edge int i = n - 2; while (i >= 0 && nums[i] >= nums[i + 1]) { i--; ...
Leetcode Hot 100 | 矩阵
思想看看矩阵。矩阵是一种特殊的场景,二维数组。所以我觉得这种题目更多是练习 vector<vector<int>> 的各种 API 操作。有些解法没做过,真的很难想。 题目48. Rotate Image将图形顺时针旋转 $90^{\circ}$。 123456789101112131415161718class Solution {public: void rotate(vector<vector<int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); for (int i = 0; i < m; i++) { for (int j = i + 1; j < n; j++) { swap(matrix[i][j], matrix[j][i]); } } ...
Leetcode Hot 100 | 前缀树
思想前缀树,一种多叉树。用来方便地存储字符串,用途包括自动补全等。 题目208. Implement Trie (Prefix Tree)这题让我们实现前缀树,完成插入、查找、查找前缀的方法。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253class Trie {private: struct TreeNode { bool isEnd; TreeNode* children[26]; TreeNode() { isEnd = false; memset(children, 0, sizeof(children)); }; }; TreeNode* root;public: Trie() { root = new TreeNode(); ...
Leetcode Hot 100 | 堆
思想今天看看堆。堆是一种特殊的二叉树,分成最大堆和最小堆。最大堆中,树根是最大的元素;最小堆中,树根是最小的元素。在 C++ 中用堆,可以用优先队列,它的底层是堆实现,同时提供了一些常见的方法,使得我们可以把它当作堆来处理。 当遇到第 k 大,或者反复取最值的题目,或许堆是一个不错的考虑。 题目215. Kth Largest Element in an Array这题让我们找出一个数组中第 k 大的元素。 12345678910111213141516class Solution {public: int findKthLargest(vector<int>& nums, int k) { priority_queue<int, vector<int>, greater<int>> pq; for (int num : nums) { pq.push(num); if (pq.size() > k) {...
