最近互联网都涨思维了,移动互联网更是得瑟地不行,在风口上嗷嗷地飘,PE/VC没事儿就就往那儿蹭,而那物流网的天儿还刚蒙蒙亮,这就是我们这些攻城狮所处的有点儿雾霾的时代。这年头攻城狮总有不寐的夜,为啥纠结呢?还不是让数据给闹的。这里一篇小文只是一盘关于数据的小菜,一款关于数据的管弦谱,怎么演奏,那得看自己,看情况,不解决啥实质问题,该闹还得闹,该纠结还得纠结,谁让你拱呢。
说俩词儿
数据库:就叫D吧,就是你可以把东西放D那儿,回头儿你还可以从D把东西拿出来。跟火车站旁边那个存包的一回事儿,而且也得要身份证,别忘了哈。
机构:提供一个或多个服务的一组机器,他们协同完成一大类事。
下面就唠点正嗑儿,说点行话吧。
问题的产生
任何存储介质,其存储容量总归是有限的。因此,随着业务的发展,甚至突发的业务高峰,水平扩展能力总是不可回避的挑战。这也必然要求数据是分布式存储的,而解决问题的基本指导思想也必然是分而治之,否则那电费、流量费恐怕就不知道翻多少倍了,要命的是生意没法做了,这年头慢的东西就会被淘汰。
数据路由概念
在分布式环境中,对于一个请求而言,总是要决策到哪里去读/写,这就是数据路由问题,也是一个基本问题。写操作决定了读操作,因此写操作中针对具体的设计目标如何分而治之就成为了问题的关键。但是反过来说也是正确的,读的需求决定写的方式,而且应该这样考虑,因为写的目的不仅仅是存在那里,更是要考虑读的过程如何发挥价值。换句话说,数据路由首先要解决写到哪里和如何写的问题,但它是为如何读而准备的。关于写的设计应当是服从于读的方式、方法、形式和策略。就像接力赛一样,你把接力棒放在前面队友的手里就是写,他接到了,跑了,就是读,当你递过去的时候你在想什么?对了,就是应该像你此刻那样想。当你在使用、架构或自研某种广义数据库的时候,你首先考虑接棒了吗?当然这个问题涉及面更广,这里仅仅侃侃“到哪里”的问题-雅名“数据路由”。老是做海底捞,憋不?别淹着,当是潜伏哈。
问题的内在特质与归结
设:
l 请求=R
l 服务=S,可以是一个服务实例,也可能是一个服务集群
显然问题可以归结为集合R到集合S的映射,数学上就是一个函数,f(R)=S。
要求对于任何特定的请求Rx,必须总是映射到特定的Sx,不论它们的元素如何变化,这就是问题的内在特质。你不能说,我存了个包在XX,到时候你让我到YY去取,取完了那警察来了你替我哈。
挑战
假定我们已经实现了一种规则可以完成R到特定S的映射,该规则就是数据路由要实现的,但是随着业务的发展,S必然会变大,这时候挑战就来了,怎样的规则才能动态地适应这种改变呢?这就是挑战所在。
数据在存储上有时会有一个要求,那就是要力求数据的均衡分布而不是Skew,这就意味着特定的S存储的数据需要再分配,这也内在地要求数据路由具备及时调整映射的能力。听着有点高大上,简单类比,可以这么说,想象一个二维坐标系,X轴是数据系统的所有硬盘,Y轴是各自保存的数据量,画一个曲线,如果它看上去像个心电图,那是有病啊,应该相对平直才好(跟现实相反哈)。你做架构的时候,在这点上,那就是要把它整地“没有生命体征”,一条线倍儿值,你厉害。拿HADOOP来说,要是BLOCK都集中在某些服务器上,其它都基本闲着,那就像一个人五官都纠结在一起,跟包子一样,美不?答案正确,软件设计的美与现实世界的美学它就那么任性地统一着。要不然,那结果就是小沈阳穿那苏格兰格裙的Style,跑偏了。
路由方式
通常路由都是通过制定一个这里统称为Key的东西来指路,不同的产品叫法不同,如Key, Rowkey, Field等等。无所谓,皮儿不同,馅儿是一样的。按照拱城狮看世界的极简风格来看,这个世界就是两根手指头就能表达,串和数,剩下的都是关系。这个Key,别管他穿啥马甲,里子就这两样。
完全映射
映射执行机构,即数据路由机构,包含R和S的所有元素,构成全映射。缺点在于需要更大的内存来提供高速的路由服务。并且要求快速地从大量的元素中找到特定元素。这就像你有点事到学校班里接你家少爷(假定你不知道在哪个班),到学校了,人家给你一摞花名册,你就一个名字一个名字地看,要是像字典一样排序了还好,但你也得扫一遍。这个比拟的要点在于,所有的名字都在花名册上,然后由一个具体的名字找到班级-119,最后人家告诉你119班在哪儿,看到没,“到哪里”,路由就是给你指路的警察美女,人家那服务最后就是一句话,给你指路,别没话找话哈。
范围映射
R经过某种换算得找到一个可落座的范围,再从范围映射到S。优点在于数据路由机构可以大大节约存储,但要求快速的换算。HBase算是这样的一个例子,它通过把按字典顺序排序的rowkey为标识的行数据用基于3级B-Tree的LSM Tree组织起来来实现行的快速定位,找到Region就是范围的映射。MongoDB也有对这种方式的支持。你要是靠把治疗帕金森的药推销到儿童医院问鼎年度销售冠军,那你绝对是一罐爱肤乐油,让人醉了,显然范围没有overlap。
哈希
该方式力求数据的均匀分布,性质上基本就是随机撒,对于大块读取连续的或一个范围的数据是不利的。MongoDB支持根据哈希值来分散数据。
知道北京火车站吧,如果把人映射到进站口,那就是这种方式,一个人从那个口进,没什么约定。至于在软件的世界里,中间怎么哈希的,那方式多了去了。如果人都拥挤到特定的口,那就是北京站的管理层哈希砸了,它肯定会想法儿把它弄匀乎了。如果你一个公司的一群人真被哈了,比如说,你规定每个人的身份证号的尾数对应着进站口号,那就得化整为零进去,进去后想再化零为整,那就得再做些功,所以也有缺点,如果你是具有独特健身pattern的导游。
不可变S的映射
最常见的就是hash-mod方式,最大的缺点在于不具备扩容能力。优点在于路由过程资源占用很小。现实中也有存在,比如说,但凡说集群的shard/partition等数值不可变的情况都属于此类。ElasticSearch大体上就是属于这种情况,对于一个Index,一旦建立了,就不能改变其shard数量。可实操的扩容方法就是建立更多的Index,但这要求在Index之上建立更上一层的路由。交警美女上面还有个交警大叔呢,你得先约他,记着哈,别急。
其实没有什么最好的方案,一切都取决于需求的定位或设计目标是什么,简而言之,结果导向的。比如说,重写轻读和重读轻写在整体设计上就会意味着不同的指导意义。侧重顺序读还是随机读也会影响整体设计,当然适用的场景也就有分别了。说俗点,那你得为接棒的服务,递的时候就得想着接。
时间是个人们杜撰的伟大概念,基本上信息系统都离不开,而且读的时候基本上都跟它有关,还而且,经常关注的就是最近一段时间的东西,别说你就爱吃蔫儿菜啊。但是砖家说了,如果你给这样一个系统做个心电图,那图的节奏看着可能就跟着雷劈了差不多。这只是一个时间维度。
人,他贪啊,其实现实世界的需求是,点、线、面、体甚至更高维度的信息可能同时都需要。这里以时间线为例,提一丢丢拙案,那些造NoSQL或者别的什么东西的大牛们,对于那些人家认为新鲜的,能不能把那个叫Replica的随便设个想要的数量,甚至于智能地自主决策,别一刀切行不,这样起码并发压力图看着不雷劈了。对,最新的大片儿你得多备几份,看的人多吗,当口的生意你不做,年终了你想让人家抽富士苹果啊,我看中。
实时监测
在整个数据服务体系中,对CPU、内存和磁盘空间的监测是必要的,至少它可以提醒人工扩容的必要性,以及压力或数据量的不均衡性,以便采取应对措施。广义讲,任何分布式系统,如果没有一个中枢神经系统,比如说NameNode,HMaster和Mongos等(在这一点上,目前他们做的可能还不是特别好),掌握着各个节点与读写路由决策相关的关键指标,那就只能无理决策了,闭着眼睛拍脑门,“反正我没看见,都在那了,自己看”。毕竟每个节点时刻在发生着变化,刻舟求剑必然淹死在红海里,只有动态闭环反馈才能保持均衡。一碗水端平,难,你造吧。
浮云下的展望-智能扩展
近两年,云计算甚嚣尘上,也涨翅膀了,会飞了。如果你的数据系统存在一个全面的健康监测机构,使得通过一些规则设定实现全自动的扩展成为可能,那就有点智能了。例如在一定条件下,通过Python调用OpenStack API完成虚机和数据库等的安装、配置、优化及初始化。这可能是当下云服务商努力的方向之一。记着,如果你的产品设计能让人变懒,那就对路了,信不,你孙子肯定比你懒。从呱呱坠地开始一直到一缕青烟,人的一切的事,就是通过一个click,一个手势,一句话,一个眼神甚至一个念头,立马变成现实,风就是往这儿吹地。要不你到盘古大厦楼顶吹吹风,来个真实体验。
结束语
在当今数据量Big bang的时代,如果您有幸致力于自主研发或使用数据处理系统,希望这碟小菜您还觉得有一丢丢嚼头,浪费你视觉神经细胞了,我可没@U奥。