月度归档:2016年03月

Android Studio常用快捷键

[Android Studio] Android Studio常用快捷键

(会持续更新)这边讲的常用快捷键是指做完Keymap到Eclipse后的,不是纯Android Studio的,这边主要讲下比较常用的一些快捷键:

Ctrl+O:快捷查找当前类中的函数,变量

Alt+Enter:导入包

Ctrl+E:查看最近打开过的文件

Ctrl+Shift+E:查看最近编辑过的文件

Ctrl+G / Ctrl+Alt+Shift+G:查询变量或者函数或者类在哪里被使用或被调用,后者是前者的复杂表现,可以选择查询范围等。

Alt+H:查找功能,全局查找

F4:查看类继承关系

F2:查看文档说明(函数使用说明)

double Shift:全局查找,这个查看和Alt+H稍稍有些不同,这个是全局文件查找,到文件名称层面。

Ctrl+Shift+R:快速定位到你所想打开的文件。

Ctrl+K:选中一个变量后,快速定位到下一个使用该变量的地方(不过这个快捷键现在还存在一些bug,具体请看:Android Studio keymap到Eclipse后,查找下一个相同变量快捷键Ctrl+K失效

Alt+↑:光标所在位置那行代码往上移动

Alt+↓:光标所在位置那行代码往下移动

Ctrl+D:删除光标所在位置那行代码

Ctrl+X:剪切光标所在位置那行代码

Alt+Shift+↓/Ctrl+C:复制光标所在行代码到下一行

Ctrl+Shift+R:修改名称

Alt+←:后退,定位到上个查看或者编辑的地方

Alt+→:往前定位,比如你定位到上个点后,想回去,就可以用这个快捷键

Ctrl+/:当行注释,反注释再按一次即可

Ctrl+Shift+/:模块注释,反注释再按一次即可,注意这边的”/“不能用小键盘的

Ctrl+Shift+小键盘/:折叠代码(Ctrl+Shift+小键盘*这个不灵了,今天没空了,后面会针对这个问题做解决,并更新上来),当然笔记本没小键盘,你可以自己改快捷键

Ctrl+Alt+S:打开settings界面

Ctrl+Alt+Shift+S:打开Project Structure界面

Alt+Shift+X:运行(Run)

Alt+Shift+D:调试运行(Debug)

Ctrl+F9:编译工程

Ctrl+Shift+K:push文件到Server(git)

Debug类快捷键

F5:但不调试进入函数内部。

F7:由函数内部返回调用处。

F8:执行到下一个断点,没断点则执行完成。

Ctrl+Alt+F8/双击鼠标:直接查看选中位置的值,这两个快捷键稍稍有点区别,具体区别请看这:Android Studio 调试过程中快捷查看断点处变量值(Ctrl+Shift+I无效)?

这里有一个Android Studio的新的快捷功能,查看当前类中有哪些函数变量没被用到,哪些写法不合理。Eclipse没有的,很有用,下图中Inspect Code with Editor Settings就是是,你可以自己配置你所想用的快捷键,配置过程中,如果发现你想配置的快捷键被使用了,怎么看明白和哪些冲突,怎么解决,请戳这:Android Stuido如何查看快捷键冲突?

分类: Android Pro

摘自:http://www.cnblogs.com/0616–ataozhijia/p/3870064.html

这些小工具让你的Android开发更高效

本文为作者「Tikitoo」投稿,应该多少受我点影响,Tikitoo也是一位自学的Android工程师,并且完全通过自学找到一份还不错的工作。互联网爱好者,并且是简书专题的运营者,点击「阅读原文」可以跳转到作者的博客。

在做Android 开发过程中,会遇到一些小的问题,虽然自己动手也能解决,但是有了一些小工具,解决这些问题就得心应手了,今天就为大家推荐一下Android 开发遇到的小工具,来让你的开发更高效。

1. Vysor

Vysor 是一个可以将手机的屏幕投影到电脑上,当然也可以操作,当我们做分享或者演示的时候,这个工具起到了作用。

2. Vector Asset

Android Studio 在1.4 支持了VectorAsset,所谓VectorAsset;它可以帮助你在Android 项目中添加Material Icon 和SVG 图片来作为一个Drawable 资源来使用。不过唯一一点的缺陷就是没有搜索功能,如果你想精心挑选Material Icon ,可以打来网页版来选择,也可以下载SVG 和Png 格式。对于VectorAsset 的好处,它的文件更小,更容易适配不同的屏幕。

3. Stetho

Stetho 是一个Android 开发调试小工具,它可以让你使用Chrome Develop Tools 来可以来查看Sqlite 数据库和SharePreferences,而且可以查看网络连接的数据。在Chrome 输入框输入「chrome://inspect」,点击inspect 就可以开始了。如果使用OkHttp 需要添加拦截器StethoInterceptor。

4. OctoTree

OctoTree 是一个浏览器插件,它可以让你在Github 看代码时,左边栏会出现一个树状结构,就像我们在IDE 一样。当我们看一个项目的结构,或者想看具体的某个文件,这样就会很方便。

5. Chrome ADB

Chrome ADB 是一个使用Chrome 来调试Android 的小工具,它除了提供了安装,卸载,清理数据的基本功能,而且还提供了主页,返回,锁屏的虚拟键功能,也可以看各个应用占用的内存(不得不点名批评一下微信,关闭都还占用100M 内存,不知道你要干嘛)。它还有Android 的App,两者交互一定更有意思。

6. TinyPng

TinyPng 是一个图片压缩工具,可能有些人感觉这个工具应该给设计师使用,我觉得也是。不过有些时候,设计师给你出了个1920* 1080 的启动页,一张图片,1M 左右,我也是泪奔了,感觉设计师说话的时间,估计我们都压缩完了,自己动手,丰衣足食。而且它还提供了API,对不同语言都还有提供了插件,比如Java 就提供了Maven 的支持。

7. PostMan

PostMan 是一个API 调试工具,它提供Chrome App 和Mac App,除了提供基本的API 测试功能, 它还可以添加各种的Auth 认证,响应结果可以选择不同类型,比如HTML,JSON 等,可以设置通用的Header,还可以将之前测试的添加到一个集合,而且也可以同步到服务器,而且最近还添加了团队服务,想想服务器端写完测试你就能看到结果,而不是给你API 文档(当然API 文档还是要有的),这画面太美,我不敢想象。当然它的功能也远远不止这些,它还有专业版,想尝试更多的东西可以体验一下。

8. Genymotion 虚拟机

刚开始做开发的时候,每次使用官方的虚拟机,都想吐槽一下,但是发现了Genymotion 之后,这一切都变化了,它的速度几乎可以和真机媲美了,当然如果有真机,当然还是推荐使用真机测试。据说官方模拟器2.0 很快,不知道是不是又吹牛逼。

9. Json2POJO

Json2POJO 是可以将一个Json 字符串转换成Java 的POJO 类的网页工具,而且可以选择转换器,比如我们使用Retrofit 可以选择Jackson,Gson,而且可以选择重写get,set 方法,还有hashcode,equals 和toString 方法,可以省去了不少手写的时间。

10. Android Pixel

AndroidPixel 是一个简单的将不同的分辨率的换算工具,只要你有一个尺寸的大小,其他的尺寸大小就可以得出,当然dp 这样的单位,可以解决一部分问题,但是大多还要需要微调,这时AndroidPixel 就起到了作用。这个工具来自上一个公司同事告诉我的。

11. Android Arsenal

Android Arsenal 主要是推荐Github 上一些流行的Android 开源项目,基本上最近热门的Android 开源项目都会出现在这里,它还对不同类库进行了分类。

12. AndroidAssetStudio

Android Asset Studio 是一个在线制作工具,它可以制作Iocn,ActionBar,点9 图等等,简单的操作,大大提高了我们开发的效率。

13. WiFi ADB

WiFi ADB 是一个通过无线网络来使电脑和手机连接的手机App(可以去Google Play 搜索类似的),当我们做测试的时候,只需在手机上打开,电脑只需在命令行输入「adb connect xxx.xxx.xxx.xxx:5555」,电脑可以连接手机,就可以通过无线网络来调试开发的应用。

14. ES Explorer

ES Explorer 是一款文件管理器,但实际它又不仅仅是一款文件管理器,在获得Root 之后,它的功能更强大了,它可以浏览受限制的文件目录;而且提供了一系列小工具,比如下载器;还有集成了众多云储存服务。

微信公众号不支持链接,可以点击「阅读原文」查看。

友情提示:

之前的书籍奖励的两位同学「纪红阳」、「.」,没错,第二个中奖的用户微信名称就是一个点,不知道你们给我回复了收获地址被淹没了还是压根忘记回复了,请加我微信吧「stormzhang」,微信好友已经太多了,其他人一概不加,忘见谅!

 

摘自:http://mp.weixin.qq.com/s?__biz=MzA4NTQwNDcyMA==&mid=402858357&idx=1&sn=5dd38f4dcc5d7680e6daf7b3d1105b63#rd

成功者是如何战胜生命中的忧虑?

繁重的生活、工作压力让每个人都能感受到情绪的存在,人们都想摆脱不良情绪,却在很多时候都被情绪牵着鼻子走。如何能够面对现实,活得开心?今天“读写客”推荐美国成功学大师戴尔 · 卡耐基文章,探讨人性的优点与缺点。

1871年春,一个年轻人拿起一本书,书中21个词汇对他的未来产生了深刻的影响。他是加拿大蒙特利尔综合医院的一个学生。他为期末考试烦恼,为无所事事烦恼,为何去何从烦恼,为怎么实习烦恼,为如何谋生烦恼。

得益于1871年读过的那21个词汇,这位年轻的医学院学生成为他那一代人中最有声望的内科专家。他创建了蜚声世界的霍普金斯医学院,他成为剑桥大学的皇家教授——那是大英帝国授给医学界人士的最高荣誉。他被英国国王封为爵士。他去世时,关于他生平事迹的书籍足有整整两卷,长达1466页。他是威廉·奥斯勒爵士。1871年春他读过的那21个词汇出自托马斯·卡莱尔,这些词汇让他在此后的人生中远离了烦恼:“我们的主要任务不是遥望远方的黑暗,而是关注于眼前。”

42年后一个微风和煦的晚上,耶鲁校园里的郁金香迎着春风盛放,就是这个人——威廉·奥斯勒爵士,对耶鲁学子们发表演说。他告诉这些学生,像他那样一个任教于四所大学、写过一部畅销书的教授,理应有一个“卓尔不凡的大脑”。他宣称,事实并非如此。他说,熟悉他的人都知道,他的脑子“平庸之极”。

那么,什么才是他的成功秘诀呢?他解释说,他的成功归功于他所说的活在“日密舱”里。这话怎么讲?在耶鲁演讲前几个月,威廉·奥斯勒爵士搭乘一艘邮轮横渡大西洋。船长站在驾驶舱里,按动一枚按钮——机器“叮当”一声,瞬间变戏法似的,轮船一些部件立即纷纷关闭,然后轮船进入“水密舱”。

“现在,你们每一人——”威廉·奥斯勒博士对这些耶鲁学子说,“你们每个人的身体都是一部比巨型邮轮更了不起的组织,航程也更远大。我要告诫你们,学会控制,生活在‘日密舱’,这才是航行最安全的保障。去驾驶舱看看,至少确保主要隔水舱运行正常。

在你人生的每一个阶段,按一下按钮,把“过去”——死去的昨天关在外面;接着,按另一个按钮,一个金属舱壁再次关上,那是“未来”——还未诞生的明天;这样你就安全了——你的今天就安全了!

把未来关闭得和过去一样严严实实吧……未来就是今天……永远就没有个什么明天。人类的救赎就在今天。一个对未来担惊受怕的人,精力的损耗、内心的压力和精神上的烦恼会像咬尾的蛇一样紧追不舍……那么,将过去和未来的大水壁关闭了,养成这样一种习惯——活在当下的‘日密舱’中!”

奥斯勒博士的意思莫非是我们完全不必为了明天而未雨绸缪?不,完全不是。在那场演讲中他接着说过,对明天最好的准备方式就是集中你们所有的智慧和热情,把今天的事情做得无可挑剔。这是迎接明天唯一最可行的办法。

在耶鲁大学,威廉·奥斯勒爵士呼吁学生按耶稣基督祷告的那样开始每一天:“把今天的面包给我们。”

记住,这句祷文只要求今天的面包,而没有抱怨我们昨天吃下去的旧面包,也没有说:“主啊,近来小麦带干旱,可能还会干旱,明天秋天我可去哪儿找面包啊?——或者我要是失业了,主啊,我去哪儿找吃的啊!”

没有,这句祷文只教诲我们找今天的面包。因为,今天的面包可能是你唯一能吃到口的。

多年前,一个身无分文的哲学家在一片贫瘠的土地上晃荡,那儿的人生活得很艰辛。一天,人们在一座山丘上围绕着哲学家,他发表了一场演说,在人类历史上其引用率可能空前绝后。他的演说包含26个词汇,回荡了几个世纪之久:“不要去想什么明天,因为明日自有明日的想法,活好今天才是正道。”

很多人反对耶稣的这句话:“别想明天的事情。”他们将这句话斥之为完美建议和神秘主义。他们说:“为了保护家人,我必须买保险;为了养老,我必须攒钱;未来将来,我必须早做打算。”

没错!你当然必须。实际上,耶稣这句话是300年前翻译的,在詹姆斯王朝时的意思和今天的意思并不一样。300年前,thought这个词的意思常常指anxiety(焦虑、忧虑)。现代版《圣经》对耶稣这句话的引用更为准确:“别为明日忧。”

是的,无论如何,想着明天;为了明天未雨绸缪,但别因为明天而烦恼。

第二次世界大战期间,我们的军事领导人为明天做了谋划,但他们无法承受烦恼之重。

“我为最好的将士配备了我们所能提供的最好武器。”指挥美国海军的欧内斯特·J.詹姆斯上将这样说,“还给了他们执行使命的最佳方案,我能做的就是这些。”

“如果一艘舰艇被击沉。”欧内斯特·J.詹姆斯上将接着说,“我没办法把它打捞起来。如果一定会沉没,我也束手无策。我能更有效地为明天的事情工作,而不是为昨天的事情懊恼不已。另外,如果我任由那些烦恼缠住我,我也扛不住。”

无论战争时期还是和平时期,乐观思维和悲观思维最大的区别在于——乐观思维能理顺事情的前因后果,取得符合逻辑、建设性的计划;悲观思维则经常引起紧张和神经崩溃。

我荣幸地采访过阿瑟·海斯·苏兹伯格,1935到1961年间,他是世界上最有影响力的报纸之一《纽约时报》的出版人。苏兹伯格先生告诉我,当“二战”硝烟弥漫欧洲时,他惊慌失措,对未来太焦虑,以至于几乎无法入眠。他常常半夜起床,取出画布和油画笔,看着镜中的自己,试图画一幅自画像。其实他根本不会画画,但为了驱逐焦虑,还是画了。苏兹伯格先生告诉我,他从来无法祛除他的焦虑,直到他将一首赞美诗中的词汇作为自己的座右铭——“一步对我足够”。

光明指引……

我紧随你的脚步:

我勿需眺望远景;

一步对我足够。

大约同一时间欧洲某个地方,一个穿军服的年轻人也学到了人生这一课。他的名字叫特德·本杰明诺,来自马里兰州的巴尔的摩,他的焦虑使他患上了一级战斗疲劳症。

“1945年4月。”本杰明诺写道,“我的焦虑发展到了医生所说的‘痉挛性结肠炎’——那是一种能引起剧烈疼痛的病。如果战争不是那时结束,我整个人肯定早就垮了。”

本杰明诺接着说:“我当时已经筋疲力尽了。我是墓地登记员,隶属于第94步兵师,是没有军衔的那种军官。我的职责就是对在各项行动中所有阵亡、失踪和负伤住院的人员建立档案,并保存这些记录。我还必须协助把那些在战斗最激烈时阵亡后匆匆浅埋的军人尸体——无论是盟军还是敌军的,挖出来进行深埋。我还必须将阵亡军人的个人物品收集起来,负责寄送给他们的家人或近亲;对这些物品,他们非常珍视。

我担心不停,生怕出什么纰漏,引起尴尬。我担心我能否完成这任务。我担心我能不能活到抱一抱我那唯一的儿子的那一刻——他才16个月大,我还没见过呢。我焦虑和疲惫得体重掉了34磅。我狂躁不安,距疯掉只一步之遥。我看着自己的双手,发现它们简直就是皮包骨。一想起回家时成了个废人,我就魂飞魄散。我崩溃了,像孩子似的哭泣。我脆弱极了,一旦独处我就泪流满面。在巴尔吉战役后不久的那一阵,我哭得太多了,连做一个正常人的希望都差点放弃。

“最后我去了部队医院,一位军医给了我一些建议——这些建议彻底改变了我的生活。在做了彻底体检后他告诉我,我的问题是心理上的。他说:‘特德,我希望你把自己的生命看成一个计时沙漏器。你知道,在沙漏器顶部有不计其数的沙粒,所有沙粒都会缓慢而均匀地穿过容器中部的狭窄瓶颈;除非把沙漏弄坏了,你我没有任何办法能多让一粒沙子经过瓶颈。你,我,或任何别的人,都像沙漏器一样。每天早上一起床,我们会觉得有几百个任务需要当天完成;然而,如果我们不按部就班一个一个地来——就像沙粒通过沙漏器的瓶颈一样,慢慢地来,有条不紊地来;不论我们的身体还是心理,都会垮掉的。’

“自从军医给我上了这堂难忘的课那天后,我便开始践行这些哲学。‘一次一粒沙……一次一件事’,这个忠告在战争期间不仅挽救了我的身体,还挽救了我的心灵;对我目前在广告印务和平面印务公司担任的公共关系和广告经理这个职务,也很有帮助。我发现,那些战争时期出现的问题,在职场中同样出现了:太多事情需要马上处理——而时间却太紧。

譬如,库存太低,新表格需要填写,进货需要安排,地址要修改,办公室开张关张,等等。我记起那位军医的话‘一次一粒沙……一次一件事’,才没有方寸大乱。通过不断温故这句话,我以一种有效得多的方式完成了任务,那种在战场上差点毁了我的迷茫和紊乱感烟消云散。”

关于当代生活方式,最令人瞠目结舌的观点之一是:我们的医院一度把一半病床留给了各种精神和心理病人——无数个“昨天”累积起来的千钧重压和令人忧惧的“明天”,终于将这些人压垮。然而,这类病人绝大部分原本并不需要住院,他们原本可以过着幸福有意义的生活——如果他们一早就知道耶稣所说的“别为明日忧”或者威廉·奥斯勒爵士说的“活在日密舱”的道理。

此刻,你我正好同时站在两种永恒的交会点:不堪回首的浩瀚而永恒的历史以及连通永恒的未来。我们不可能置身一种永恒里——不可能!甚至不可能活在被分割的一秒钟之内。如果非要去折腾,必然身心俱毁。所以,还是知足常乐,活在我们唯一能够存在的时间内:从现在起,直到上床就寝。

罗伯特·路易斯·斯蒂文森这样说:“无论负担多么沉重,任何人都能撑一天;无论工作多么艰难,任何人都能坚持一天;从朝霞到日暮,任何人都能生活在甜蜜、耐心、珍爱和纯洁之中。这就是生活的全部要义。”

是的,这就是生活对我们的要求。但对于密歇根州萨基纳多的E.K.谢尔兹太太而言,在学会“活在今天”之前,她陷入了绝望——甚至处于自杀的边缘。谢尔兹太太向我讲述她的故事时,这样说道:

“1937年,我丈夫去世了。我极度抑郁——几乎不名一文。我给我的前雇主——堪萨斯市洛奇福勒公司的里奥·洛奇先生写了一封信,恢复了我以前的工作。以前我是以去乡村和小镇推销《世界百科全书》为生。两年前,我丈夫生病,我卖掉了我的汽车。恢复工作后,我想方设法凑齐了买一辆二手车的首付款。我曾以为,重操旧业有助于缓解我的抑郁症,但孤身一人开车,孤身一人吃饭简直让我难以忍受。有些地方生意不好做,我觉得很难赚够买车钱——尽管那也不算什么大钱。

“1938年春,我去密苏里州的维塞里斯卖书。那儿的学校很穷,路很旧。我如此孤独和沮丧,甚至想到了自杀。我的日子毫无奔头了,我恐惧明天早起面对生活。我担心一切:还不起购车款,付不起房租,吃不起饭,身体日渐垮了却看不起病……只有两个想法阻止了我的自杀:我姐姐会伤心欲绝,我没钱支付我的葬礼。

“后来的一天,我看到的一篇文章将我从沮丧里拽了出来,并给了我活下去的勇气。其中一句话非常鼓舞人,我永远不会忘记文章中这句话对我的恩典。这句话是这样的:‘对聪明人来说,每一天都是新生活。’我把那句话打印下来,粘贴在汽车挡风玻璃上,这样,开车时每一分钟都会看到。我学会了忘记昨天,也不想明天。每天早晨,我都对自己说:‘今天就是新生活。’我发现,每一次活过一天不算太难。

“我战胜了我的孤独恐惧,我的需求恐惧。现在的我很开心,对生活充满了热情和爱。我现在明白,无论今后生活怎么变幻,我都不会再恐惧了;我现在明白,我不必为未来恐惧;我现在明白,我能一次活好一天;我现在明白‘对聪明人来说,每一天都是新生活’的含义。”

底特律不久前去世的爱德华·S.伊文斯先生,在领悟“生活就是活在每一天、每一分钟的肌理中”这句话之前,差一点杀了自己。爱德华·S.伊文斯幼时家境贫寒,他挣的第一分钱是做报童,随后在杂货店打工。再后来,为了养活家里七个人,他去做图书馆助理管理员。尽管薪水少得可怜,他却担心丢掉饭碗。八年后,他终于鼓起勇气创业。

但一旦开始,他凭东拼西凑的50美元老本,仅在第一年就赚了两万美元!然后是一场变故,一场要命的变故。他为一个朋友做贷款担保,这个朋友却破产了。很快,祸不单行——他存款的那家银行倒闭了。爱德华除了将赚到的每一分钱全部亏掉,还倒欠一万六!他无法承受这个打击。

他告诉我:“我寝食难安,我很奇怪地得了一种病——焦虑症。焦虑,我的病完全是焦虑引起的。有一天当我走在街上时,走不动了,昏倒在人行道上。我被送到病床上,我身上长满了大疡肿。大疡肿向体内发展,直到我一病不起,备受折磨。我的身体一天天虚弱下去。最后,大夫告诉我只有两个礼拜可活。我吓坏了,写好遗书,躺回病床等待末日来临。现在,挣扎和焦虑都无济于事。于是,我放弃了,放松了,睡着了。此前几个礼拜,我没有一天睡满过两小时;现在呢,反正尘世间的一切都已了结,我睡得跟个婴儿似的。我的精疲力竭开始逆向发展,我的胃口回来了,我的体重居然增加了。

“几周后,我能拄着拐杖走路了。六周后,我就回去工作了。我曾经一年赚了两万美元,现在找了个每周付我30美元的工作我也很开心。我的工作是销售——汽车装船运输时,需要在车后轮上装阻隔物——我就卖那种阻隔物。我现在汲取了以前的教训。对过去,我无怨无悔;对将来,也从容坦荡。我将自己所有的时间、精力和热情全部倾注于销售工作中。”

爱德华·S.伊文斯的事业从此突飞猛进。几年后,他成为伊文斯产品公司老总,公司在纽约证券交易所上市好几年了。如果你飞临格陵兰岛,可能会降落在以他名字命名的伊文斯机场。当然,如果伊文斯不能领悟“活在‘日密舱’”的含义,他绝不会取得这些成就。

你可能会想起怀特·奎恩说过的那句话:“给你昨天的果酱,给你明天的果酱,但今天的果酱想都别想。”

此句话比喻那些永远无法实现的诺言和空头支票。

我们大多数人都喜欢为昨天耿耿于怀,为明天惴惴不安,却从来不抓住眼前的醇厚的“果酱”。

本文选自《人性:优点与弱点》,北京大学出版社

淘宝大秒系统设计详解

导读:最初的秒杀系统的原型是淘宝详情上的定时上架功能,由于有些卖家为了吸引眼球,把价格压得很低。但这给的详情系统带来了很大压力,为了将这种突发流量隔离,才设计了秒杀系统,文章主要介绍大秒系统以及这种典型读数据的热点问题的解决思路和实践经验。

一些数据

大家还记得2013年的小米秒杀吗?三款小米手机各11万台开卖,走的都是大秒系统,3分钟后成为双十一第一家也是最快破亿的旗舰店。经过日志统计,前端系统双11峰值有效请求约60w以上的QPS ,而后端cache的集群峰值近2000w/s、单机也近30w/s,但到真正的写时流量要小很多了,当时最高下单减库存tps是红米创造,达到1500/s。

热点隔离

秒杀系统设计的第一个原则就是将这种热点数据隔离出来,不要让1%的请求影响到另外的99%,隔离出来后也更方便对这1%的请求做针对性优化。针对秒杀我们做了多个层次的隔离:

  • 业务隔离。把秒杀做成一种营销活动,卖家要参加秒杀这种营销活动需要单独报名,从技术上来说,卖家报名后对我们来说就是已知热点,当真正开始时我们可以提前做好预热。
  • 系统隔离。系统隔离更多是运行时的隔离,可以通过分组部署的方式和另外99%分开。秒杀还申请了单独的域名,目的也是让请求落到不同的集群中。
  • 数据隔离。秒杀所调用的数据大部分都是热数据,比如会启用单独cache集群或MySQL数据库来放热点数据,目前也是不想0.01%的数据影响另外99.99%。

当然实现隔离很有多办法,如可以按照用户来区分,给不同用户分配不同cookie,在接入层路由到不同服务接口中;还有在接入层可以对URL的不同Path来设置限流策略等。服务层通过调用不同的服务接口;数据层可以给数据打上特殊的标来区分。目的都是把已经识别出来的热点和普通请求区分开来。

动静分离

前面介绍在系统层面上的原则是要做隔离,接下去就是要把热点数据进行动静分离,这也是解决大流量系统的一个重要原则。如何给系统做动静分离的静态化改造我以前写过一篇《高访问量系统的静态化架构设计》详细介绍了淘宝商品系统的静态化设计思路,感兴趣的可以在《程序员》杂志上找一下。我们的大秒系统是从商品详情系统发展而来,所以本身已经实现了动静分离,如图1。

图片描述

图1 大秒系统动静分离
除此之外还有如下特点:

  • 把整个页面Cache在用户浏览器
  • 如果强制刷新整个页面,也会请求到CDN
  • 实际有效请求只是“刷新抢宝”按钮

这样把90%的静态数据缓存在用户端或者CDN上,当真正秒杀时用户只需要点击特殊的按钮“刷新抢宝”即可,而不需要刷新整个页面,这样只向服务端请求很少的有效数据,而不需要重复请求大量静态数据。秒杀的动态数据和普通的详情页面的动态数据相比更少,性能也比普通的详情提升3倍以上。所以“刷新抢宝”这种设计思路很好地解决了不刷新页面就能请求到服务端最新的动态数据。

基于时间分片削峰

熟悉淘宝秒杀的都知道,第一版的秒杀系统本身并没有答题功能,后面才增加了秒杀答题,当然秒杀答题一个很重要的目的是为了防止秒杀器,2011年秒杀非常火的时候,秒杀器也比较猖獗,而没有达到全民参与和营销的目的,所以增加的答题来限制秒杀器。增加答题后,下单的时间基本控制在2s后,秒杀器的下单比例也下降到5%以下。新的答题页面如图2。

图片描述

图2 秒答题页面
其实增加答题还有一个重要的功能,就是把峰值的下单请求给拉长了,从以前的1s之内延长到2~10s左右,请求峰值基于时间分片了,这个时间的分片对服务端处理并发非常重要,会减轻很大压力,另外由于请求的先后,靠后的请求自然也没有库存了,也根本到不了最后的下单步骤,所以真正的并发写就非常有限了。其实这种设计思路目前也非常普遍,如支付宝的“咻一咻”已及微信的摇一摇。

除了在前端通过答题在用户端进行流量削峰外,在服务端一般通过锁或者队列来控制瞬间请求。

数据分层校验

图片描述

图3 分层校验
对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,如图3所示:在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:

  • 先做数据的动静分离
  • 将90%的数据缓存在客户端浏览器
  • 将动态请求的读数据Cache在Web端
  • 对读数据不做强一致性校验
  • 对写数据进行基于时间的合理分片
  • 对写请求做限流保护
  • 对写数据进行强一致性校验

秒杀系统正是按照这个原则设计的系统架构,如图4所示。

图片描述

图4 秒杀系统分层架构
把大量静态不需要检验的数据放在离用户最近的地方;在前端读系统中检验一些基本信息,如用户是否具有秒杀资格、商品状态是否正常、用户答题是否正确、秒杀是否已经结束等;在写数据系统中再校验一些如是否是非法请求,营销等价物是否充足(淘金币等),写的数据一致性如检查库存是否还有等;最后在数据库层保证数据最终准确性,如库存不能减为负数。

实时热点发现

其实秒杀系统本质是还是一个数据读的热点问题,而且是最简单一种,因为在文提到通过业务隔离,我们已能提前识别出这些热点数据,我们可以提前做一些保护,提前识别的热点数据处理起来还相对简单,比如分析历史成交记录发现哪些商品比较热门,分析用户的购物车记录也可以发现那些商品可能会比较好卖,这些都是可以提前分析出来的热点。比较困难的是那种我们提前发现不了突然成为热点的商品成为热点,这种就要通过实时热点数据分析了,目前我们设计可以在3s内发现交易链路上的实时热点数据,然后根据实时发现的热点数据每个系统做实时保护。 具体实现如下:

  • 构建一个异步的可以收集交易链路上各个中间件产品如Tengine、Tair缓存、HSF等本身的统计的热点key(Tengine和Tair缓存等中间件产品本身已经有热点统计模块)。
  • 建立一个热点上报和可以按照需求订阅的热点服务的下发规范,主要目的是通过交易链路上各个系统(详情、购物车、交易、优惠、库存、物流)访问的时间差,把上游已经发现的热点能够透传给下游系统,提前做好保护。比如大促高峰期详情系统是最早知道的,在统计接入层上Tengine模块统计的热点URL。
  • 将上游的系统收集到热点数据发送到热点服务台上,然后下游系统如交易系统就会知道哪些商品被频繁调用,然后做热点保护。如图5所示。

图片描述

图5 实时热点数据后台
重要的几个:其中关键部分包括:

  • 这个热点服务后台抓取热点数据日志最好是异步的,一方面便于做到通用性,另一方面不影响业务系统和中间件产品的主流程。
  • 热点服务后台、现有各个中间件和应用在做的没有取代关系,每个中间件和应用还需要保护自己,热点服务后台提供一个收集热点数据提供热点订阅服务的统一规范和工具,便于把各个系统热点数据透明出来。
  • 热点发现要做到实时(3s内)。

关键技术优化点

前面介绍了一些如何设计大流量读系统中用到的原则,但是当这些手段都用了,还是有大流量涌入该如何处理呢?秒杀系统要解决几个关键问题。

Java处理大并发动态请求优化

其实Java和通用的Web服务器相比(Nginx或Apache)在处理大并发HTTP请求时要弱一点,所以一般我们都会对大流量的Web系统做静态化改造,让大部分请求和数据直接在Nginx服务器或者Web代理服务器(Varnish、Squid等)上直接返回(可以减少数据的序列化与反序列化),不要将请求落到Java层上,让Java层只处理很少数据量的动态请求,当然针对这些请求也有一些优化手段可以使用:

  • 直接使用Servlet处理请求。避免使用传统的MVC框架也许能绕过一大堆复杂且用处不大的处理逻辑,节省个1ms时间,当然这个取决于你对MVC框架的依赖程度。
  • 直接输出流数据。使用resp.getOutputStream()而不是resp.getWriter()可以省掉一些不变字符数据编码,也能提升性能;还有数据输出时也推荐使用JSON而不是模板引擎(一般都是解释执行)输出页面。

同一商品大并发读问题

你会说这个问题很容易解决,无非放到Tair缓存里面就行,集中式Tair缓存为了保证命中率,一般都会采用一致性Hash,所以同一个key会落到一台机器上,虽然我们的Tair缓存机器单台也能支撑30w/s的请求,但是像大秒这种级别的热点商品还远不够,那如何彻底解决这种单点瓶颈?答案是采用应用层的Localcache,即在秒杀系统的单机上缓存商品相关的数据,如何cache数据?也分动态和静态:

  • 像商品中的标题和描述这些本身不变的会在秒杀开始之前全量推送到秒杀机器上并一直缓存直到秒杀结束。
  • 像库存这种动态数据会采用被动失效的方式缓存一定时间(一般是数秒),失效后再去Tair缓存拉取最新的数据。

你可能会有疑问,像库存这种频繁更新数据一旦数据不一致会不会导致超卖?其实这就要用到我们前面介绍的读数据分层校验原则了,读的场景可以允许一定的脏数据,因为这里的误判只会导致少量一些原本已经没有库存的下单请求误认为还有库存而已,等到真正写数据时再保证最终的一致性。这样在数据的高可用性和一致性做平衡来解决这种高并发的数据读取问题。

同一数据大并发更新问题

解决大并发读问题采用Localcache和数据的分层校验的方式,但是无论如何像减库存这种大并发写还是避免不了,这也是秒杀这个场景下最核心的技术难题。

同一数据在数据库里肯定是一行存储(MySQL),所以会有大量的线程来竞争InnoDB行锁,当并发度越高时等待的线程也会越多,TPS会下降RT会上升,数据库的吞吐量会严重受到影响。说到这里会出现一个问题,就是单个热点商品会影响整个数据库的性能,就会出现我们不愿意看到的0.01%商品影响99.99%的商品,所以一个思路也是要遵循前面介绍第一个原则进行隔离,把热点商品放到单独的热点库中。但是无疑也会带来维护的麻烦(要做热点数据的动态迁移以及单独的数据库等)。

分离热点商品到单独的数据库还是没有解决并发锁的问题,要解决并发锁有两层办法。

  • 应用层做排队。按照商品维度设置队列顺序执行,这样能减少同一台机器对数据库同一行记录操作的并发度,同时也能控制单个商品占用数据库连接的数量,防止热点商品占用太多数据库连接。
  • 数据库层做排队。应用层只能做到单机排队,但应用机器数本身很多,这种排队方式控制并发仍然有限,所以如果能在数据库层做全局排队是最理想的,淘宝的数据库团队开发了针对这种MySQL的InnoDB层上的patch,可以做到数据库层上对单行记录做到并发排队,如图6所示。

图片描述

图6 数据库层对单行记录并发排队
你可能会问排队和锁竞争不要等待吗?有啥区别?如果熟悉MySQL会知道,InnoDB内部的死锁检测以及MySQL Server和InnoDB的切换会比较耗性能,淘宝的MySQL核心团队还做了很多其他方面的优化,如COMMIT_ON_SUCCESS和ROLLBACK_ON_FAIL的patch,配合在SQL里面加hint,在事务里不需要等待应用层提交COMMIT而在数据执行完最后一条SQL后直接根据TARGET_AFFECT_ROW结果提交或回滚,可以减少网络的等待时间(平均约0.7ms)。据我所知,目前阿里MySQL团队已将这些patch及提交给MySQL官方评审。

大促热点问题思考

以秒杀这个典型系统为代表的热点问题根据多年经验我总结了些通用原则:隔离、动态分离、分层校验,必须从整个全链路来考虑和优化每个环节,除了优化系统提升性能,做好限流和保护也是必备的功课。

除去前面介绍的这些热点问题外,淘系还有多种其他数据热点问题:

  • 数据访问热点,比如Detail中对某些热点商品的访问度非常高,即使是Tair缓存这种Cache本身也有瓶颈问题,一旦请求量达到单机极限也会存在热点保护问题。有时看起来好像很容易解决,比如说做好限流就行,但你想想一旦某个热点触发了一台机器的限流阀值,那么这台机器Cache的数据都将无效,进而间接导致Cache被击穿,请求落地应用层数据库出现雪崩现象。这类问题需要与具体Cache产品结合才能有比较好的解决方案,这里提供一个通用的解决思路,就是在Cache的client端做本地Localcache,当发现热点数据时直接Cache在client里,而不要请求到Cache的Server。
  • 数据更新热点,更新问题除了前面介绍的热点隔离和排队处理之外,还有些场景,如对商品的lastmodifytime字段更新会非常频繁,在某些场景下这些多条SQL是可以合并的,一定时间内只执行最后一条SQL就行了,可以减少对数据库的update操作。另外热点商品的自动迁移,理论上也可以在数据路由层来完成,利用前面介绍的热点实时发现自动将热点从普通库里迁移出来放到单独的热点库中。

按照某种维度建的索引产生热点数据,比如实时搜索中按照商品维度关联评价数据,有些热点商品的评价非常多,导致搜索系统按照商品ID建评价数据的索引时内存已经放不下,交易维度关联订单信息也同样有这些问题。这类热点数据需要做数据散列,再增加一个维度,把数据重新组织。

作者简介:许令波,2009年加入淘宝,目前负责商品详情业务和稳定性相关工作,长期关注性能优化领域,参与了淘宝高访问量Web系统主要的优化项目,著有《深入分析Java Web技术内幕》一书。个人网站http://xulingbo.net