Planet of Woodpecker.org.cn for CPUG

August 14, 2017

@khsing

Nginx 的流量镜像模块

Nginx 发布了1.13.4版本,并且包含了一个流量镜像的模块 ngx_http_mirror_module

这对于线上系统就很好了,比如可以镜像部分流量来做测试、debug之类的

例子也很简单:

location / {
    mirror /mirror;
    proxy_pass http://backend;
}

location /mirror {
    internal;
    proxy_pass http://test_backend$request_uri;
}

by khsing at August 14, 2017 07:01 AM

August 13, 2017

@khsing

软件的收费模式

Ulysses 发了一篇blog: Ulysses Switches to Subscription 就唰喇喇的把自己的售卖模式从卖 License 换到了卖时间了。

曾几何时,还在指责 Mac App Store 不支持升级的收费策略的时候,这些应用开发商却把自己的收费模式先换成了订阅。我承认软件开发商在卖 License 的模式下面临着很多的生存困境,比如一个 App 很好,但是为了持续的获得收入只能走两条路:

  1. 发展新客户,每年都把东西卖给陌生人,这个过程其实是挺难的。
  2. 向老客户收钱,每年总有那么几个改版本号骗钱的App奸商,比如臭名昭著的Parallels Desktop。

开发商能怎么办,也很无奈啊,程序员嗷嗷待哺,不弄点钱,新版本怎么开发,总不能卸了磨就杀驴吧。所以这模式得改,要说这改的快的还是几个大厂,以Adobe为首的先把自己的 Creative 套件给转到订阅了,Microsoft把也提供了365的订阅模式,订阅模式确实对厂商来说是非常的好,收入有了保障,日子也可以过的有滋味了。

用户当然是希望App能稳定的好好工作,别罢工,积极解决遇到的问题,持续更新。最讨厌的就是付费更新,最最讨厌的就是不付费更新在新版OS里就不能好好工作的那种,比如Parallels Desktop。

用户付费买的是什么?是软件的使用权还是有效时间的使用权?

如果是一个有效时间的使用权,应该适用于专业用户,专业用户能够频繁的使用这个软件,这样你才能对得起你的服务和售价。普通用户买来就不合算了,比如工具软件,普通用户一年也就用上几次,只是希望安安静静的工作就行了,所以普通用户修图片应该买 Pixelmator 而不是 Photoshop。

如果是使用权,那就是一个稳定的OS版本下,可以一直使用这个软件,比如我10年前买一个软件,只要我的操作系统没有换,其他环境没有换,这个版本就应该可以一直使用下去。

有些软件的某个版本写的太好了,以至于新版本没有什么吸引力让我去升级,比如我常用的那个Dash 和 Alfred,Dash 4 和 Alfred 3都出来很久了,提醒更新也很久了,但是他们现在的这个版本太好了以至于我完全没有什么动力去升级,厂商当然就挣不到钱喽(心疼1s),所以从某种程度上也可以理解 TextMator 和 Sublime Text 为啥后来更新乏力了,该买的早就买了,不买的也不会再买了。

所以说产品定位很重要,针对专业用户的尽管走订阅模式,因为用你的工具用户能挣回来更多的钱。如果你只是一个针对普通用户的工具,还是卖License吧,以量取胜,增加边际收益,而且工具不是你的长期事业,能分化出专业用户还是得走订阅模式来稳定收益,更长期服务下去。

当然订阅模式也存在 @bfishadow 说的那个问题,即便你一年啥事儿都不干,还是得给你付费才能使用,这确实是很操蛋的事情了,所以我觉的 Sketch 的订阅模式很好,好的是他订阅的是你升级的权利,并不是使用的权利,所以你的订阅过期了,软件依然可以使用,只是不能升级到最新版了而已,所以我之前使用的日记软件Day One是不会升级到新版去的。

by khsing at August 13, 2017 08:56 AM

August 12, 2017

@khsing

体验是优化出来的

从直觉上都认为 Apple Pay 的支付体验是优于微信支付的,直到头几天 Apple Pay 和银联一起搞了一个5折之类的促销活动,刺激了很多人去用 Apple Pay,包括星巴克,7-11。从集中的使用了一段时间来看,Apple Pay在国内的体验是不敌微信支付的。

主要就从速度来说,Apple Pay的支付速度远不及微信支付,举一个我在7-11的例子吧:

  • Apple Pay: 排队 -> 告诉店员使用Apple Pay -> 店员拿起 POS 机设置金额 -> 贴上去支付 -> 完成
  • 微信支付:排队 -> 准备好支付界面-> 告诉店员使用微信支付 -> 直接贴在扫码机上面 -> 完成

所谓的需要打开App再支付的步骤,排队的时候就干完了,而且就现在情况来说,打开个App和掏个手机基本不差。

从技术方案上,从安全性来说Apple Pay都要比微信支付好,但是从部署难以程度,从体验的优化上,微信支付已经在国内大幅的超越了Apple Pay,下一步 iPhone 的 NFC 接口开放之后会不会对微信支付的体验上带来优势呢?也许结合小程序和RDIF在零售领域玩出新花样也不好说。

项目 微信支付 Apple Pay
绑定银行卡 需要 需要
需要POS机 不需要 需要
POS操作难易 易(甚至不需要)
需要网络 不需要 不需要
店员培训
适用范围 iPhone 5S + 有摄像头的手机

可见这部署成本以及市场教育的结果,再加上市场优化的结果,微信支付的体验某种程度上也来自于这些服务于商铺的服务商的优化。

by khsing at August 12, 2017 09:07 AM

June 06, 2017

@khsing

十条无我编程的戒律

下面是译自Jeff Atwood的The Ten Commandments of Egoless Programming

========我是华丽的分割线========

这十条无我编程的戒律,源自Jerry Weinberg的《程序开发心理学》一书。

  1. 理解并接受你所犯的错。这是说尽早的在产品发布之前发现这些错误。幸好我们不是在JPL(隶属NASA的喷气推进实验室)开发火箭制导软件的一小撮人,在我们的行业中很难出现致命错误,所以我们可以也必须从错误中学习、开怀并且继续前行。
  2. 你并不等于你的代码。记住审查的目的是为了找到问题,而且问题一定会被找到。不要为一个没有发现的问题而自责。
  3. 你知道多少不重要,总有人知道的比你多。如果你问一个人他总能告诉你一些新鲜的玩意。寻找并且从其他人那里接受输入,尤其是你觉的你不需要的时候。
  4. 没有商讨就不要重写代码。在修复代码和重写代码之间总有一条不错的界线,知晓其中的不同,并在代码审查的框架中追查文法上的变化,而不是孤僻的强迫症。
  5. 用耐心和尊敬善待那些知道的比你少的人。非技术人员在和开发打交道时普遍持有偏见,好一些情况下认为我们是一群自负的怪人,坏一些的情况下认为我们是一群玻璃心。不要用愤怒和不耐烦加深这种偏见。
  6. 在这个世界上持续存在的只有变化。用微笑和开放的心态去接受变化。把每一个需求、平台或是工具上的变化视作新的挑战,而不是严重的不利因素去抵触。
  7. 真正的权威来自于知识,并不是职位。知识带来权威,权威带来尊敬,所以你如果想要在一个自大的环境中受尊敬,增加知识吧。
  8. 为你的信仰而战,但也要勇于承担。要知道有时候你的想法会被批驳。即便最终你是对的,也不要报复或者说“我早就说了”这样的话,也不要作出一副为你的想法惋惜或者哭诉的模样。
  9. 不要成为屋子里的人。不要成为长期处在阴暗角落且打水的时候才出现的码农,屋子里的人与世隔绝、淡出人们视线、失控且在开放协作的环境中无立锥之地。
  10. 批评代码而不是批评人——善待码农,而不是代码。尽可能的让你的评论都是积极的而且目的是促进代码质量。评论要和标准,编程规范,优化性能等内容相关。

软件的人性化的准则真是不过时的。这本《程序开发心理学》成书于1971年,而一年后我才出生。

========我是华丽的分割线========

Guixing 翻译于 2017-06-06

by khsing at June 06, 2017 07:40 AM

June 01, 2017

@khsing

黑客帝国的Neo和围棋世界的柯洁

黑客帝国(The Matrix, 1999)一直是我非常喜欢的一部科幻片,其中世界设定值得深思,不时的就会质疑自己是不是一块电池。Neo作为电影的主角有洞悉虚拟世界的能力,也被称之为救世主,在电影的3部曲结束之后,Neo战败,Matrix清除了Agent Smith,达成了人类和机器的和平。

自从 AlphaGo 去年4/5大败李世石之后,人类的围棋世界其实就已经崩塌了,无法战胜 AlphaGo 已经是必然。 今年柯洁和 AlphaGo 的对决以3:0落败,也成了 AlphaGo 的收官之作,从此退役,独孤求败。而柯洁也和 Deepmind 达成共同研究 AlphaGo,让其辅助人类研究围棋。

Neo和柯洁某种程度上何其相似,在 Matrix 即将摧毁人类最后的据点 Zion 之时,Matrix 打败了 Neo,获取了 Agent 的代码,完善了自己。柯洁最后大败给 AlphaGo,但柯洁也开始帮助 AlphaGo 进一步完善。

AI的一直是科幻界的主题,那部以人工智能(2001)命名的电影,人工智能把自己都给骗了,David努力在寻找自己不是人造的(Artificial)的证据,并且一直在寻找变成真正小孩的方法,最后发现自己并没有唯一性也不能变成真小孩,但是奇幻的一点也是他还是有唯一性,所以人工智能从情感上已经无法分辨了。

人类发明AI是科技发展的必然,机器仿生技术的进步必然会促进生活水平的提高。现在很多人还在纠结同性恋,变性人,out了,下一步该怀疑一下和你恋爱的是不是一个AI了。(这个题材也有了,《她》(2013),[捂脸])

AI和机器人的发展,一方面会让财富快速的向掌握AI和机器的人聚拢,另一方面人类会成为机器豢养的宠物。

by khsing at June 01, 2017 01:56 AM

May 09, 2017

@khsing

我所依赖的科技公司

