缓存更新的套路
看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。
我不知道为什么这么多人用的都是这个逻辑,当我在微博上发了这个贴以后,我发现好些人给了好多非常复杂和诡异的方案,所以,我想写这篇文章说一下几个缓存更新的Design Pattern(让我们多一些套路吧)。
这里,我们先不讨论更新缓存和更新数据这两个事是一个事务的事,或是会有失败的可能,我们先假设更新数据库和更新缓存都可以成功的情况(我们先把成功的代码逻辑先写对)。
更新缓存的的Design Pattern有四种:Cache aside, Read through, Write through, Write behind caching,我们下面一一来看一下这四种Pattern。
目录
Cache A ...
为什么我不在微信公众号上写文章
很多朋友问我为什么不在微信公众号上写文章。我都没有直接回答,老实说,我也是扭扭捏捏的,才去开了个个人的微信的公众号,而且还只是为了使用微服小程序,和文章的发布通知,我承认现在的阅读都在移动端,而且微信的公众号是国内移动端的文章流量及分享的入口,但是我还是更愿意使用blog这样的方式分享文章,最多也是在blog这边写好文章后,再去微信公众号那边通知一下。这个原因,不是因为我是一个老顽固,有习惯思维,而是,我不觉得微信公众号是一个好的信息传播和交流的平台。
我下面的言论仅仅代表我的个人观点,我不想强加给别人,我只是想说明一下为什么我不把我的blog迁移到微信公众号上。
首先,互联网是开放和共享的,不是封闭的。信息的传播更是需要开放的,大家可以看看互联网之子。
我希望我的文章能够被rss feed到各种阅读器中。
我希望我的文章能有更长的生命周期,长到十几年前的文章都会有人来读。
我希望我的文章可以被搜索引擎所检索到。
我希望我的文章能被别人整理,与其它人的文章放在一起互补并引用。
我希望我的文章能被修改,因为文章会有错误,也会需要时常更新。
然而,微信公众号都不能很好的支持 ...
性能测试应该怎么做?
偶然间看到了阿里中间件Dubbo的性能测试报告,我觉得这份性能测试报告让人觉得做这性能测试的人根本不懂性能测试,我觉得这份报告会把大众带沟里去,所以,想写下这篇文章,做一点科普。
首先,这份测试报告里的主要问题如下:
1)用的全是平均值。老实说,平均值是非常不靠谱的。
2)响应时间没有和吞吐量TPS/QPS挂钩。而只是测试了低速率的情况,这是完全错误的。
3)响应时间和吞吐量没有和成功率挂钩。
目录
为什么平均值不靠谱
为什么响应时间(latency)要和吞吐量(Thoughput)挂钩
为什么响应时间吞吐量和成功率要挂钩
如何严谨地做性能测试
为什么平均值不靠谱
关于平均值为什么不靠谱,我相信大家读新闻的时候经常可以看到,平均工资,平均房价,平均支出,等等这样的字眼,你就知道为什么平均值不靠谱了。(这些都是数学游戏,对于理工科的同学来说,天生应该有免疫力)
软件的性能测试也一样,平均数也是不靠谱的,这里可以参看这篇详细的文章《Why Averages Suck and Percentiles are Great》,我在这 ...
让我们来谈谈分工
昨天,我看到一个新闻——雅虎取消了QA团队,工程师必须自己负责代码质量,并使用持续集成代替QA。 同时,也听到网友说,“听微软做数据库运维的工程师介绍,他们也是把运维工程师和测试工程师取消了,由开发全部完成。每个人都是全栈工程师”。于是,我顺势引用了几年前写过一篇文章《我们需要专职的QA吗?》,并且又鼓吹了一下全栈。当然,一如既往的得到了一些的争议和嘲弄;-)。
有人认为取消QA基本上是公司没钱的象征,这个观点根本不值一驳,属于井底之蛙。有人认为,社会分工是大前提,并批评我说怎么不说把所有的事全干的,把我推向了另外一个极端。另外,你千万不要以为有了分工,QA的工作就保得住了。
就像《乔布斯传》中乔布斯质疑财务制度的时候说的,有时候,很多人都不问为什么,觉得存在的东西都是理所应当的东西。让我们失去了独立思考的机会。分工也是一样。
所以,为了说完整分工这个逻辑。请大家耐住性子,让我就先来谈谈“分工的优缺点”吧。
目录
分工的优点和缺点
全球化下的分工
分工的温床和天敌
什么样分工才是好的
小结
分工的优点和缺点
首先,分 ...
Cuckoo Filter:设计与实现
(感谢网友 @我的上铺叫路遥 投稿)
对于海量数据处理业务,我们通常需要一个索引数据结构,用来帮助查询,快速判断数据记录是否存在,这种数据结构通常又叫过滤器(filter)。考虑这样一个场景,上网的时候需要在浏览器上输入URL,这时浏览器需要去判断这是否一个恶意的网站,它将对本地缓存的成千上万的URL索引进行过滤,如果不存在,就放行,如果(可能)存在,则向远程服务端发起验证请求,并回馈客户端给出警告。
索引的存储又分为有序和无序,前者使用关联式容器,比如B树,后者使用哈希算法。这两类算法各有优劣:比如,关联式容器时间复杂度稳定O(logN),且支持范围查询;又比如哈希算法的查询、增删都比较快O(1),但这是在理想状态下的情形,遇到碰撞严重的情况,哈希算法的时间复杂度会退化到O(n)。因此,选择一个好的哈希算法是很重要的。
时下一个非常流行的哈希索引结构就是bloom filter,它类似于bitmap这样的hashset,所以空间利用率很高。其独特的地方在于它使用多个哈希函数来避免哈希碰撞,如图所示(来源wikipedia),bit数组初始化为全0,插入x时,x ...
Docker基础技术:DeviceMapper
在上一篇介绍AUFS的文章中,大家可以看到,Docker的分层镜像是怎么通过UnionFS这种文件系统做到的,但是,因为Docker首选的AUFS并不在Linux的内核主干里,所以,对于非Ubuntu的Linux分发包,比如CentOS,就无法使用AUFS作为Docker的文件系统了。于是作为第二优先级的DeviceMapper就被拿出来做分层镜像的一个实现。
目录
Device Mapper 简介
Thin Provisioning 简介
Thin Provisioning Snapshot 演示
Docker的DeviceMapper
Device Mapper 行不行?
Device Mapper 简介
DeviceMapper自Linux 2.6被引入成为了Linux最重要的一个技术。它在内核中支持逻辑卷管理的通用设备映射机制,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构,它包含三个重要的对象概念,Mapped Device、Mapping Table、Target device ...
Docker基础技术:AUFS
AUFS是一种Union File System,所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中。UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起,然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)。
AUFS又叫Another UnionFS,后来叫Alternative UnionFS,后来可能觉得不够霸气,叫成Advance UnionFS。是个叫Junjiro Okajima(岡島順治郎)在2006年开发的,AUFS完全重写了早期的UnionFS 1.x,其主要目的是为了可靠性和性能,并且引入了一些新的功能,比如可写分支的负载均衡。AUFS在使用上全兼容UnionFS,而且比之前的UnionFS在稳定性和性能上都要好很多,后来的UnionFS 2.x开始抄AUFS中的功能。但是他居然没有进到Linux主干里,就是因为Linus不让,基本上是因为代码量比较多,而且写得烂(相对于只有3000行的union mount和10000行的UnionFS,以及其它平均下来只有60 ...
Docker基础技术:Linux CGroup
前面,我们介绍了Linux Namespace,但是Namespace解决的问题主要是环境隔离的问题,这只是虚拟化中最最基础的一步,我们还需要解决对计算机资源使用上的隔离。也就是说,虽然你通过Namespace把我Jail到一个特定的环境中去了,但是我在其中的进程使用用CPU、内存、磁盘等这些计算资源其实还是可以随心所欲的。所以,我们希望对进程进行资源利用上的限制或控制。这就是Linux CGroup出来了的原因。
Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。这个项目最早是由Google的工程师在2006年发起(主要是Paul Menage和Rohit Seth),最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器(container)这个名词太过广泛,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。然后,其它开始了他的发展。
Linux CGroupCgroup 可让 ...
Docker基础技术:Linux Namespace(上)
时下最热的技术莫过于Docker了,很多人都觉得Docker是个新技术,其实不然,Docker除了其编程语言用go比较新外,其实它还真不是个新东西,也就是个新瓶装旧酒的东西,所谓的The New “Old Stuff”。Docker和Docker衍生的东西用到了很多很酷的技术,我会用几篇 文章来把这些技术给大家做个介绍,希望通过这些文章大家可以自己打造一个山寨版的docker。
当然,文章的风格一定会尊重时下的“流行”——我们再也没有整块整块的时间去看书去专研,而我们只有看微博微信那样的碎片时间(那怕我们有整块的时间,也被那些在手机上的APP碎片化了)。所以,这些文章的风格必然坚持“马桶风格”(希望简单到占用你拉一泡屎就时间,而且你还不用动脑子,并能学到些东西)
废话少说,我们开始。先从Linux Namespace开始。
目录
简介
clone()系统调用
UTS Namespace
IPC Namespace
PID Namespace
Mount Namespace
Docker的 Mount Nam ...
Docker基础技术:Linux Namespace(下)
在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD、IPC、PID、Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像。在这一篇中,主要想向大家介绍Linux的User和Network的Namespace。
好,下面我们就介绍一下还剩下的这两个Namespace。
目录
User Namespace
Network Namespace
Namespace文件
参考文档
User Namespace
User Namespace主要是用了CLONE_NEWUSER的参数。使用了这个参数后,内部看到的UID和GID已经与外部不同了,默认显示为65534。那是因为容器找不到其真正的UID所以,设置上了最大的UID(其设置定义在/proc/sys/kernel/overflowuid)。
要把容器中的uid和真实系统的uid给映射在一起,需要修改 /proc/<pid>/uid_map 和 /proc/<pid>/gid_map 这两个文件。这 ...
关于移动端的钓鱼式攻击
今天,在微博上看了一篇《微信和淘宝到底是谁封谁》的文章,我觉得文章中逻辑错乱,所以,我发了一篇关于这篇文章逻辑问题的长微博。后面,我被原博主冷嘲热讽了一番,说是什么鸡汤啊,什么我与某某之流的人在一起混淆视听啊,等等。并且也有一些网友找我讨论一下相关的钓鱼式攻击的技术问题。所以,我想写下这篇纯技术文章,因为我对那些商业利益上的东西不关心,所以,只谈技术,这样最简单。
首先说明一下,我个人不是一个安全专家,也不是一个移动开发专家,按道理来说,这篇文章不应该我来写,但是我就试一试,请原谅我的无知,也期待抛砖引玉了,希望安全的同学斧正。
关于钓鱼式攻击,其实是通过一种社会工程学的方式来愚弄用户的攻击式,攻击者通常会模仿一个用户信任的网站来偷取用户的机密信息,比如用户密码或是信用卡。一般来说,攻击者会通过邮件和实时通信工具完成,给被攻击者发送一个高仿的网站,然后让用户看不出来与正统网站的差别,然后收集用户的机密数据。
目录
移动端钓鱼攻击点分析
攻击方式
从一个应用唤起另一个应用的方式
在一个应用内内嵌Web的方式
...
Linus:为何对象引用计数必须是原子的
(感谢网友 @我的上铺叫路遥 投稿)
Linus大神又在rant了!这次的吐槽对象是时下很火热的并行技术(parellism),并直截了当地表示并行计算是浪费所有人时间(“The whole “let’s parallelize” thing is a huge waste of everybody’s time.”)。大致意思是说乱序性能快、提高缓存容量、降功耗。当然笔者不打算正面讨论并行的是是非非(过于宏伟的主题),因为Linus在另一则帖子中举了对象引用计数(reference counting)的例子来说明并行的复杂性。
在Linus回复之前有人指出对象需要锁机制的情况下,引用计数的原子性问题:
Since it is being accessed in a multi-threaded way, via multiple access paths, generally it needs its own mutex — otherwise, reference counting would not be required to be atomic an ...
DHH 谈混合移动应用开发
David,Ruby on Rails 作者,37signals 合伙人
畅销书作家、演说家、赛车手、业余摄影师、顾家好男人
37signals 在2013年2月发布了 Basecamp 的 iPhone app,在此之前我们就使用原生开发(native)还是混合开发(hybrid)做了许多尝试。在2012年项目启动的时候,大多数人都倾向于原生开发。
Facebook 在2012年发布了他们新的 iOS app,为了获得更好的用户体验,他们放弃了原来的 HTML5 混合开发方式。考虑到2010~2011年的时候,HTML 在移动端的性能确实不尽如人意,这个决定在当时看来也在情理之中。2010年的时候我们觉得 iPhone 3G/3GS 够眩够快,但按照现在的标准来看它们就太慢了。因此在为移动应用开发做架构设计时,我们需要考虑新的移动设备的计算能力,而不是那些老的过时的设备。
目录
移动开发架构设计不需要过多考虑设备的性能
第一代产品:原生外壳(native shell)+嵌套WebView
第二代产品:原生外壳+原 ...
HTML6 展望
HTML5 概述
HTML5 是 HTML 语言最受欢迎的版本之一,它支持音频和视频、离线存储、移动端、和标签属性等等。还提供了<article>, <section>, <header>这样的标签来帮助开发者更好地组织页面内容。然而 HTML5 规范仍然没有最后定稿,并且它并不是一个真正意义上的语义标记语言。
HTML6 展望
你有没有曾经希望能在 HTML 中使用自定义标签?比如:使用<logo>来显示你的网站logo,还有使用<toolbar>来显示工具栏等等。我们经常使用<div id=”container”>和<div id=”wrapper”>来组织页面,在 HTML6 里我们希望可以直接使用象<container>和<wrapper>这样的自定义标签。
和 XML 一样,HTML6 应该支持 namespace(命名空间),如:xmlns:xhtml=”http://www.w3.org/1999/xhtml”
HTML6 代码样例:
<!D ...
Google Inbox如何跨平台重用代码?
原文链接《How Google Inbox shares 70% of its code across Android, iOS, and the Web》
开发一个移动应用在当下并不是一件容易的事情。如果想要获得最多的用户,你的应用通常需要覆盖 iOS, Android, 和 Web 三大平台。这就意味着同一个应用需要开发三个版本,使用 Objective-C 或者 Swift 开发 iOS 版本,使用 Java 开发 Android 版本,使用 JavaScript/CSS/HTML5 开发 Web 版本。工作量增大的同时也意味着有更多的 bug 需要修复。
这个问题也是 Google 在开发 Google Inbox 时致力要解决的。在最近发布的这款应用中,Google 使用了一些工具实现了70%的代码跨平台复用。
Google Inbox 覆盖 iOS, Android, Web 三个平台,它们使用的是同一个后台代码逻辑,只是前端的用户体验和平台相关特性的实现有所不同。Google 自主开发了一套辅助工具将 Android 版本的 Java 代码逻辑编译为 Objectiv ...
vfork 挂掉的一个问题
在知乎上,有个人问了这样的一个问题——为什么vfork的子进程里用return,整个程序会挂掉,而且exit()不会?并给出了如下的代码,下面的代码一运行就挂掉了,但如果把子进程的return改成exit(0)就没事。
我受邀后本来不想回答这个问题的,因为这个问题明显就是RTFM的事,后来,发现这个问题放在那里好长时间,而挂在下面的几个答案又跑偏得比较严重,我觉得可能有些朋友看到那样的答案会被误导,所以就上去回答了一下这个问题。
下面我把问题和我的回答发布在这里,也供更多的人查看。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
int var;
var = 88;
if ((pid = vfork()) < 0) {
printf("vfork error");
exit(-1);
} else if (pid == 0) { /* 子进程 */
var++; ...
Leetcode 编程训练
Leetcode这个网站上的题都是一些经典的公司用来面试应聘者的面试题,很多人通过刷这些题来应聘一些喜欢面试算法的公司,比如:Google、微软、Facebook、Amazon之类的这些公司,基本上是应试教育的功利主义。
我做这些题目的不是为了要去应聘这些公司,而是为了锻炼一下自己的算法和编程能力。因为我开始工作的时候基本没有这样的训练算法和编程的网站,除了大学里的“算法和数据结构”里的好些最基础最基础的知识,基本上没有什么训练。所以,当我看到有人在做这些题的时候,我也蠢蠢欲动地想去刷一下。
于是,我花了3-4个月的业余时间,我把Leetcode的154道题全部做完了。(这也是最近我没有太多的时间来写博客的原因,你可以看到我之前做的那个活动中有几个算法题来自于Leetcode)有人说我时间太多了,这里声明一下,我基本上都是利用了晚上10点以后的时间来做这些题的。
LeetCode的题大致分成两类:
1)基础算法的知识。这些题里面有大量的算法题,解这些题都是有套路的,不是用递归(深度优先DFS,广度优先BFS),就是要用动态规划(Dynamic Programming),或是拆半查找( ...
State Threads 回调终结者
(感谢网友 @我的上铺叫路遥 投稿)
上回写了篇《一个“蝇量级”C语言协程库》,推荐了一下Protothreads,通过coroutine模拟了用户级别的multi-threading模型,虽然本身足够“轻”,杜绝了系统开销,但这个库本身应用场合主要是内存限制的嵌入式领域,提供原生态组件太少,使用限制太多,比如依赖其它调用产生阻塞等。
这回又替大家在开源界淘了个宝,推荐一个轻量级网络应用框架State Threads(以下简称ST),总共也就3000行C代码,跟Protothreads不同在于ST针对的就是高性能可扩展服务器领域(值得一提的是Protothreads官网参考链接上第一条就是ST的官网)。在其FAQ页面上一句引用”Perfection is achieved not when there is nothing more to add, but rather when there is nothing more to take away.”可以视为开发人员对ST源码质量的自信。
目录
历史渊源
基于事件驱动状态机(E ...
bash代码注入的安全漏洞
很多人或许对上半年发生的安全问题“心脏流血”(Heartbleed Bug)事件记忆颇深,这两天,又出现了另外一个“毁灭级”的漏洞——Bash软件安全漏洞。这个漏洞由法国GNU/Linux爱好者Stéphane Chazelas所发现。随后,美国电脑紧急应变中心(US-CERT)、红帽以及多家从事安全的公司于周三(北京时间9月24日)发出警告。 关于这个安全漏洞的细节可参看美国政府计算安全的这两个漏洞披露:CVE-2014-6271 和 CVE-2014-7169。
这个漏洞其实是非常经典的“注入式攻击”,也就是可以向 bash注入一段命令,从bash1.14 到4.3都存在这样的漏洞。我们先来看一下这个安全问题的症状。
目录
Shellshock (CVE-2014-6271)
AfterShock – CVE-2014-7169 (又叫Incomplete fix to Shellshock)
原理和技术细节
bash的环境变量
bash的函数
bash的bug
...
互联网之子 – Aaron Swartz
1986年11月8日,有个叫Aaron Swartz的人在美国芝加哥伊利诺伊州出生。因为他父母创办了一个软件公司,所以,Aaron在3岁的时候就接触到了电脑,然后就着迷了。
我们先通过Aaron Swartz 的青少年时期来看一下他是怎么样的一个天才:
12岁的时候Aaron就创建了一个类似于Wikipedia式的网站(那时还没有Wikipedia),13岁的时候,Aaron赢得为年轻人而设,创作教育及协同非商业网站的ArsDigita Prize比赛首名。 奖品包括参观麻省理工学院及与网际网路界的知名人士见会。
14岁的时候,他就成为了RSS1.0的开发组的一员。(后来,他和 John Gruber一起开发了Markdown)
15岁的时候,进入W3C的 RDF 核心工作组,并写了RFC3870——这个文档描述了一个新的media type – “RDF/XML“,用于定义互联网上的“语义网络”
17岁进入斯坦福大学,1年半后,18岁的时候因为受不了教条式的教育缀学,并通过Y Combinator公司的夏季创办人计划成立Infogami软件公司,在那 ...