如何获得高并发经验

我把我以前的回答整理了一下,炒个冷饭,凑个数吧。

作为一个天天和高并发打交道的程序员,我并不觉得一定要有高并发实际项目经验才能做高并发,有些完全没有实际高并发经验的人,没准上手也能做的很好。但也很有可能上来就塌了。高并发只是一个不确定的结果,并不是过程。为什么我说是不确定呢?在来自全人类的高并发访问面前,一切都有可能发生,所以我们经常能看到顶级网站的颤抖。我把我觉得有用的东西汇集到一起,希望能对大家有帮助。

首先,我觉得基础知识非常重要,这包括算法,操作系统,jvm,数据库,缓存,多线程等等,其实这都是独立而又关联的知识。书本里都有,但理论要结合实际,一定要联系到具体的技术才会有用。但也别迷信任何技术,比如说使用了netty就能比谁谁谁快几十倍,但这有两个前提,一个是netty适合你的应用场景,另一个是你用netty用的合理。也别只痴迷于框架,框架只会挡住你的眼睛,让你觉得什么都不重要。大并发面前,没一个框架靠得住,靠得住的只有人,是人来根据具体的应用场景,使用各种知识去解决具体的问题。

一个后端程序员最重要的技能是分布式系统设计,这是经验和知识的结合,或者说就是用前面提到的基础来搭积木。编程语言是不重要的,但有那么几个语言在高并发应用方面积累了非常多的宝贵经验,比如说java,scala还有新兴的go。

这里最常见的就是如何分片sharding和负载均衡load balancer。为什么要分片和负载均衡呢? 因为一台机器你再怎么玩,能力也是有限的。很多人都知道都知道更大的并发需要更多的服务器,这么多的服务器怎么分工,就是分片和负载均衡。这听起来还是挺容易的,做起来也不难。

有时候你的分布式系统很可能加不了那么多服务器,这就是所谓的scalability,这是我们在项目伊始就要多加注意的地方。但这东西有个平衡,高的scalability不是没有代价的。我以前给人家讲课的时候,常讲一个例子,如果你设计一个自家厨房,你肯定只设计一个洗碗的水池对不对?平时绝对是够用的,但是如果你有一天请20个朋友来你家吃饭,吃饭大家围着桌子一起吃非常快,但你发现洗碗就scale不上去了,派再多人洗碗也没用,最多同时只能一个人在洗碗,这就成为你家接待能力的瓶颈。但家里厨房并不是为接待20+个朋友设计的,搞太多水池是个累赘。这就需要权衡,没有一定对的设计。

All Time Favorites - highscalability.com
https://www.mullie.eu/why-your-code-doesnt-scale/www.mullie.eu图标

How to make your code scale · Matthias Mullie

How to make your code scale · Matthias Mulliewww.mullie.eu图标

所以并没有一种高并发设计可以打遍天下无敌手,google, twitter, amazon, facebook, linkedin都有自己的应用场景,有自己的实际需要,有自己的权衡,有自己的技术特点。有一得就必有一失,比如说google和uber使用go来解决起自身的特殊需要和已经产生的问题,但是go对你的团队来说可能仅仅是个略显丑陋的普通语言。你去照搬人家微服务的设计,很可能还不如老老实实用个spring mvc + mysql

“这里并没有什么所谓的顶点,我们还仍然愿意为此挥拳“

------我忘了我在哪里看到了

所以我们去了解我们自己系统的特点,选择对应的技术,明白当前技术的得失。有兴趣的朋友可以看看

Eventual Consistency vs Strong Consistency

https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/cloud.google.com

高并发和scalability还不能离开高可用,你搞5w台服务器,但只要坏一台就全部服务都受影响肯定是不行的。你想如果1台服务器的可用性是99%,那如果你有100台,它们在一起每台都不坏的可用性就只有99%^100, 这个值只有36.6%。也就是说如果你有个100台机器的机房,每年大半时间都有机器在出问题。单纯的冗余并不能解决问题,如果有些服务坏掉或者重启,你需要能有一些应对和调整的策略,你需要让别的服务器知道哪些下游服务器可用,哪些已经挂了。这有很多的搞法,大家可以看看zookeeper。但像zookeeper这样的技术也不能过度使用,有些朋友把啥都往zookeeper里放,造成zookeeper成了系统的瓶颈,这就反而不美了。

这有还很多细节,比如说id怎么生成,你用一个mysql自增长的整数就会影响并发的能力,uuid生成也没那么简单,也要根据实际情况调整。比如说你的数据怎么sharding,以后怎么扩容,可以看看一致性哈希,再结合前面id算法,可以给你带来很多思考。然后跨多个数据中心怎么办,如果是一个可写其他只读,那我怎么知道去哪个数据中心写,其实还是可以做在那个id算法里。这些我觉得也可以自学,网上公开的资料很多。关于ID的算法,我也是最近玩go,仿制twitter的snowflake id做了一个用乐观锁的分布式ID算法。

beinan/fastidwww.github.com图标

现在的高并发服务不单单是线上的服务,还包括很多线下的服务,比如说大数据,这个也是不能忽视的部分。数据处理又根据你的需要可以是实时的,实时的可以使用storm, twitter有一个新的实现heron,有更合理的架构,而且和storm api兼容。如果不是实时的,选择就更多了。

很多人可能会比较在意GC的设置,其实GC并不直接影响你系统的并发能力,它可能会影响到你系统的吞吐量和访问延时之间的关系,而且其实近年来jvm和go的默认GC设置已经很难让其成为系统的瓶颈了。

最后才是实操经验,其实这主要让猎头和hr觉得你行,因为你干过。但你具体行不行技术面试一聊就知道了,再好的公司也不是各个都行。国内做得好的可以多看看阿里、头条等,但我不知道他们具体并发多少。如果你前面那些基础好,去阿里和头条不会太难,去一个核心点的组,就接触到了。或者可以看看twitter的技术博客也有帮助(要翻墙)。

https://blog.twitter.com/engineering/en_us.htmlblog.twitter.com

编辑于 2018-07-06

文章被以下专栏收录

    十七年来,我总是从技术社区汲取营养,却贡献甚少。年近不惑,突然想放下自己的羞涩和懒惰,把自己这些年来的技术故事写下来,可不敢说回馈社会,只为自斟自饮,一吐胸中块垒。正所谓外行看热闹,内行看门道,我这门道不多,热闹不少,我打算写十七个系列,现在这是第一个系列,关于后端。