使用了很多科技产品,如果这家公司和他们的产品突然消失,也许生活会很不方便,那么究竟有哪些是我生活中不可或缺的公司和产品呢?

  1. Apple,苹果公司的产品应该是我几乎无法替代的,他家的软件服务产品都不值一提,唯独iPhone和Mac是我工作生活不可缺少的,让我替换起来成本很高。
  2. Google,搜索产品基本是最最最不能缺少的东西了,缺了他我都不会上网了,Gmail和Contact都还可以替换,至于Chrome我只是开发的时候会用。
  3. 淘宝,万能的淘宝,基本上没有买不到的东西和服务,合法的哈。

上面这些是基本需求了,作为一个码农,下面两个服务也是不能缺少的

  1. Github,太多的开源项目在上面了。
  2. StackOverflow,离了他我都不会写代码了。

以上满足了基本需求。

by khsing at May 09, 2017 05:37 AM

April 26, 2017

@khsing

Uber被苹果请喝茶

这两天还发生了一件事,Uber CEO Travis Kalanick被Apple CEO Tim Cook叫去喝了茶,主要是Uber在代码中嵌入了追踪用户手机的指纹技术,甚至用户清理手机之后,也一样可以追踪的到,而且设置了地理围栏(Geofence)来躲避苹果的审核人员。

这事儿挺有意思的,对用户做标记是广告和推荐系统中必须要做的一件事,从最早iOS可以在App中直接读取Mac地址到后来这个接口变成私有API,以及苹果提供了iAd的一套标记用户方法,等等这些都是为了知道屏幕背后的那条狗。从这个角度来说Uber做的这个技术其实是很通用的,只要是做广告和推荐的都这么干。不同之处应该是Uber调用了私有API,从而可以永久标记一个用户,如果只是使用了iAd的标记,用户可以在iOS设置->通用->隐私->广告中重置。

司如其人,Uber的CEO按常理来说就是一个混蛋,只要没有被抓到,什么事情都可以干的出来。

by khsing at April 26, 2017 03:11 AM

Apple Pay、内购(IAP)和微信支付的体验

昨天说到应用内购买和微信支付体验问题,早上开车想了一下,Apple Pay,IAP和微信支付还真不是一码事,而且还各有各的特点。

先说IAP,应该说这是这三个产品中最早的一个,应用内购买是苹果在2009年推出的。解决应用内虚拟物品的购买,消费通过App Store绑定的信用卡、借记卡、或者余额来购买。便捷性上呢,在没有Touch ID之前,需要输入一次Apple ID用户名和密码进行消费,现在内购基本上就是弹出一个确认购买,TouchID,购买成功或者失败。

其次是微信支付,是微信提供的一套支付体系。微信借着滴滴打车和红包砍下了国内移动支付1/3以上的市场份额,生生把二维码支付和抢红包发展成了全国民运动。分场景来说,在微信内的支付很方便,无论是打赏还是微商城一类的支付都是很方便的,但是在其他App中使用微信支付是需要跳转到微信支付完成之后再跳转回去,这个过程就不是那么的原生和自然,但是依然是很不错的体验。

最后是Apple Pay,在国外开展的算是顺利,但是在国内却几乎是一败涂地,被二维码打的可以说是连牙都没找到。除去Apple Pay的POS机部署成本、国人信用卡持卡率等问题不说,仅教育用户这一项,Apple比微信和支付宝来说基本就是没有投入,只有在升级完之后的一个添加银行卡的引导过程,这是远远不够的,中国的移动支付市场是腾讯和阿里两家用补贴和红包砸出来的。就支付体验来说,分线上和线下两个场景来说,Apple Pay的体验都是很不错的,线上来说,无需跳转到另外的App,Touch ID就直接支付,很轻松,线下就更不用说了,轻触一下就完成了。但是,凡事总是有但是,Apple Pay在国内使用的时候,店员不知道、不会操作、设备不支持等等的问题比起微信二维码来说,那就是复杂太多了,店员不耐烦的时候甚至会说:你还是微信支付宝吧。

这时候再来看用户体验的问题,Apple Pay和微信支付的场景都基本上是支付,而IAP还有不同的地方在于支付完成后还要记录用户的支付记录,有些App的功能开启还需要恢复购买这样的功能,所以从功能上来说IAP的业务逻辑要复杂于Apple Pay和微信支付,这也造成了IAP用户体验差,尤其国内还有长城的存在,IAP的接口都在国外,这中间的网络通信就导致IAP支付过程很慢,甚至会失败。Apple Pay的体验优于IAP主要是无须网络连接照样完成支付,逻辑简单。

微信支付的体验好于IAP的主要原因是访问的服务都在国内,如果是店家扫描二维码支付甚至无须客户手机联网,这一点和Apple Pay是同等级的,只是没有Apple Pay那种系统级别行云流水般的顺滑而已。

所以,要微信把赞赏切换到IAP的话,是有一些损伤体验的,但是切换到Apple Pay的话,应该不存在体验损伤的问题,只看用户是不是使用了Apple Pay,这个大前提就喝退了很多人。

by khsing at April 26, 2017 03:10 AM

April 24, 2017

@khsing

微信和苹果的一次交锋

已经好几天的热点了,苹果从结果上逼微信干掉了iOS版文章打赏功能,理由是违反了苹果的App准入规定3.1.1的条款,即解锁程序内功能时必须使用IAP(内购),苹果举了个例子是:订阅,游戏货币,游戏等级,访问高级内容,或者解锁完全版本等,而且不可以引导用户跳过IAP使用其它支付。

先下结论,这次事件从目前的结果来看,微信的付费阅读产品可能会延期,至少会在iOS端会缺席。

再来想想这次事件的几个问题:

首先,微信的打赏究竟在不在苹果的这个规定范围内?

打赏虽然没有解锁一个新的功能,但是实际上这本身就是一个新的功能,我认为归类到订阅、访问高级内容这样的服务中也合乎情理。

其次,苹果的这个规定合理么?

根据我的地盘我做主的原则,这事儿其实也没的说,就腾讯来说他自己也干过很多我的地盘我做主的事情,比如干掉淘宝(虽然是淘宝先动手的),干掉优步,可以说微信也是乏善可陈。

最后,这些决定对用户的影响是什么?

苹果是敦促微信回到他的规则上来,乖乖的交虚拟产品的苹果税,微信的做法是用二维码代替按钮(之后也被要求撤下),耍了小聪明,猜测6小时后下线二维码也是在苹果的勒令之下撤下了二维码。其实,微信完全可以继续保留功能,打赏走IAP。但是我也听说,这是为了保持微信支付的优秀体验,好吧,微信的支付体验比Apple Pay要好?

要知道现在的做法是有损公众号的内容提供者的,也就是说微信为了自己的产品体验,强行损害了自媒体的利益,腾讯,干的真是漂亮!

微信的公众号域名是http://mp.weixin.qq.com,一直有对这个mp缩写的猜测,我倾向于这是Media Platform的缩写,媒体平台。如果你是一个内容创业者,或者是一个收入依赖于微信的媒体运营者,长点心吧,这次的事情已经说明,你们的利益是被腾讯这个平台裹挟的,是他可以作为筹码和其他公司打架的武器。

在拥抱微信获取流量的同时也要把灵魂交给撒旦!

再来说Apple的规则是不是真的就那么的神圣?

其实今天微信遇到的问题,不是微信一家遇到的问题,而是所有进入App Store平台的App一起面临的问题,比如Kindle作为一个电子书应用,不能在iOS版App内买书,为啥呢?因为这是虚拟产品,要交30%的苹果税,图书利润很薄还要和作者分成,除非iOS版购买比其他版本购买多30%,但是这个逻辑是不是很诡异呢?打开微博、爱奇艺要续费一个会员,也必须走IAP,为什么呢?因为3.1.1条款。这确确实实是一条霸王条款!

既然这个问题是行业内一样面临的问题,苹果有没有可能去改善?答案是可能会有改善。君不见喊了一万年的App支付订阅模式在去年就有所改进,很多的App也跟进了,比如我常用的Podcasting应用Overcast就在苹果支持订阅模式之后就推出了订阅付费的模式。

苹果占据了移动市场食物链顶端,而且目前的地位别人还无法撼动,所以他的规矩就是规矩,想要Apple作出改变,要么告他,要么退出App Store市场。很多Mac上的App就因为不满App Store的分成和苹果的霸道退出了App Store,比如Sketch, Sip等应用,但是Mac端好歹还是有其他途径安装App的,而iOS安装App的合法路径只有一条————App Store。

强大就封闭,弱小就开放。这就是一个很现实的生存环境,没有什么道义可言,只有商业利益赤裸裸的摆在这里。

至于苹果是不是惧怕微信的小程序而故意修理呢?也许有吧,但是小程序真的就能取代App么?

by khsing at April 24, 2017 12:04 PM

April 21, 2017

@khsing

2016款Macbook Pro的分辨率

入手2016款Macbook Pro有一小段时间了,一个小的细节是显示器的默认分辨率从1440×900变成了1680×1050,但是显示屏的物理分辨率还是2880×1800,而且那里也不现实Best for Retina了,但是这样的改变让屏幕可显示区域变大了,鸡贼了苹果。

对于一个轻度OCD患者来说,这太不科学了,改回来,必须是Best for Retina.

by khsing at April 21, 2017 02:26 AM

April 20, 2017

@khsing

升级Homebrew中的PostgreSQL

最后还是入手了新版的MBP,开发环境都是重新设置的,用PostgreSQL的时候,启动提醒版本不兼容

FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 9.5, which is not compatible with this version 9.6.2.

所以要升级一下原来的库,作弊条开始

  • brew services stop postgresql
  • brew install postgresql@9.5
  • initdb /usr/local/var/postgres9.6 -E utf8
  • 开始升级数据库
pg_upgrade \
  -d /usr/local/var/postgres \
  -D /usr/local/var/postgres9.6 \
  -b /usr/local/Cellar/postgresql@9.5/9.5.6/bin \
  -B /usr/local/Cellar/postgresql/9.6.2/bin/ \
  -v
  • mv /usr/local/var/postgres /usr/local/var/postgres9.5
  • mv /usr/local/var/postgres9.6 /usr/local/var/postgres
  • brew services start postgresql

