转载下
@陈萌萌之前的答案:
我有 20 个整数,一把全装进内存,调用个 sort,完事了。
我有 2GB 那么多的整数,一把全装进内存……恩恩,如果机器不那么破,勉强也完事吧。
我有 20GB 那么多的整数,对,往你家 PC 里多插几条 8GB 的内存条试试?
那我现在有 200GB 那么多的整数……看你丫的怎么装内存,哈哈哈哈哈哈!
吓尿了吧!?写外排序?你写啊!It's ONLY the beginning!很多人可是连内存里的快排都写不出的哦~
好,现在有 200GB 的整数,排个序吧……呃,给你 10 台机器吧。如果数据不是 200GB,而是 2TB,2PB……
- 这 200GB 的整数,如何分配?
- 这 10 台机器之间如何通讯?没错,我不止坑了你去写外排序,我还得坑你去玩网络编程。
- 假设每一台机器上的数据都已经完全排好,如何多快好省地把各自排序好的结果 merge 在一起?
- 如何设计有效的 merge 逻辑减少 10 台机器之间的网络IO。
- 别以为 10 台机器不需要维护,万一在排序的时候其中一台机器挂了,怎么办?具体包括但不限于:他在挂之前有响应其他机器发给他的 request 吗?他在挂之前自身的任务完成了多少了?假设这台机器在挂的时候正在跟隔壁的机器互相传输数据肿么办?
- 谁去监听这 10 台机器的健康?或者是其他机器怎么知道某台机器挂了?如果是连接超时,怎么知道是网络阻塞还是目标机真的挂了?
- 如果某台机器真的挂了无法恢复,又或者由于隔壁的黄大牛要打魔兽了劫走了一台(集群升级,集群中的节点被临时撤走的事常有哦),如何把那台机器上那 20GB 的数据分给其余的 9 台?
排序简单么?简单。
但是给很多数字排序就不简单了。
就拿淘宝来说说,当作给新人一些科普。
先说你看到的页面上,最重要的几个:
【搜索商品】——这个功能,如果你有几千条商品,完全可以用select * from tableXX where title like %XX%这样的操作来搞定。但是——当你有10000000000(一百亿)条商品的时候,任何一个数据库都无法存放了,请问你怎么搜索?这里需要用到分布式的数据存储方案,另外这个搜索也不可能直接从数据库里来取数据,必然要用到搜索引擎(简单来说搜索引擎更快)。好,能搜出商品了,是否大功告成可以啵一个了呢?早着呢,谁家的商品出现在第一页?这里需要用到巨复杂的排序算法。要是再根据你的购买行为做一些个性化的推荐——这够一帮牛叉的算法工程师奋斗终生了。
【商品详情】——就是搜索完毕,看到你感兴趣的,点击查看商品的页面,这个页面有商品的属性、详细描述、评价、卖家信息等等,这个页面的每天展示次数在30亿以上,同样的道理,如果你做一个网站每天有10个人访问,你丝毫感觉不到服务器的压力,但是30亿,要解决的问题就多了去了。首先,这些请求不能直接压到数据库上,任何单机或分布式的数据库,承受30亿每天的压力,都将崩溃到完全没有幸福感,这种情况下要用到的技术就是大规模的分布式缓存,所有的卖家信息、评价信息、商品描述都是从缓存里面来取到的,甚至更加极致的一点“商品的浏览量”这个信息,每打开页面一次都要刷新,你猜能够从缓存里面来取吗?淘宝做到了,整个商品的详情都在缓存里面。
【商品图片】——一个商品有5个图片,商品描述里面有更多图片,你猜淘宝有多少张图片要存储?100亿以上。这么多图片要是在你的硬盘里面,你怎么去查找其中的一张?要是你的同学想拷贝你的图片,你需要他准备多少块硬盘?你需要配置多少大的带宽?你们的网卡是否能够承受?你需要多长时间拷贝给他?这样的规模,很不幸市面上已经没有任何商业的解决方案,最终我们必须自己来开发一套存储系统,如果你听说过google的GFS,我们跟他类似,叫TFS。顺便说一下,腾讯也有这样的一套,也叫TFS。
【广告系统】——淘宝上有很多广告,什么,你不知道?那说明我们的广告做的还不错,居然很多人不认为它是广告,卖家怎么出价去买淘宝的广告位?广告怎么展示?怎么查看广告效果?这又是一套算法精奇的系统。
【BOSS系统】——淘宝的工作人员怎么去管理这么庞大的一个系统,例如某时刻突然宣布某位作家的作品全部从淘宝消失,从数据库到搜索引擎到广告系统,里面的相关数据在几分钟内全部消失,这又需要一个牛叉的后台支撑系统。
【运维体系】——支持这么庞大的一个网站,你猜需要多少台服务器?几千台?那是零头。这么多服务器,上面部署什么操作系统,操作系统的内核能否优化?Java虚拟机能否优化?通信模块有没有榨取性能的空间?软件怎么部署上去?出了问题怎么回滚?你装过操作系统吧,优化过吧,被360坑过没,崩溃过没?这里面又有很多门道。
不再多写了,除了上面提到的这些,还有很多很多需要做的技术,当然并不是这些东西有多么高不可攀,任何复杂的庞大的东西都是从小到大做起来的,里面需要牛叉到不行的大犇,也需要充满好奇心的菜鸟,最后这一句,你当我是别有用心好了。
因为你看到的,只是你看到的呀!
你没有从上帝的视角去看一下,在你点击某个按钮的一瞬间,全世界几千万人可能也在点同一个按钮!
Scale,scale!
Scale带来大量的直接开销,而这些直接的开销会带来大量的第二级的间接的开销,第二级的会带来第三级的……
比如:
你开始就一台服务器,做个小网站,会java或者python或者世界最XX语言就行,花了一天。
然后幸福的烦恼来了,流量上去了,你开始认真了,你就得想着,准备个热备份吧,那就有同步问题了,你那点Java知识就没啥用了,得找懂得数据库和服务器系统的人了。
然后流量继续增大,你发现服务器压力太大,得进行分布式了,搞个最简单的Master Slave模式,slave分流点读请求吧。这时候一般的服务器管理人员也不行了,得找一两个有分布式系统经验的人了。
然后流量继续增大,你发现简单的Master Slave也搞不定了,你需要更复杂的服务器集群,这时候你发现光管理这些服务的人就一大坨了,他们自己就能成立个部门叫Infrastructure。
这时你发现,你这么多机器,代码总不能让程序员自己一台台的登录上去部署吧,于是又得找专门的人,成立一个组,叫Deployment。
然后你发现,这么多机器,现在除了和外面的用户通信,自己之间也要互相通信,也要做AAA(Authentication,Authorization,Auditing),也要做很多和外面用户请求没啥关系的脏活累活,于是你把原来做网站的人分了两组,一组叫后端,一组叫前端。
然后你发现你的程序员太多了,需要好多内部开发的工具,比如搜代码的,比如搜办公室的,比如内部通讯的,于是你又得雇一大堆人做Internal Tools。
由于你完美的管理,网站流量继续增大,你发现一个服务器集群都不够,你得开专门的数据中心了,于是你又得买地,又得雇一帮运行维护人员维护数据中心。
然后你发现你的员工实在太多了,人的管理成了新的头痛,于是你需要专门的HR部门,财务部门,法务部门,于是你的员工变的更多了……
然后你发现你的员工实在太多太多了,你得雇一大批为这些干正事的员工服务的人员,比如清洁工,厨师,保安,shuttle司机,前台招待,托儿所老师……
……
……
最后你发现你做了一个按钮,似乎只用到了一个前端,
然后为了能让这个按钮同时被几千万人用,后面需要2个数据中心,2000台机器,200个后端,50个QA,100个Infra,100个Deployment,200个运维 ……
然后为了能让这些人正常上班,后面需要100个Internal tools,100个保安,50个HR,20个财务,20个法务,20个shuttle司机,50个厨师,100个清洁工,20个前台招待,10个托儿所老师 ……
说了这么多,
最后你,作为一个用户,所看到的,当然只有那个“看起来不太复杂”的按钮了……