Simplicity is prerequisite for reliability

做分布式系统的人都知道大名鼎鼎的 CAP 定理,这个定理仿佛一个巨大的枷锁,套在了每一个分布式系统的开发者身上。前些日子我实现了一个 AP 的分布式系统,也就是说发生网络分区(P)的时候,系统会自动分裂成两部分各自独立工作,而不是像 ZooKeeper 或者 etcd 这种 CP 系统在网络分区之后少数派降级不工作。

为了验证系统在网络分区时的行为是否符合预期,我需要做个故障模拟,在本地搭建一个 Linux 集群,然后用 iptables 丢弃指定来源的包人工制造出网络分区的效果。

Read More...

前些日子我对 Grav Admin 的访问速度感到很不满意,经常打开 Dashboard 页面就给我来个 504 Gateway Timeout,不得不再刷新一次才能正常访问;甚至有一次我在编辑页面写了一大段文字之后,保存失败导致内容丢失,后来尝试再写也没法补全丢失的内容。这份不愉快让我萌生了寻找一个更厉害的博客引擎的念头。

但是基本上 Grav 已经是 2016 年最棒的开源 CMS 了,也就是说综合各个方面因素,没有什么比它更好的 CMS 可供选择。失望之余不免产生想要亲自动手造一个轮子,但是考虑到我已经废弃了原本就不怎么突出的前端能力,如今的我已经对实现一个靠谱的博客后台力不从心,这些冲动最终也只是想想而已。

Read More...

许久之前我分享了一个在 Hexo 博客中制作照片流的方法,至今这个照片流已经成为了我的博客中更新最频繁的页面,承载着我对那些曾经浪费我生命的美好事物的回忆,一开始是书籍和动漫、电影等影视作品,如今还多了个游戏,毕竟游戏继电影之后,也被归为艺术之列,号称「第九艺术」。

我对照片流这个功能是如此的喜爱,以至于我将博客从 Hexo 迁移到 Grav 之后,之前为 Hexo 开发的几个插件都被我放弃了,唯一一个被窝移植到 Grav 上的,就是照片流。当然也有一部分原因是移植照片流的工作十分简单,以至于我只需要借助 Twig 模板的宏定义功能就能轻松搞定。

Read More...

要说 2016 年我在技术上的最大的收获,当属心态发生了转变。在此之前,我在技术上没有一个明确钻研方向,为了解决问题嘛,碰到什么问题就搞定什么问题,一时半会搞不定就绕过去,也能获得很好的结果。到头来却是,我成了一个「全栈」工程师,不知道我真实水平的人以为我能力很好,什么烫手山芋交给我都能得到超出预期的好结果。我自己却感觉到彷徨和困惑:几年之后,人们提起我的时候,想到的是一个干活很靠谱的全栈,还是一个别的什么?

Read More...

最近几周一直在魔改一个重要的生产系统,给这个系统加上了一个嵌入式的关系数据库,在内存中缓存一些结构化的数据,使得应用在和数据库之间发生网络隔离的时候也能做一些关键操作。既然是缓存就会涉及到缓存失效、同步、一致性等一系列问题,好在我可以充分利用业务特性来实现最终一致性,但是还是在数据同步上遇到了一个有趣的问题:如何将数据库中有记录被删除这件事情通知到应用,使得缓存中的相关记录也被删除?

Read More...

网易又双叒叕打造了一款厉害的游戏,我自然也不能免俗下载体验了一番这款名为「阴阳师」的「国民手游」,并首次在其中体验了网游氪金的快感。

前些日子我知道这个游戏,但是由于我一直没有玩网游的习惯和精力,也就一直没有想过要体验一番。后来认识的一些朋友开始在社交网络上各种晒姑获鸟,各种吸欧气,看得我心中长草。因为不知道「吸欧气」是什么鬼,我还专门学习了一个提高了姿势水平,还学到了「玄不救非,氪不改命」这句箴言。学习完之后就开始玩阴阳师了,毕竟也想看看自己到底是欧洲人还是非洲人。

Read More...

前些日子欧气爆发,在高可用架构的微博抽奖活动中得到一张 GIAC 的门票,然后我申请了出差,千里迢迢赶赴京师。去年夏天有幸去北京围观 Velocity,姿势水平提高不少,本次 GIAC 请到了多位业界知名的技术大拿,也有不少和我接下来要做的工作相关的主题分享,这些更是提升了我对本次行程的期待。

确定赴京行程后便是约饭,从朋友处得知之另一个朋友拿到了 Google 的 offer,也是个值得庆祝一番的事情。

Read More...

上一篇博文「魔改 pip 的快乐与痛苦」中,我提到魔改开源代码,一个需要时刻考虑的事情,就是如何方便地合并上游变更。为了合并上游变更,我们要尽量克制自己乱写代码的冲动,不要作出那些使得合并代码变得困难重重的事情,比如像我曾经干出的修改包目录的蠢事。

为了修正我犯下的错,我决定在 mpip 代码仓库中保持基本 pip 一样的包目录,改换包目录这种事情放到编译过程里做。于是我不仅要在编译过程里把代码复制一份,还得把包目录从 pip 移动到 mpip,然后把代码里各种和 pip 相关的包目录、文件路径、常量定义、环境变量,总之一切有可能让 pip 和 mpip 之间不清不楚互相干扰的,都得改干净,这样才能让 mpip 和 pip 和平共处。

Read More...

半年前我做了一个 side project,把 pip 魔改一番,使得我能够将 Maven 的 Nexus 仓库作为 pip 的后端仓库。于是原本通过 pip install xxx==version 命令,我们可以从 https://pypi.python.org/simple/ 把指定版本的包下载下来然后安装,我可以用 mpip install xxx==version 从公司内网的 Nexus 仓库下载包然后安装。

之所以做这么个工具,是因为公司没有提供一个内部的 pypi 服务器。Python 不是公司的主流语言,公司自然不会投人力物力去维护这么一个服务,如果由我所在团队自行维护,又得付出额外的人力物力,并不是十分划算。于是我们之前的做法是将系统依赖的三方包,不管是 whl 还是 tgz,直接放在代码目录里,然后在生成部署包的时候再复制、安装。

Read More...

很长一段时间里,我一直以为,对于同一个时间格式,我们把一个时间对象序列化成字符串之后,还能反序列化成和原对象表达同一个时间的时间对象,至少在不考虑时区之类的问题时,这个命题应该成立。

$$ \forall F \in DateFormat, F(D)=S \rightarrow F^{-1}(S)=D $$

然而就在这两天,我遇到了一个打破上述认知的奇怪问题,Date 对象格式化之后再解析回来,就完全乱套了。

Read More...