完成

by khsing at April 20, 2017 04:13 AM

云服务和数据自由

最近发生了一个事情,我之前为了方便就把一些流程图都放在了ProcessOn的云服务上,我很容易的能把这个内容发给朋友,而且也可以邀请朋友同事一起来改,但是在我想导出一个思维导图的时候,发现只能导出成图片、私有的pos文件或者pdf,这个时候我就是很懵逼的情况。按理说,这个数据是我的,我应该有数据迁移的自由。

数据自由交换是一种权利,比如我记录的笔记之类的内容,这是我的创作内容,应该可以很容易的导出成一个容易迁移的格式,说的就是Evernote和OneNote。大概从2年前开始,我买了Office 365服务,理所应当的被送了一些空间,OneNote正好可以使用这些空间,我就打算把之前使用Evernote的内容都前一过来,但是当我发现OneNote只能一个Note一个Note的导出成PDF的时候,我彻底的放弃了这个产品,就更不要提他经常不知所以的同步状态,继续乖乖的付费使用Evernote。

从这些云服务的情况来看,我对他们的担心主要是三个问题

  1. 数据的属主问题。在云服务不能提供良好的数据导出时,这个数据并不能完全意义上属于我。
  2. 数据的交换问题。以文档类数据为例,ProcessOn 没有提供导出Mindmap为Freemind等其他软件格式就是一个数据不能自由交换的例子,这和1意义上相同。
  3. 服务的持续性问题。如果不在1,2的问题,那么第三个问题就是很严重的问题,作为一个云服务公司,如果数据既不能自由导出流转,那服务的期限最好就是永久,否则就是数据的丢失就是不可避免的了。

我并不排斥使用云服务,而且我司也是做云服务的,只是我觉的一些通用的产品数据应该被自由流通和编辑。举几个例子:

  • 文档,应该可以导出成为txt, rtf, word格式
  • 表格,应该可以导出成为csv, excel格式
  • 思维导图,应该可以导出成为,freemind, xmind, mindmanager格式

数据才是正真的自己拥有。

by khsing at April 20, 2017 04:01 AM

March 28, 2017

@khsing

思考和书写

人活着除了生理上的存活状态,最主要的还是思考在继续。我们看见周围的事和物都会去思考一系列的问题,比如:这是什么?为什么会发生?等等。

互联网的出现极大的拓展了我们获取知识的能力和范围,而移动互联网的出现则彻底的把我们的时间变的碎片化。在大量碎片信息的冲刷之下,我们的独立思考变的弥足珍贵。

现实生活和工作中面临的问题有小有大,大部分的问题凭着我们的经验和直觉就解决了。而有些问题是值得仔细思考的,甚至是需要长时间的理性思考的。这似乎与我们现在的移动互联网生活是冲突的,刷微博和朋友圈,接收着大量的碎片化信息,是无法完成深度思考的。有些时候我们的直觉会欺骗我们,看到一件事或物,经过简单的分析和思考就认为这件事情掌握了,了解了,然而这只是一个假象。在时间碎片化的今天,这一情况更为普遍。

一个接受和没接受教育的人的最本质的能力区别是阅读和写作,阅读是一种输入技能,经过思考之后书写出来就是输出了。这一点很像写了一个数据处理函数。

思考和写出来是有很大区别的,一个你觉的已经思考过的内容,要写出来的时候就变成了梳理的过程,这时候就会发现自己在脑海中浅思考的错误,所以写出来的内容往往比自己想的内容更加缜密。

如果一件事,经历之后,再经过思考梳理,形成文字材料才是真的消化,想通透了。所以技术人员要多思考,多实践,多分享。

by khsing at March 28, 2017 10:26 AM

March 12, 2017

@khsing

写给SaaS创业公司的安全基础知识

头两天看到了写给SaaS创业公司的安全101,内容涵盖了不少,非常值得一读,其实不光是给SaaS企业了,其他公司一样适用。

我摘了几个贴在这里

  • 密码共享和密码管理,所有系统都有一个终极的Admin账户,这个账户是共享的,防止这个人的单点故障,同时一旦共享了,那么密码是需要加密共享的,所以要有密码管理。
  • 全盘加密,Mac/Windows都有很好的加密方法了,几乎一键加密。
  • 买3个以上域名,第一个用于公开的品牌和企业的邮箱。第二个用于自己的SaaS服务,比如googleapis.com之类的。第三个域名用于内部的后勤支持,比如公司vpn等基础设施等等,而且这个域名最好匿名,这样别人就难以猜测了。营销邮件应该使用独立的域名,以防反垃圾系统标记后影响公司业务邮件来往。
  • 所有地方都使用HTTPS
  • API密钥,每一个客户都应该拥有不同的API钥匙对。
  • 物理安全:
    • 使用屏保,并且从屏保恢复需要输入密码。
    • 不要使用U盘,这是入侵的最方便最直接的方法了。
  • 企业内部沟通用Slack,客户间沟通用邮件,国内可以适用企业内部用BearyChat,客户沟通用邮件+微信。
  • 认证服务支持SSO和OAuth
  • 备份
    • 冷备/热备/异地容灾
    • 自动化备份
    • 定期恢复演练
    • 备份加密
  • 防火墙和访问权限
    • 服务访问需要认证,比如ElasticSearch, MongoDB, MySQL等
    • Review防火墙设置,只能允许必要的服务和端口开放。
    • 自动扫描。

可以照这个列一个checklist,看看自己公司都做到了哪些?

by khsing at March 12, 2017 05:12 AM

you-get下载视频

网络资源虽然很方便了,但是我依然喜欢把东西下载下来,尤其是喜欢的YouTube视频,因为版权等一系列的原因,这些东西在互联网可能只是短暂的停留。

you-get简直是一个神器,下载视频刚刚的。而且可以制定下载格式,连字幕都下载好了。比如指定下载mp4格式

you-get --itag=18 https://www.youtube.com/watch?v=ud4qy1EHRKQ

by khsing at March 12, 2017 03:43 AM

March 02, 2017

@khsing

消除Outlook的安装后反复欢迎提醒和Update无法更新的问题

Outlook for Mac 2016实在是太慢了,写个邮件都要卡顿半天,重新装了2011版来用,导出导入olm文件很是方便,这也是这几年来我一直使用outlook的一个主要原因。

遇到的问题是无法更新和欢迎界面每次都弹出。

其实就是一个权限的问题,我也懒的去找哪一个文件了,直接执行

find ~/Library -type f -user root -exec sudo chown `whoami` {} \;

问题解决!

by khsing at March 02, 2017 06:30 AM

March 01, 2017

@khsing

伟大长城带来的痛苦

上个礼拜,全球最大的开源社区仓库Github被认证,带来的不便就不说了。

最近用了一个项目,大量的使用了Git Submodule,如果在CI服务器上来做这件事儿,就是问题多多。没有办法,我只能clone一个下来再把内容放到自己的git repo里去,把依赖于github的submodule都给去掉。

苦不堪言!

by khsing at March 01, 2017 08:27 AM

February 27, 2017

@khsing

一毛钱股份

就算老公一毛钱股份都没拿到,在我心里,他依然是最牛逼的创业者 的文章上个礼拜被炒的火热,当事人很快就被扒出来了,最后陈CEO也出来解释了;

这事儿最重要的一点就是CEO老陈有没有给老韩承诺给股份?不管是口头的还是书面的,甚至比例都不重要,只是确定这个饼是不是存在。

如果没有,老韩媳妇现在要股份是理亏,最终是吃亏。

如果有,但是比例没有定,那么一个股份制公司运行了7年之久还没有确定的股份比例,我只能说老陈这个CEO不是蠢就是坏!

  1. 至于老韩人家家里过什么样的生活和股份的获得没有任何关系!甚至有说老韩你7年买房、买车、结婚生子,日子已经过的不错了。呵呵,圣人不死大盗不止!这7年人家日子过的好坏,买了豪车别墅也和凭承诺拿股份没有任何的关系;这就好比是一个公司在创业初期,比尔盖茨投了钱或者精力,比尔盖茨过的生活也和能否获得这个公司股份是没有关系的,如果这公司有承诺比尔盖茨股份,那就按承诺来,如果没有那比尔盖茨也得吃瘪,还是和他个人的生活没有关系。同理,公司现在的经营情况,获利情况依然和老韩拿股份这事儿没关系,只和当时的承诺有关,与其他事都无关;
  • 至于公司后面的发展老韩无法带队或者工作状态低迷,而且就老陈CEO的回复来看,是给发了200万分红之后出现的;这个情况还是和老韩获取股份没有关系,如果老韩入伙时没有承诺,老陈CEO就该早做决断,而不是把这个问题一拖再拖,而且是从2013年拖到了2017年。有承诺,即便是消极怠工也一样得给股份,请参考聚美优品陈欧在新加坡的公司一事;

  • 发200万和发100万也和股份获得没有关系。注意,这个文章是老韩老婆发的,也许老韩只和老婆说了100万,也许公司只发了100万。这笔钱并不是老韩退出股份的报酬,所以该是多少股份还是得给多少股份。

  • 说一千道一万,最重要的还是承诺;老陈没有承诺,老韩给公司干了7年,终了白干,这是老陈CEO辜负了老韩的信任;老陈给了承诺,终了没有兑现,这是老陈CEO的失信,甚至可以对簿公堂;老韩后期消极怠工,这是老韩不义;面对老韩消极怠工不做处理,这是老陈CEO失职;

    结论:拖延症害死人啊!

    那到底该不该给老韩股份呢?

    有句话叫吃水不忘挖井人,老陈在最需要的时候,老韩跟他一起干,完成了公司的冷启动,你说他该不该拿股份?

    再说了,老韩和老陈一起干的时候是降薪,经济学有个概念叫机会成本,老韩也许没有直接投入金钱,但是投入这家公司的机会成本是值得他拿这个股份的!

    by khsing at February 27, 2017 03:23 PM

    February 23, 2017

    @khsing

    继续留在Mac OS X

    macOS 10.12 发布之后我升级过了两次,但是体验都不是很好,本身系统的变化不大,但是带来的问题并不小,对我最大的影响是外接显示器之后的风扇狂转不止。甚至让我产生了它们要修复系统在老机器上运行过于流畅的bug了。

    本身我自己的MBP也已经用了4年之久了,是应该更新一下了,然而对于新版MBP的失望,配件的短缺,看来我的MBP还要继续服役1年以上,等配件比较齐全的时候再下手了,希望到时候macOS能稳定一些。

    我常读的Joel On Software主角,Joel Spolsky也表达了同样的

    @spolsky: Sorry Apple. After 10 years loyalty, this latest MBPro with useless touchbar and unreliable keyboard was last straw. Switched to Dell XPS13👋

    tweets

    by khsing at February 23, 2017 04:10 AM

    January 08, 2017

    @khsing

    在阿里云ubuntu 16.04 lts上安装gitlab-ce

    需要安装一个gitlab-ce给大家用,最近把操作系统都换到ubuntu来了,这个ubuntu是阿里云定制过的。

    清华大学又一个gitlab的镜像,但是阿里云无法连通,超时,但是单独curl又是好的,结果呢是阿里定制了/etc/apt/apt.conf文件,修改如下即可

    Acquire::http::Proxy "http://mirrors.aliyun.com/";
    

    内部用一个proxy连接的trick,添加一行即可使用清华的镜像了

    Acquire::http::Proxy::mirrors.tuna.tsinghua.edu.cn "DIRECT";
    

    by khsing at January 08, 2017 04:00 PM

    November 17, 2016

    @khsing

    Trump elected to be next president

    做为一个中国人没什么太多资格去讨论一个外国元首,但是他作为一个影响全球的世界元首,对其他国家或多或少还是有影响的,从最近汇市和股市的尿性就可以看出来了,就这还没有上任呢。

    至于Trump为啥能被选上呢?鬼知道,现在来看大家都归结于社交媒体的胜利。不无道理,以我之见,很多人选Trump的主要原因是想看到一些改变,而不是希拉里作为一个成熟政客的4年表演,她的表演和观海同志一样,who want repeat 4 years again? 而Trump能不能做到他说的make American great again, 未必吧,潜台词是American is not great anymore,但是即便是如此大家也愿意看到一些不太确定的变化吧,更何况Trump说的一些事情也是很多人想做的,比如限制非法移民和废除Obama~~Don’t~~Care之类的。

    至于现在的民族主义、孤立主义抬头,全世界的新潮流吧,从英国脱欧开始到现在的美国有可能转向保守主义等等,都有表明这个世界正在起变化。全球化进程是不是就此开始衰退,我倒没有太担心,从发达国家已经流出的工作岗位是不会再流回的,他们只是很有可能被另外一种更新的技术来取代。

    今天这是卖白菜的操了卖白粉的心,多虑了,洗洗睡觉!

    by khsing at November 17, 2016 12:58 AM

    November 16, 2016

    @khsing

    selenium wait 和 iframe

    还是从朋友那个小事儿做的时候弄出来的问题

    1. selenium 如何切换driver到一个ID设置为中文iframe?
    2. 遇到alert了怎么处理?
    3. 检查某个元素是不是出现了?

    不要问我为啥id会用中文,说多了都是泪,总之这是一个一言难尽的问题,一句话,国有企业你懂的。

    1. 切换到特定的iframe/frame
    driver.switch_to_frame(driver.find_element_by_id('some_id'))
    

    这样就可以在这个frame/iframe里做相应的find element操作了,但是要记住操作完了要切换回来

    driver.switch_to_default_content()
    

    多层嵌套的iframe也没有问题,只要一步一步的切换进去就好了

    1. 接受alert

    一个简单的方法就是预计有alert的地方,写上接受就好了

    driver.switch_to.alert.accept()
    

    这样很粗暴,但是也很有效,精细一些的做法看文档,比如:

    • 确认或者取消
    from selenium.webdriver.common.alert import Alert
    Alert(driver).accept()
    Alert(driver).dismiss()
    
    • 读取alert的文字内容
    Alert(driver).text
    
    • 认证的用户名和密码
    driver.switch_to.alert.authenticate(username,password)
    
    • 输入内容
    name_prompt = Alert(driver) name_prompt.send_keys(“Willian Shakesphere”) 
    name_prompt.accept()
    
    1. 检查某个元素是否出现

    以前的一个很粗暴的做法是time.sleep(N),但是这种情况下非常粗旷,selenium 提供了更精细的一些控制方法

    • 等待某个元素出现以后获取这个元素
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    wait = WebDriverWait(driver, 10) #10秒,超过这个时间就会raise Exception
    element = wait.until(EC.element_to_be_clickable((By.ID,'someid')))
    
    • 这里的expected_conditions可以是下面的这些条件
      • title_is
      • title_contains
      • presence_of_element_located #元素可以找到
      • visibility_of_element_located #元素可见
      • visibility_of
      • presence_of_all_elements_located #所有元素可以被找到
      • text_to_be_present_in_element #元素中包含text
      • text_to_be_present_in_element_value #元素的value值包含text
      • frame_to_be_available_and_switch_to_it #iframe可以切换
      • invisibility_of_element_located #不可见元素被找到
      • element_to_be_clickable #不但可见,而且可点
      • staleness_of
      • element_to_be_selected #元素被选中
      • element_located_to_be_selected #
      • element_selection_state_to_be
      • element_located_selection_state_to_be
      • alert_is_present #弹框出现

    这些基本覆盖了常见的情况了,足够用了,记得处理异常,否则就挂了。

    by khsing at November 16, 2016 11:22 PM

    macOS 的ssh-add -K

    macOS 10.12 开始ssh-add并不是默认将你的ssh-key添加进去了,所以需要额外配置一下

    打开自己的ssh配置文件~/.ssh/config,加入如下内容

    Host *
        UserKnownHostsFile /dev/null #这一句还好吧
        StrictHostKeyChecking no #这一句非常危险,结合上一句再加上dns劫持的话,再加上密码认证就很有泄漏密码的可能性
        ForwardAgent yes
        TCPKeepAlive yes
        IdentityFile ~/.ssh/id_rsa
        AddKeysToAgent yes
    

    by khsing at November 16, 2016 03:09 AM

    November 08, 2016

    @khsing

    再说 vendor 目录进不进版本控制

    先说结论:不进

    官方的指导是不进,如果非要进有如下四个方法

    1. 尽可能使用已经发布的包,这样可以使用tarball的方式来更新。
    2. composer.json中指定preferred-installdist或者更新的时候带上--prefer-dist参数
    3. 在提交git/svn之前,删除掉所有.git目录
    4. 在项目的.gitignore中加上/vendor/**/.git

    为什么我又来发这个了呢,因为我踩到坑了啊,由于使用了private package在composer.json中加了repositories,结果vendor下这些内容都成了submodule,但是远端的并不会更新,所以这是一个很严重的问题。

    至于以后的部署问题,我还要再梳理一下。

    by khsing at November 08, 2016 10:34 AM

    November 07, 2016

    @khsing

    Selenium 连接一个已有的连接

    帮朋友弄个东西,需要先登录,有一个不复杂的验证码,但是上OCR也太重,所以就先起一个driver,然后手工登录之后再连过来进行操作.

    • 先启动一个Driver和Session,并且打印出连接的URL和Session
    url = driver.command_executor._url       #"http://127.0.0.1:60622/hub"
    session_id = driver.session_id            #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
    
    • 然后再连接过去
    driver = webdriver.Remote(command_executor=url,desired_capabilities={})
    driver.session_id = session_id
    
    

    REF:
    Stackoverflow: Connect to an already running instance of chrome using selenium in python

    by khsing at November 07, 2016 08:38 AM

    对新的 Macbook Pro 有点失望

    新的 Macbook Pro 发布已经有一小段时间了,接口都统一成了USB-C的样式,新增了一个Touch Bar的功能,外形上基本没有变化。

    我现在使用的是Macbook Pro的2012年中版,平时的情况基本满足需求,对我来说目前就是内存和SSD硬盘都有一些吃紧,Touch Bar什么的其实我并不Care,所以要我升级来说主要就是升级内存和SSD,如果说外观上能有一个升级的话,这是加分项。

    But,这一次的升级除了Touch Bar之外乏善可陈(Touch Bar其实最有用的是TouchID),而且Touch Bar还去掉了ESC,这对于一个程序员来说是个悲剧,就更不要提那个蝴蝶结构的键盘了。其次就是那个令人诟病的接口了,机身只有4个USB-C,充电、数据传输、外接显示器都得靠这4个全新的接口,所以买回来的第一件事应该是买USB-C相关的各种转接头,这简直就是个悲剧,更悲剧的是Apple这次涨价了。

    这样以来对于我来说今年要想更新Macbook Pro就不是一件明智的事情了,要么让我的老Macbook Pro挺一年,要不就是买一个2015款的16/32G内存的版本。我有点希望一个本子有ThinkPad的键盘+Macbook Pro的触摸板和ThinkPad的丰富的接口的机器,起码我不用带一堆配件或者辫子。

    记Apple一次失望的Macbook Pro更新,而且饭盒和垃圾桶都没有更新了。我有点离不开的是macOS,虽然它越来越烂了,也需要重启才能解决kernel_task占用过多内存的问题之类的,但是依然是目前能用到的最好的操作系统了。

    by khsing at November 07, 2016 03:20 AM

    November 03, 2016

    @khsing

    还是不要全局 .gitignore 了

    昨天踩了一个小坑,使用bower安装了一堆的组件进来,我这里是好的,但是同事去构建的时候就不对了。

    发现我git commit的时候,jQuery包里的dist目录没有添加进去,进而发现实际是我在很久以前在~/.gitignore里添加了一个dist导致彻底忽略了。

    索性就把这个家目录下的.gitignore给删除了,反正都是跟着项目走的,新建git repo的之后添加一个.gitignore就好了。

    by khsing at November 03, 2016 03:14 AM

    November 02, 2016

    @khsing

    在Mac上设置一套好用的PHP开发环境

    在Mac上工作多年,近1年多写PHP比较多,所以也总结了一点在Mac安装一套好用的PHP开发环境的套路。写出来丢在了Github上,更新了几次,这次给team更换开发环境到Mac的时候也是让大家照这一套来做的,自觉用起来非常顺手,主要的特点是:

    • 全部使用了HomebrewHomebrew Services来管理软件和服务
    • 环境是 Nginx + PHP-FPM + MySQL,如果有用到Redis和Memcached的地方使用brew install就好了。
    • 新增项目无需修改nginx配置文件
    • 尤其适合Laravel框架

    详见Setup Mac Development Envrionment

    by khsing at November 02, 2016 02:16 AM

    November 01, 2016

    @khsing

    我的 Macbook Pro 可能要挂了

    新的Macbook Pro发布了,看着一堆的TB3和配件,我觉的我的Macbook Pro还能挺一年。

    但是最近我的MBP的耳机插口坏了,这就尴尬了。

    于是我把音频输出走了TB到了Dell的显示器上,但是更尴尬的是显示器没有音量控制。

    于是我又接了一个功放在显示器上,好惨!

    by khsing at November 01, 2016 04:14 AM

    October 26, 2016

    @khsing

    解 git submodule 无映射路径的问题

    我们在使用Git submodule 的过程中我遇到的一个问题是执行git submodule update之后会出一个错误

    fatal: no submodule mapping found in .gitmodules for path 'vendor/predis/predis'
    

    这个问题就是你发现有一个不在.gitmodule文件中的submodule在更新,解决办法就是

    git ls-files --stage | grep 160000
    

    这可以看到你所有的Submodule文件,然后

    git rm --cached PATH
    

    Problem solved.

    REF:

    by khsing at October 26, 2016 04:01 PM

    October 17, 2016

    @khsing

    更换了iPhone 6 Plus 的电池,又换回去了

    上周我某宝买了一个飞毛腿iPhone 6 Plus的电池,主要是原来的那个电池只要天一冷就关机,最严重的一次是在电量70%的情况下,手机关机了,我很是焦虑,所以入手一个新电池准备过冬。

    盼星星盼月亮,终于把电池给盼来了,换上了,图片已经收入Flickr。但是悲剧发生了,换完之后充不进去电,坑爹啊!

    我又把iPhone的原装电池换了回去,飞毛腿退货,差评,换一个牌子继续折腾。

    btw.

    在手撕那个胶条的时候一定要慢,一定要慢,一定要慢,重要的事情说三遍!

    by khsing at October 17, 2016 09:42 AM

    阿里云的证书被吊销了?

    上周的我要登陆阿里云的时候发现他家的证书被吊销了,我发了个微博,阿里云的客服就立马回复过来了是:

    亲,经核实,SSL 证书管理机构及提供商GlobalSign的部分证书由于OCSP服务异常导致证书出现错误,会导致 macOS Sierra 系统部分用户使用 Chrome 或者 Safari 等浏览器时访问受限。GlobalSign反馈问题已经修复,新用户不受影响,但是由于证书体系的缓存性质,有一部分用户可能还会受到影响。
    

    但是今天还是无法使用Chrome打开,而Safari和Firefox都已经正常了。

    update: 2016-10-17

    重装Chrome之后正常了

    by khsing at October 17, 2016 06:16 AM

    September 25, 2016

    @khsing

    oh-my-zsh 总是很慢

    csh切换到zsh已经很久了,但是有时候他会很慢,甚至是在ctrl+c的时候,看了一下,主要的时间都是去检查git状态了,反正这个功能不是特别需要,就关掉好了。

    git config --add oh-my-zsh.hide-status 1
    

    Ref: oh-my-zsh slow, but only for certain Git repo

    by khsing at September 25, 2016 04:04 AM

    Safari 10 Released

    Safari 10发布了,除了在浏览器中支持Apple Pay之类的新特性之外,还支持了CSP(Content Security Policy) 2.0,这让好多 UserScript 就无法使用了。

    by khsing at September 25, 2016 03:51 AM

    September 23, 2016

    @khsing

    开始使用MWeb

    知道MWeb这个App已经很久了,也使用Markdown很久了,头段时间MWeb打折就下单了,而且也把blog从MovableType换到了Wordpress,所以也就结合用起来了。

    MWeb支持上传图片到Google Photos和七牛,但是我还没有尝试,所以就先这样吧,以后再设置前来玩。

    从朋友那里借了一个HHKB Pro 2 Type S,发现键位真是不太适应,刚刚适应一点,去别人那里总是按错键,也是小醉。

    ps. 本文编辑自MWeb

    by khsing at September 23, 2016 08:08 AM

    September 17, 2016

    @khsing

    再说阿里月饼事件

    之前我写了一篇《阿里价值观卖的是什么馅的月饼?》 说了一下我的看法,在那之后,事情有了新的进展,阿里集团把5人全部开除了,我也陆续看了一些相关和其他人的意见,就再说一次。

    先说阿里巴巴的最终决定,这基本上就是用一个错误去掩盖前一个错误的决定。他们讨论了4个小时,参与人包含了马云、逍遥子等人,基本就是阿里巴巴高管悉数出动了,而第一个决定只用了2个小时,参与人也就是HR、行政和这4个人的直接领导,另一个据说是阿里云的安全老人叶敏,在其领导道哥的周旋下虽然躲过了第一个决定,但是因此事把阿里巴巴放在公众风暴眼的情况下,几个大佬就做了一个简单但是他们却艰难的决定,叶敏也开除,从此阿里黑(阿里云除外,原话)。

    我在Eric 这一篇阿里月饼事件: My Concurring Opinion里注意到一个细节是此事之前有规定只能预定1个订单,最多3盒,单就这一点,从结果看这5个人都超出了规定数量,都违反了规定;到这里我也不否认这5名同学违反活动规定,采用技术手段影响了秒杀月饼这个活动的公平性(也仅仅是相比较其他没有使用技术工具的同学而言);

    真正值得争议的部分是阿里对此事的处置办法,在2个小时内让涉及此事的4名同学走人,罪名状是:违反阿里核心价值观——诚信原则。且先不论阿里价值观中是否有这一条,先说说这几位同学是否因此事可以确认他们就不诚信呢?诚信,诚实守信。这几名同学在发现预定月饼远超自己想要的数量后是主动向行政部门报告了此事,而且坦白说明使用了脚本来模拟点击秒杀月饼,这不是诚实这是什么呢?守信,单从此事我并看不出他们有失信于谁的行为。

    要说错,他们唯一的错在于抢的太多,影响活动公平性的问题也来自于此,要是他们脚本只抢1单或者系统只允许抢1单(没想到可以连续秒杀,换成真人去点也一样),我相信这个问题便不存在了。凡是认为他们使用脚本进行秒杀本身就是动机不对,此诛心之论,要是这样来说,凡是使用工具抢火车票的都是动机不对,理应枪毙;

    单从抢月饼一事我看不出这5名阿里员工有何违背诚信的地方。

    关于微博上 @吴军博士言论 , 我非常认同贺师俊的回答

    同时我也看到有人在知乎问 如果月饼事件(或类似的事)发生在 Google、微软或者 Facebook 这种公司,它们会如何处理? ,回答都很不错。

    喜事办成丧事,这也是阿里HR的本事。

    by khsing at September 17, 2016 04:36 PM

    May 03, 2016

    @shell909090

    唐僧被吃了

    唐僧被吃了。

    本来不应该发生这样的事的。

    正常来说,悟空会随时在师傅身边保护。要逃过悟空的眼睛,几无可能。因此唐僧的安全可以说是固若金汤。但是事有凑巧,今天是悟空回天庭报道的日子。由于悟空当年大闹天宫,被压在五行山下。今日戴罪立功,属于假释。所以按照天庭假释管理办法,需要每个月向天庭报道一次。当然,正常来说这种事情也就是走个过场。天上一日地上一年,每月报道一次是按地上时间计算的,所以在天上就是每个时辰出现一次,日夜不休。天庭监狱管理委员会的工作人员也受不了这个繁琐,所以文书手续,验明正身一概抽查。正常而言只要猴头出现,就算过关。

    但是今日,玉帝闲来无事,要去隔壁礼部视察。礼部主事和刑部尚书关系交好,于是偷偷通知了刑部尚书。万一玉帝没事干,出了礼部进刑部,那就是天大的麻烦。所以各种见不得光的事情都要收起来。因此悟空这几个月的报道格外麻烦。

    为此,悟空特意驾筋斗云前后看了一圈。附近地界太平,没有什么妖孽。又召出土地来问过,再三确认安全。于是向二师兄三师兄好好叮嘱了一番,这才上天庭报道去的。

    然后唐僧就死了。

    如来很生气,后果很严重。悟空队还没排到,就被监狱管理委员会的人扣下。西天联合天庭,成立天庭取经事故联合调查委员会,由迦叶尊者任首席调查官,主持调查工作。太白金星出任首席行政官,代表天庭协调双方工作。

    委员会成立后,首先对事情的经过进行了初步的调查,基本排除了悟空伙同外人作案的可能性。于是委托太白金星对悟空进行谈话,说服其配合委员会的工作。在这次谈话中,悟空才初次知道师父去世的细节。

    据天庭取经事故联合调查委员会的初步查证,事故是这样发生的。唐僧师徒行路到一半,看到个牌子,上面写着,大雷音寺,左转向前,还有28公里。于是唐僧师徒毫不怀疑的左转。结果前方并不是大雷音寺,而是小雷音寺。唐僧师徒住下后,唐僧在沐浴时不慎撞到头,昏倒在池内。童子问水是否够热无人回应,误以为客人喜欢热水。于是添足柴火,三个时辰过去,唐僧师父被煮成一锅老汤。。。

    太白金星话还没说完,就被悟空飞起一脚踢倒。还没站起身,就被悟空楸住领子:老官,你扯的什么鬼话。哪里有人会呆呆被烧一点动静都没有的,我师父又不是木头。这种鬼话就是骗童子都不够,你真当俺老孙呆子不成!

    太白金星连忙求饶:大圣,大圣,听我一言。当初调查委员会的人也是不信,可是小雷音寺的人说,西方有科卡罗斯煮死米诺陶斯,那米诺陶斯又不是呆子。为什么唐师傅的事就不可能是意外呢?

    悟空冷笑一声:就算是意外好了。他们装成大雷音寺,骗我师父入住,这才能不动声色煮死我师父。这冒充大雷音寺的罪过,总不是意外了吧。

    太白金星又说:这个我们也调查过了。对方拿出一份西天颁发的“关于鼓励信众自行传教的规定”,其中第一百七十三条第五款规定,为了传播西天教义,允许采取各种形式。因此小雷音寺的信众们就采用模仿大雷音寺的方式,向民众宣传大雷音寺的尊严。

    大圣顿时哑口:这种事难道教务办不管么?

    太白金星道:教务办哪里有空一个个检查信众自行传教的细节,最多也就是出了岔子找出首恶而已。实在乱子搞大了,了不起再出一个“关于禁止信众自行传教的规定”也就是了。

    悟空咬咬牙,再道:就算小雷音寺无事,那乱插路标,诱我师父前去之人呢?

    太白金星拨开悟空手指:大圣,小雷音寺的人对我们都拿的出“关于鼓励信众自行传教的规定”,对着人家自然也是拿出规定,说为了弘法,故此需要改标线路就是了。

    悟空双手抱胸坐下,翘起二郎腿冷笑:天下哪里有为了弘法,把正法指向邪路的道理。必是此人见钱眼开,没细细核对文件之故。

    太白金星道:悟空,你又何必固执。他又不是吃你师父的首恶,你何必和他过不去。要说细细核对文件,你前几次的假释报道,似乎也是核对不全吧。

    悟空轻叹口气:师父也许呆,俺老孙却不傻。小雷音寺敢仿大雷音寺而无事,显然是背后有人不希望我师徒前去西天。因此调查报告里鬼话连篇,就是不敢指摘背后之人的不是。我待罪之身,哪里能左右这些。俺老孙唯一能左右的,便是此为虎作伥之人。若不是他从中作梗,哪里来这许多事。周围乡邻,难免也为其所骗,拜错菩萨。难道你认为他无罪?

    太白金星微微一笑:非也非也,大圣你这么想是再好不过。

    悟空微微一愣:怎讲?

    太白金星道:既然小雷音寺众人无罪,这桩事总也需要个了结。你是观音菩萨保举,若说是你玩忽职守,大家面上不好看。西天的意思是,此人擅做主张,引诱唐僧师父到小雷音寺,以至招待不周,发生意外。此人负有不可推卸的责任。大圣你再做污点证人,说他当初也为你指路,并无什么不妥。以至于未曾察觉。

    悟空怒道:合着你们就是找我坑替罪羊来了?

    太白金星道:大圣,大圣。你不刚刚还主张要严惩此人?如今随了你心意,你又要怎样?

    悟空呆若木鸡,不知如何自处。

    PS:其实昨天就写完了,拿给霍叔叔看。霍叔叔说,你这类比太绕了。我说好,我想办法改改。结果还没等我改,取经事故联合调查委员会已经宣布了调查结果。再等下去怕是连西游记都要被查禁。所以赶紧出一版,大家凑合看看吧。

    by shell909090 at May 03, 2016 03:58 AM

    April 11, 2016

    @shell909090

    三亚潜水体验

    最近去三亚玩了,我就说潜水吧。

    水况

    潜水地点是在分界州,水不算太好。水下景点一般在深度5-15米范围内,有两艘沉船,一个飞机残骸。小沉船离岸比较近比较浅,水深不超过10米。大沉船需要再游一刻钟,深度15-18米左右。飞机残骸也差不多深度,不过只看到一点。水下危险生物包括狮子鱼石头鱼棘冠海星(魔鬼海星),水母。这次潜导在水下就被水母蜇了,被蛰的还很神奇。他下水就戴了面镜,升上水面就开始痛了,还被蛰在眼皮上。到底水母是怎么进去的就鬼知道了。不过问题也不严重,痛了一会就没事了。

    能见度分别比较大。在10米左右有一个明显的分界面。在分界面上,能见度大约是10米左右,下面只有3-5米。从上面明显能看到下面像一潭池塘一样。水底温度21-22度。我去的时候是四月上旬,所以只能代表这个时间点的情况。据说6月前后的时候能见度会好很多,水温也会比较高。亚龙湾和蜈支州的情况据说要好点,不过从我看到的水色来说,估计好不了太多。

    洋流情况还好,0.5m/s以下,一般都不构成问题。那天浪在0.5m左右,水面上有点晕。周围潜水环境还行,只是偶尔有人炸鱼,可能有巨响。另外水面上有摩托艇在开,和潜导分开的话,没有SMB上浮会比较危险。

    潜店

    这次潜水是走的中仁潜水的持证fun dive,价格是880两支气瓶。价格包括接送,上岛费用,一顿午饭。还包括了海豚表演门票。但是fun dive来说,根本没时间去看。

    BCD,fin,regulator是潜店提供的,他们问了我的身高体重来配fin和防寒衣。不过防寒衣是岛上提供的。我的体型比较大,所以穿了他们最大的防寒服。5mm的,比较适合水况,也很新,估计是穿的人不多的缘故。本来还问了我是否有度数,不过我的面镜和呼吸管是自带的,所以用不到。我还自带了3mm的手套,考虑到这里的水下危险生物,这个举措其实非常明智。

    岛上有免费的更衣和冲凉,但是寄包要20元。气瓶是中潜自己打的,一般都超过200bar。但是配重是公用的,比较烂。

    我们潜FD是岸潜,水面游动100-200米。DSD有一个平台,跳下去就行。平台那里比较浅,据说在5米左右。

    三亚潜水

    除了分界州外,我还去了一趟亚龙湾。在那里,我碰上了三亚名产——体验潜水。

    下车之后我就看到有人在做潜水培训。仔细看了一下,是一个潜水体验旅游的报名点。名义价格是400左右。我仔细观察了一下,整个点没有任何标志。没有PADI或者CMAS的标。

    在我吃饭的时候有人过来拉生意,鼓动我们潜水。我直接说我是PADI的持证潜水员,然后他就消失了。

    不做任何评论,大家自己分析。

    注意,在三亚海滩上是有打着PADI标志的潜店的,在PADI上也可以查到这家。不要以为我说的是他们。我其实在他们店里休息过一会,听了他们和客户的一些对话,觉得他们做生意还基本不过分吧。

    by shell909090 at April 11, 2016 04:33 AM

    March 25, 2016

    @shell909090

    潜水的一些简单解说

    潜水的乐趣

    潜水好不好玩?不好说。这得看你是不是喜欢潜水。不同的人在潜水中获得不同的乐趣。有人喜欢看鱼看珊瑚看沉船,有人喜欢水下漂浮的感觉,有人甚至只是泡妹子/帅哥。是的,潜水者里帅哥/美女的比例极高。因为潜水很要求体力,所以大部分人身材都很好,像我这种胖子绝对是少数(不过在学校里我看到了另外一个胖子,比我还夸张,衣服都是自带的)。我甚至看到一个学着学着潜水泡上了教练的妹子。。。

    是否适合潜水

    潜水的一般性要求是10岁以上,没有心血管疾病,癫痫什么的。细节可以去PADI网站上看一下。通常对于休闲潜水而言,大部分人都应该是没问题的。这里只说几个上面没有的问题。

    不会游泳能不能潜水?

    咳咳,我就不会游泳。

    潜水对游泳的要求是,能在水面上游动200米,或者在水面停留10分钟(我记得是这两个值)。这基本和会游泳没什么区别——除了通过条件。考核这项的时候,是允许你穿着防寒衣在海水里考的。这等于让你穿件救生衣问你会不会游泳一样,我想大多数旱鸭子的水性还不至于糟糕到这种地步。糟糕到这种地步的,坐船都要额外买保险了。

    但是会游泳还是非常有帮助的。如果会游泳的话,在水下移动的时候会很有优势。所以建议还是去学一下游泳。当然,你可以学以潜水为目标的游泳——主要就是不用换气。不求游多少距离,没气了站起来喘完了再游也行。

    潜水的另一个要求是胆大心细,遇事冷静。在水下碰到状况,很多都只能靠自己。所以胆子要大,但是遇事要冷静。

    当然,冷静谁也说不好。有的人平时也挺冷静,碰到大事了就突然反应不过来。大多数人都是这样,也不用不好意思。至于胆量,有个很简单的测试。找一个游泳池(当然,是淡水),3米以上,脚够不到底的地方。不穿救生衣,从岸上往下跳(注意,很多泳池禁止你这么做,请首先咨询管理员取得许可),跳下去之后游回岸边。捏着鼻子插筷子也好,摒气也好,随便你。看你的胆子和游泳技巧是否能够做到。如果做不到,例如不敢跳,或者跳下去根本不会游上来,那就不要费劲了。你跳下去不是潜水,是去找死的。

    技术解说

    携带呼吸装置潜水其实只有一个要点,就是呼吸。除此之外的东西都只能算是技术,学了肯定能会的那种。例如怎么组装备,规范动作怎么做什么的。智商没什么太大问题都很容易。

    可能很多人会首先说耳朵的问题。耳压平衡是潜水基础中的基础,一上来就会讲的。在水下做了平衡就不应该耳朵痛了。像三亚名产,不做平衡告知就丢下水,10分钟后耳朵痛就升水,那是道德问题,不是技术问题。如果学了耳压平衡但是做不到,那平时坐飞机都应该有问题,你需要检查内耳疾病。

    呼吸之所以重要,是因为呼吸关系到浮力。会游泳的应该有体会,浮在水面的时候,吐气就会下沉。潜水的时候也是一样,吸气上浮,吐气下沉。听起来很简单,但是水里需要呼吸不停,而且由于游动,呼吸量还不小。这种情况下如何保持稳定,就是一个非常有技巧的事情了。技术上说,这叫中性浮力。好的潜水员甚至可以靠呼吸停留在沙滩上十公分处,既不接触,也不浮上去。

    潜水的时候,身上的气瓶是负浮力。防寒衣虽然是正浮力,但是不足以平衡气瓶。如果只穿这两件的话,就必须不断踢水,停止踢水就会下沉。所以身上会背一个充气背心,来抵消气瓶的浮力。这样通过向背心内充放气,可以将全身的浮力和重力抵消到1公斤以内。人的一次呼吸一般潮气量在3000左右,换算成浮力有三公斤左右的波动,这样就可以通过呼吸来控制上升下降。一般操作上还会额外配一些配重,然后通过背心的浮力抵消配重。这样一方面在下潜的时候允许通过放气变的更重,可以有更大的余地。另一方面,在遇到紧急情况的时候,也可以通过快速脱下配重浮出水面(警告,这样很危险,容易产生减压病或肺部过度扩张)。

    浮力的难点在于,呼吸对浮力的影响是瞬时的,但是你很难感知现在是正浮力还是负浮力。你能发现的只有浮力对深度的影响,现在是往上飘了还是往下沉了。这就像顶杆子一样。你不能感觉到力,只能感觉到位置变化,不断调控。而呼吸要影响到深度,至少需要1-2秒的延迟。而且等你发现的时候,往往像火箭一样,停不下来了。好比上浮,吸一点气,我擦没反应啊。再吸一点?哎呦沃草升天啦。赶快吐气,我擦快停下,快TM升水了。好了好了。。。等等,我擦怎么变砖头了?再来。。。等你折腾一会,教练会让你看一眼压力。靠,没气了,升水吧。

    理论上说,要找保持悬浮,需要找准平衡气量,在这个范围内小幅呼吸。但是在不同深度下,充气背心的浮力是会发生变化的。潜水到后面,气瓶里空气不足,也会产生额外的浮力。你需要不停用经验发现现在的平衡气量是多少,围绕着小口呼吸,甚至有的时候需要充放气来重新平衡一下。

    中性浮力是很多东西的基础。例如在水下摄影,如果浮力一塌糊涂,一呼吸相机都抖成中风了,潜水又禁止憋气。那还照个P啊。从珊瑚上游过也是,如果浮力控制不好,要么离很远,要么你就会直接在珊瑚上砸出一个人型的坑。

    PADI的技术路线

    PADI的入门课程从小孩开始(骗钱从娃娃抓起啊),我们这里只说大人的。

    最低的是SCUBA Diver执照。一次体验潜水,然后做泳池课程和基础训练,再潜两次就能拿到。这个执照能潜12米深度。

    大部分人应该没听说过SCUBA Diver执照。因为只要再多两潜,几乎不需要额外课程,就可以拿到OpenWater执照(简称OW)。大部分人会直接潜水五次,拿OW执照。潜水深度从12米提高到18米,这样就可以去大部分地方潜水玩了。

    OW再往上是Advenced OpenWater(简称AOW)。AOW在拿照方式上和OW有本质性区别。OW是固定课程,你想不想,五节课都要过才能拿证。AOW是一堆专长,两项必修的,其他再选三项,就能通过。总计来说需要潜水五次,两次超过18米深度。完成AOW执照后,可以潜30米深度。

    上面这些深度什么概念呢?例如某次我们潜的Greenrock,一块大石头,三个顶部。最高的地方7米左右,最低30米没到(印象里的资料,可能不一定准)。SCUBA Diver的话就只能看三个顶部。OW的话就能绕着大石头一圈看岩壁和缓坡。AOW的话可以在石头底下绕一圈——正好有个班戟鱼的窝。所以很多点其实大部分执照都能下(甚至包括体验潜水),但是不一样的执照看到的东西会有差。除非你打算只去深度非常小的地方,否则执照当然是越深越好玩。当然,以休闲潜水来说,40米的深度还有很多地方去不了。但是安全起见(也是为钱包的安全),暂时就这样满足了吧。

    然后就是AOW的一堆专长。例如我修了一个鱼类辨识(看着很扯淡,其实就是看鱼玩),一个深潜,一个水底导航,一个沉船,一个顶尖中性浮力。其实大同小异(骗钱也是不手软哦)。除了告诉你一些技巧外,主要就是在不同环境下潜水。等潜水次数多了,自然就熟练和有信心了。

    AOW和AOW以下的执照,加大部分的专长执照,其实都不难拿。有钱,有闲,也就差不多了。甚至都不必须考。例如我需要去夜潜了,现场找潜店把钱交掉,题做掉。然后就可以带着去了,回来就拿到证了。无非也就是哪里拿的证和多少钱的问题。

    注意我说大部分。AOW有个专长叫潜水摄影,是问的最多的专长。尴尬的是,这货的难度非常高,我不知道为什么这货会进AOW专长课的。考这玩意一般需要学上几个礼拜,比DM都简单不了多少。当然,买的下潜水相机的人而言,倒是不会缺钱的。

    其中还有一个特别的执照,Nitrox,高氧潜水。高氧主要是用于长时间潜水,减少残氮量的。这玩意不是长时间潜水几乎不会用到。高氧的特别之处就在于,一,高氧潜水有额外风险,二,你可以拿高氧去潜深潜,从而一次性多拿一张执照。

    特别重复说明一点,并不是说氧气含量高了就能潜的深。恰恰相反,氧气浓度越高,潜水深度越低。纯氧在水下六米处吸了就有很大可能会挂掉,反倒是EANx32(氧含量32%)的氧气能允许你潜深33米。高氧的唯一目地就是减少残氮量,从而增加你的免停留潜水时间。这方面详细情况,我会写一篇关于高压空气的话题。

    要不要修哦?如果你可能会单次重复潜水,次数很多的,深度很深的,可以考虑。因为气比免停留时间还长。如果是一天两潜,深度又不高的。免停留时间本身就够,你要高氧干什么呢?急救?

    AOW再往上,潜到20左右,可以去出一张RESCUE的证。这张还要配修EFR的,贵的要死,不过基本没啥用。RESCUE是你能救别人,不是别人能救你。但是尴尬的是,又不是因为你有RESCUE执照就能带人潜水了——恰恰相反,你自己潜水还是需要人带的。而万一出了问题,正常来说带你的那个人急救资格都比你高(也肯定比你熟练)。那这张证能干嘛呢?在带你的那个人不在的场合下——例如不在潜水的时候——救人。

    你妹,不如说让我TM学游泳救人算了,还用的上点。

    潜够40,可以开始考DiveMaster(潜水长)的执照了。这个执照非常难,一般都要70潜以上才考出来。因为AOW和DM的差别就是业余和专业的差别了。在过了DM之后,你潜水就不需要人带,可以自己约潜伴了。

    我暂时还没搞明白,DM是不是能带AOW或者OW去潜,还是AOW或者OW必须由OWSI带。反正我碰到所有的DM都拿到了OWSI。

    DM再往下是专业线了,我记得不是很清楚,自己看吧。反正拿到这个证的,课程都远比这点发展线路复杂了。

    潜点选择,交通和成本

    每个潜点都有一些特点。例如珊瑚(珊瑚周围往往有大量热带鱼),石缝里的鳐鱼,海鳗,天然形成的洞穴,沉船等等。这些特点往往会对应不同深度。有的时候证不够就没什么必要去某个潜点——好比koh tao的Sattaukt这个点。沉船的位置在水下24-30米,没有AOW的证根本去不了,只能在上面远远看着。还去干嘛呢?不如去隔壁的Whiterock钻洞。还有一些点,会在特定的时间形成特色——例如鱼类季节性孵化和成长的时候。这些也需要提前搞明白。

    所以要到一个潜点前,需要查潜点地图,搞明白每个潜点的特色,需要什么证书,并且提前约好潜店和潜伴。不同潜店不同时间会去不同的点,有的潜店甚至需要提前预约才行,否则当前是没有船去的。至于约朋友——要知道,潜水行程意外太多,凑不齐人不奇怪,凑齐了才是意外。要潜店约一堆人容易,自己约朋友就纯看运气了。就算平安无事到了地方,万一碰到感冒就只能扫兴而归了(我不大建议吃通鼻子的药去潜水)。所以要珍惜每个和你一起潜水的朋友,能碰上是多大的缘分啊。

    每个潜点也会受到交通方式的影响。近海的潜点可以船潜或者从岸上下水,但是稍微远一点的,十有八九都要船潜,甚至需要船宿。这时候需要考虑自己是否受得了船宿的晃动和晕船。

    还有,来返潜点的交通方式往往用飞机。但是潜水18小时内是禁止坐飞机的。所以假期短的话,会耗费大量时间在潜水以外的时间上。这会使潜水成本大幅上升。建议能准备一些不潜水也能玩的地方来填充时间段,同时尽量准备长一些的假期。

    装备

    作为入门,一般你不需要买任何装备。大部分潜店都会租装备给你。大多数情况下,自带装备的运输费用(和劳动量)会比租装备还贵。唯一例外的是有戴眼镜的人的潜水面镜。潜水不能戴眼镜(废话)。为了安全起见,也不建议戴隐形(做过全面镜脱着的应该知道为什么)。所以建议你买一副潜水镜(注意,要罩住鼻子),然后凭你现在的眼镜度数去配光学玻璃装上去。

    如果体型特别巨大(脸好疼),可以考虑买自己的防寒衣或者全身式潜水衣。以免你想借却借不到的尴尬。水鞋没啥必要,反正一般常潜的脚底都应该够厚了,不常潜的买了你也用不上。

    如果经常潜水,例如一年五潜以上,可以考虑买一支自己的潜水电脑表。入门的也就千把块。自己的潜水表可以记录自己潜水的精确数据,潜店的装备里一般不会包含电脑表(除非租高氧气瓶),而压力表上连的那个二货往往功能有限不说(例如无法设定高氧),你也不能连着调节器一起拿走啊——那还不如直接买电脑表呢。

    值得初学者考虑的装备还有能在水下写字的板子和笔,水下的哨子(或其他声响设备),潜水手电。水下不能说话,通讯全靠手势。万一碰到手势搞不定的问题,不想升水只有用白板了。不过这种例子一般不多见,反正我潜了十多回就碰到一次,还是在水下考鱼类辨识。哨子非常有用,方便通知别人让他们看你手势。但是这玩意常规也不大用,一般只有DM叫人的时候用。如果有上过夜潜课的话,潜水手电也可以考虑入一个,大不了平时当普通手电用。

    一般好像很少有人会自带BCD的。我见过一起潜水刷瓶子打算考DM的一个妹子自己有一个背飞的BCD,但是实话说没感觉哪里必要。先不说价格,每次潜水回去的时候把BCD洗好收起来都是个大麻烦,更不提带来带去的重量。调节器也没见有人自备的,一般拿船上的就行。自己的还要定期找人检修维护,万一哪个岩石卡一下又要心疼半天。倒是O-ring可以自备几个,以免气瓶还在,O-ring没了。

    倒是很多不在装备清单里的东西很值得备一个。例如防水包。在船潜的时候,潜水日志啦,眼镜什么的要找地方放,还要防水。有个防水包会非常方便,还能放放衣服。还有,如果晕船的话,最好准备一些不嗜睡的晕船药。有的潜店会准备,但是有的潜店就不会管这个了。别以为自己不会晕船,你试试多潜几次再说。

    by shell909090 at March 25, 2016 05:16 AM

    March 06, 2016

    @xupeng

    团结紧张,严肃活泼

    今天,3 月 6 日,是豆瓣 11 岁生日,我做梦一样游了 798,看到大蔡司,还以为蔡司在这里开店了呢,

    后来才发现污龙了,

    然后莫名其妙来到中二街,

    稀里糊涂和自由女神合了个影,

    受到了严重警告,

    突然醒悟虽然圆外那么大,但可能眼界之内都是荒草。


    说完正经的,接下来是不正经的。

    我基本上是一个严肃的人,尤其是前些年工作中讨论或者解决技术问题的时候,这倒也符合其他角色对工程师的一贯印象,想起来大概是 08 年的时候,在前东家做 Intacct 的一个项目,Intacct 的 CTO Aaron Harris 对我的其他评价我现在已经记不清了,但是 “Poker face” 我至今都还记得很清楚,形容得相当精准,翻译成中文的话,我想最接近的应该是「面瘫」。

    去年参加了几次培训,遇到了一群全都不是工程师的人,第一天的时候我如坐针毡脸上自然也是 Poker 状,当然后面几天也没比第一天好到哪儿去,回来之后,有位同学看到我时不时在朋友圈里讲冷笑话,说:「哦,原来你不是我想象中的那种工程师。」

    其实,工作和生活中都有很多很好玩儿的事情,谐音、双关、翻译、重复、断句、曲解、自黑,处处都是脑洞,我还能记起来最早亲历的冷笑话,比我被称作 Poker face 还要更早一些,是同事们教老外 BA 学汉语时说,立春,意思就是 Standing Spring,他们还把公司的中文名字「华美汉盛」翻译成 “China Beauty Handsome”,正是这些好玩儿的事情,让我时刻不能放松学习的工作和生活更多了些趣味。

    最近我快三岁的女儿开始尝试自行解释一些她可能还不明白的词,比如因为大人长的大的所以叫大人,长的高就叫高人,长的小就叫小人,妈妈扫地扫的好所以叫扫地师,好像也很有道理的样子;再比如妈妈比较喜庆所以叫喜羊羊,爸爸走的慢所以叫慢羊羊,她自己很美所以叫美羊羊。

    我也自行解释一下我搞不明白的一个词:严肃活泼,那就是一本正经讲笑话,嘻嘻哈哈过难关,劳逸结合把事儿办。

    说起来汗颜,我前几天才刚刚读过一遍周爱民老师的《大道至简》,好书就是这种清清楚楚地把我已经知道、甚至已经在实践的事情再简洁地解释一遍,把我虽然有体悟但还有点模糊的道理一针见血地指出来,比如谈到到士气「三鼓而竭」这个话题,他说不认可甚至否定「积极、主动、敏锐、勇敢、主见」这些良好品质,是大多数公司无效率无创新的根源,「想法好不好」是技术问题,但态度是要认可的。恰好在几个月前,我觉得某个同事的想法太超脱实际而不认可他的那些主意,但同时也在无意中打击了背后的良好品质,读到这里,我真是直冒冷汗,这关乎中二,关乎眼界,关乎眼界太窄导致了中二。

    最近两年多我个人最大的一个变化是,我在工作和生活中可以越来越坦然地承认和面对自己过往的错误,并在自黑中纠正,但在更早的时候,害怕犯错、害怕面对已经发生了的错误的确给我带来过很大的压力,要我说,以玩笑的态度的去释放压力,在这个过程中给了我最大的帮助。

    March 06, 2016 09:22 PM

    @khsing

    油猴脚本加载微信公众号的图片

    微信公众号的文章图片使用了 Lazy Load 模式,导致使用 Evernote Clip 剪贴的时候就没有图片,这里有一个 Weixin Image PreloadUserScripts。Safari上需要安装一个 NinjiaKit的扩展。

    by khsing at March 06, 2016 09:14 AM

    February 27, 2016

    @xupeng

    最容易被忽视的,是常识

    同事最近在拆分数据库和清理数据,这当中有一些趣事,比如在拆分一个叫 luz 的集群时,新拆出的集群被命名为了 lua,可以从至少两个角度来理解这个名字,最显而易见的它是一门语言,除此之外它还代表从 z 到 a 的新一轮轮回;再比如拆分另一个叫 eag 的集群时,新集群被命名为 eager,不过它诞生时的含义其实是「eag 的 er 砸」。

    也有一些哭笑不得的问题,比如发现有些应用的数据清理 cron 曾经有日子没被成功执行,导致数据文件的体积相比它应有的大小暴涨了一个数量级;还有比如发现 Sentrynodestore_node 表涨到了几百 GB,检查的时候看到 nodestore 的 schema:

    1
    2
    3
    4
    5
    6
    7
    
    CREATE TABLE `nodestore_node` (
        `id` varchar(40) NOT NULL,
        `data` longtext NOT NULL,
        `timestamp` datetime NOT NULL,
        PRIMARY KEY (`id`),
        KEY `nodestore_node_d80b9c9a` (`timestamp`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    它都有哪些问题呢?

    脱离业务场景,孤立地看这个 schema,除了这三点可疑之处外其实并没有太多值得挑剔的:

    1. Primary key 比较长(40 个字符),通常是一个不当设计的预警信号。
    2. 写入纪录的顺序和主键索引序可能不同,潜在的问题是影响写入性能,并可能导致数据页碎片化进一步影响读性能。
    3. timestamp 字段使用了 MySQL 的关键字。

    那么再了解一点点业务,通过阅读 Sentry 这部分的代码可以了解到这些:

    1. id 要存储的原始数据是 UUID version 4,16 字节,但在存储之前用 base64 编码为可打印字符串,编码后的长度为 24 字节。
    2. data 所存储的数据是把结构化数据序列化,之后用 zlib 压缩,再把压缩之后的数据使用 base64 编码为可打印字符串。
    3. timestamp 字段是数据写入时的时间,这个字段的索引用于按时间删除旧数据。

    考虑业务的需要,这个 schema 还有哪些问题呢? id 字段使用了 utf8 编码(在 MySQL 中是 1-3 字节长度的变长编码),最大长度是 40 字符,id 字段是主键,在索引中以最大宽度对齐,再加上 varchar 类型最大长度标示 2 字节,也就是 40 * 3 + 2 = 122 字节,不仅在主键中如此,在二级索引 nodestore_node_d80b9c9a 中也是如此。

    那么怎么改进呢?

    1. 由于业务上 id 是 16 字节 的 UUID version 4,但编码为 24 字节的可打印字符串,因此在不修改业务代码的前提下,可以对业务透明地把 id 列的定义修改为 id char(24) CHARACTER SET latin1 NOT NULL,这样在索引中的宽度就可以从 122 字节减小为 24 字节。
    2. 如果对业务代码做小幅重构,可以使用 binary(16) 来存储 UUID version 4,可以进一步减小为 16 字节。
    3. data 字段所存储数据的长度大多分布在几 KB 到几十 KB 之间,以 20KB(20480) 为例,base64 编码之后的长度为 27308,比未编码数据增长了 33+%,如果可以牺牲对人类的可读性(实际上人类也直读不了 base64 编码的字符串),直接存储 zlib 压缩之后的二进制数据,就可以省掉这 33% 的空间浪费,这一部分的浪费在整个系统中所占的比重相当可观。
    4. 在 Sentry 的场景下,nodestore 是典型的写多读少,如果再加入一列自增列作为 primary key,把 id 改为有唯一性约束的二级索引,可以提升写入性能、减轻数据页的碎片化,同时还能进一步节省空间。
    5. 使用自增列(记作 dummy_id)作为 primary key 之后,在这个场景下 timestamp 字段实际上和 dummy_id 同序,按时间删除旧数据的需求就可以不必借助 timestamp 字段的索引,使用笨笨的二分法找到需要的时间边界,然后按对应的 dummy_id 作为条件来删除即可,每行纪录可以节省 24 字节。

    做到这些有多难呢?

    回顾一下上面所提到的问题和相应的优化手段,可以发现所需要的只是在理解业务的基础上,对数据库的工作方式也有基本的理解,但更实际的情况是,大量的产品开发者在编写 Model 代码时随手就会写下 max_length=255,完全没有意识到产生的列定义会是 varchar(255),或者压根儿没有意识到这么做会有什么影响,几年前我自己在做产品开发的工作时也是这样的习惯。相对来说,我愿意相信这里写了 max_length=40 而不是 max_length=255 是一个经过深思熟虑了的决定。

    要做到对数据库和索引的工作方式有基本的理解,难吗?很多同学会觉得不就是读一读文档吗没有什么技术含量啊,事实也正是如此,只要能阅读和理解文档,加上必要的动手实践,都能有超越类似场景要求的理解,比掌握一门语言要简单太多,既不需要高于普通人的智商,也不需要加班加点地埋头苦干,所需要的仅仅是踏实的态度和一点耐心,再加上一点思考。

    再举个例子

    这是随手从某著名产品中摘出的 schema,就不在这里做更多的问题分析了,不过我相信仅仅依靠上面提到的几点常识,就能看到很多问题,这多多少少能进一步说明,优秀的产品一样会有糟糕的实现,但是,这些产品不都好好的是吗?是不是应该再思考一下技术的价值,以及技术和产品的关系呢?😂

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    
    CREATE TABLE `storage_blobs` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `oid` varchar(255) NOT NULL,
        `size` big