京东PaaS平台的主要服务对象是两类人群,一类是个人开发者,二类是京东的ISV。在数据开放平台日益成熟的背景下,他们都希望以最低的成本,方便地部署自己的应用,提高生产力。而京东PaaS平台正是以满足开发者和ISV的这一需求而开发的。京东PaaS平台的核心是JAE(JingdongAppEngine),它以CloudFoundry为内核,之所以选择CloudFoundry,是因为CloudFoundry是最早开源,在社区里最成熟、最活跃的基础PaaS平台。为了给开发者提供更加便捷的服务,JAE将基础服务云化,接入各种应用组件服务,诸如高可用MySQL服务、Redis缓存集群服务、以及消息队列等;此外,它结合应用开发工具,为开发者提供了类github的代码托管服务,云测试和Java工程云端编译,以及资源统计信息,让开发者可以更专注于自己的代码业务。再者,JAE对托管在平台上的应用进行健康监控,支持查看应用日志,提供其它安全服务。让开发者只需关心自己应用代码,而其它一切事情,都由JAE为其提供,极大地提高了开发者的效率,降低了开发成本。下图描述了JAE与PaaS平台用户及其他相关服务之间的关系。JAE还根据京东PaaS平台的需求,做了许多有针对性的功能扩展。本文主要就JAE的核心技术点展开讨论,JAE的其它基础服务将参见其官方网站:智能路由(LoadBalance)我们知道,CloudFoundry支持设置应用的实例个数。但是,当并发量增大时,请求(Request)是否能够均匀地分配给后端的实例?针对多实例的应用,CloudFoundry采用随机策略地响应客户端的请求,并不能公平有效地利用实例资源,在并发量峰值时候,存在发生雪崩的可能性。为解决这一潜在问题,JAE借鉴了nginx的路由策略,采用权重(weight)算法,负载越小的实例越有机会响应请求。那么,我们需要进一步解决的问题是:如何计算实例的负载,以及如何在接收请求之后对其进行分流?下图是JAE的模块关系图:所有请求首先到达router模块,router保存所有实例的路由信息(即实例的ip和port),并由它决定由哪个实例来响应请求。每个实例的ip和port信息都是dea模块经过nats消息总线转发给router的,其实现原理是:dea将自身服务器上的所有实例信息发给nats,router订阅了这则消息,收到之后保存在路由表中,通过过期失效机制来定期获得最新的实例信息。为使router获得各实例的负载信息。我们对dea模块进行改造,在其每次向nats发送消息的时候,将实例在这一时刻的负载信息也“捎带”上。dea模块收集dea服务器本身以及所有实例的CPU使用率、内存使用率、I/O等原始信息,一并发送给router。router决定如何从这些原始数据中计算出负载值。至于采用何种算法来计算负载,这是router自身的职责范围,我们采用了类似下面的算法:实例真实负载=(vm负载*30%+实例负载*70%)*100%vm负载=CPU已使用%*30%+Mem已使用%*30%实例负载=CPU已使用%*30%+Mem已使用%*30%在上述算法中,我们在计算实例的负载值时考虑了dea的因素,其原因在于dea实际就是服务器(虚拟机),而实例运行在dea上的各个进程之上。如果某个dea的负载很高,而其上的某个实例的负载却很低,此时router不一定会将请求交给这个实例。所有算法都要考虑dea的感受。每个应用实例的负载值计算出来之后,如何决定哪个实例可以优先响应客户端请求,JAE提供了以下几个均衡策略:从下面这段代码可以看出,Router使用了weight策略。有状态的(stateful)请求不经过智能路由的处理。比如,当存在session时,第一次请求之后,服务器将响应该请求的实例信息回写至客户端的cookie中,当router收到该客户端的下一次请求时,会将其转发给同一实例。也许有人会问,这样做是否会影响请求的响应时间?答案是肯定的,但是影响很小,因为该算法是纯数值计算,效率非常高。目前的算法只考虑了几个常用的因素,还存在优化的空间,比如增加负载的因素,如I/O,实例带宽使用情况等。弹性伸缩(Auto-scaling)接续上一话题,当并发量持续增大,通过智能路由可以均衡所有实例的负载,但如何应对实例的负载持续升高,面临应用随时不可用的情况?只有增加实例!虽然,我们可以通过JAE控制界面轻松地为一个应用增加或减少实例数(只要在资源满足的情况下)。但这种纯手动的方法显然不可取,JAE将此过程自动化,所采用的就是弹性伸缩机制。惯用的方法就是定义伸缩规则,下面这是JAE管理页面的规则设置:规则是用户层面的全局定义,每个用户可以创建多个规则,具体的应用绑定规则之后才能生效。规则的正确执行依赖于“过去几分钟内,应用的平均请求次数”这一指标。我们通过实时统计来获取这一指标,其实现流程图如下图所示:所有router服务器都安装了agent,flume集群实时收集router的nginx访问日志,保存在redis中并定期进行清理,同时将分析结果保存在同一redis集群中,规则引擎从redis中取得数据,与此应用的规则对比,判断是否触发规则,之后调用cloudcontrollerrestfulapi来扩展或缩减实例数。将原始日志以及分析结果传送给云日志和云监控模块,为应用提供相应的功能。如dashboard管理页面上的应用日志查看,检索;应用PV、UV监控趋势图等。智能启动(Auto-loading)如果有80%的应用不活跃,却一直占用着资源,就会造成极大浪费。智能启动的含义是当某个应用在一段时间内未收到请求,则将应用暂时休眠,等下一次请求到达时,立即启动此应用。长时间没有请求的应用,再次访问的时候,会有秒级的加载延迟。如图所示,智能启动也用到了访问日志的计算结果,计算的是每个应用在统计周期内的访问次数,同样保存在Redis集群中。智能启动模块从CCDB中过滤取得待处理的应用列表,依次获取Redis关于周期内应用的总访问次数,如发现为零则先调用ccrestfulapi停止应用,再将CCDB中的此应用标识为sleep状态,同时通知Router更新路由表信息,这样路由表中既有所有正在运行的应用实例信息,又有sleep状态的应用信息。当Router接收到下一个访问的时候,首先从路由表是查找对应的实例信息,发现此应用处于sleep状态,就会激活此应用,并且立刻返回给客户端一个正在加载页面。这样再刷新页面,就可以正常访问应用了。下表从natsmessage来说明模块间的交互:资源隔离与访问控制资源隔离是CloudFoundry的精髓,应用在JAE上除了各种功能方便开发外,最重要的还是“安全感”了,资源隔离即应用之间的资源相互隔离不干扰,访问控制是指在JAE内部,应用之间不能通过任何方式相互访问,不能操作其它应用的代码,但可以通过HTTP方式访问其它应用。JAE在整个过程也做了一些尝试,这里分享一下。CloudFoundry用warden来实现资源隔离与访问控制的,但是JAE的第一个版资源隔离策略使用了vcapdev,当时没有warden。在当时的背景下,CloudFoundry官网还未迁移至v2版、业内的成功应用也比较少,JAE采取稳中求进的方案,即在vcapdev的基础上,借鉴了warden思路,以此来实现资源隔离和访问控制。下面,我们将详细介绍JAE的第一版资源隔离实现方法,该方法部署起来所需的资源比较灵活,既支持单机部署也支持多机部署,对个人开发者有很好的借鉴参考。如上图所示,JAE第一版资源隔离与访问控制的实现方式是vcapsafemode+cgroup+quota+ACL。首先,vcapsafemode提供了访问控制的功能,安全模式为dea服务器创建了n个用户,默认是32个用户,vap-user-11至vap-user-32,属于vcap-dea用户组,启动一个应用实例就为其分配一个用户,并将代码目录的拥有者设置为此用户,实例停止则回收用户。这样可以简单地保证应用间的访问控制,不同应用(不同用户)相互不可访问。vcapsafemode只是设置了应用目录的权限,限制了目录间的访问,但是仍然可以看到或操作大部分系统命令,系统文件,如ls,mkdir,/usr/bin,/etc/init.d/,这是很危险的。JAE通过linux的ACL(accesscontrollist)将大部分的系统命令都禁掉了,这有点杀敌一千自损八百的味道,很多应用是需要调用系统命令的。ACL的具体做法是限制了用户组vcap-dea对绝大多数系统命令的查看、操作权限:JAE用safemode+ACL实现了某种意义上的访问控制。为什么说是某种意义上的?它虽然提供了一些功能,但是没有Namespace的概念,在特定的Namespace中,PID、IPC、Network都是全局性的,每个Namesapce里面的资源对其他Namesapce都是透明的,而safemode+ACL则是一种共享的方案。Namespace问题也是后来JAE升级的主要原因。其次说到资源隔离,一个应用用到的系统资源大概有内存、CPU、磁盘和带宽等。JAE借鉴warden的方案,使用linux内核自带的cgroup和quota来解决内存、CPU、磁盘的隔离问题。下面,借此机会介绍warden的实现细节。warden实现原理cgroup(ControlGroup)是Linux内核的功能,简单的说,它是对进程进行分组,然后以组为单位进行资源调试与分配,其结构是树形结构,每个root管理着自己下面的所有分支,而且分支共享着root的资源。由各个子系统控制与监控这些组群。cgroup的子系统有:CPU、CPUset、CPUacct、memory、devices、blkio、net-cls、freezer,不同的linux内核版本,提供的子功能有所差异。cgroup的系统目录位于/sys/fs/cgroup,JAE宿主机是ubuntu12.04LTS,默认的有以下几个子系统:CPU、CPUacct、devices、freezer、memory当dea启动的时候,会重新初始化cgroup,重新mount子系统。将cgroup系统安装在/tmp/container/cgroup下,mount了4个子系统。当部署一个应用时,/tmp/container/cgroup/memory目录生成此应用的进程节点,命名为#{instance_name}-#{instance_index}-#{instance_id},即“应用名-应用实例号-实例id”,将应用的内存配额写入memory.limit_in_bytes以及memory.memsw.limit_in_bytes。限制了可使用的最大内存以及swap值。接着将实例的进程ID写入各个子系统的tasks文件中,注意到每个子模块的notify_on_release都设置为1,这是告诉cgroup,如果应用消耗的资源超过限制,就kill掉进程。Warden中写了个OomNotifier服务来监控内存的消耗情况,然后做具体操作。个人觉得太复杂,可能OomNotifier有更“温柔”的处理方法或有更多逻辑处理。但是目前来看,OomNotifier只是做了kill操作。JAE为什么对内存设置了配额,而对CPU子系统没有设置呢?因为在JAE环境中,应用主要以内存消耗为主,而且CPU如果要设置配额,只能设置占用时间的比例,在逻辑上就无法更直观地为某个应用分配CPU资源,所以就采用了“平均分配”的原则。如果一台虚拟机上只有一个应用实例,那么此应用实例可以“独享”所以CPU资源,如果有两个应用实例,各自最多只能用50%,以此类推。CPU的使用率是过去一段时间内,应用实例占用的CPU时间/总时间。接下来说到磁盘配额,JAE使用了linux内核的Quota。Quota可以对某一分区下指定用户或用户组进行磁盘限额。限额不是针对用户主目录,而是针对这个分区下的用户或用户组。Quota通过限制用户的blocks或者inodes超到限额的作用。Quota的初始化同样发生在启动dea时,在此之前,要先安装quota,并指定要进行quota管理的分区,这里用$1传参。当部署一个应用实例时,quota设置磁盘配额。上面vcapsafemode提到,每个实例都分配一个用户,而quota就是对此用户的配额管理。Quota管理blocks和inodes有hard和soft两个临界点,超过soft值,可允许继续使用,若超过hard值,就不再允许写入操作了。Block和inode都给了512M的缓冲值。因为实例停止或删除后,用户会回收,所以此用户的quota需要重置。Repquota-auvs查看磁盘使用情况:通过使用cgroup、quota、ACL,JAE间接地实现了warden的部分功能,上面提到的Namespace问题,由于ACL的限制,应用无法使用系统命令,但是从应用的角度,实例应该跑在一个运行环境完备的操作系统(container)上,可以做任何事情,而不是有各种限制。JAE第一版于2013年6月上线,维持了两个月之后,我们越来越意识到Namespace的重要性。此后,我们又花了一个月的时间,在CloudFoundryv2的基础上,将JAE第一版的功能全部迁移过来,用warden来实现访问控制与资源隔离,JAE第二版于2013年9月中旬上线。在升级的过程中,我们发现了CloudFoundryv1与v2的诸多不兼容问题。譬如,v2引入了organization、spaces、domain的概念;router用go重写,去掉了nginx,导致flume收集nginx日志方案重新设计;v2的cloudcontrollerrestfulapi的变化,dashboard几乎是重写的;运行在warden内部的应用,没有权限直接读取日志文件;在v1上运行的应用,大部分不能运行在v2上,为此我们做了个转化部署的自动化工具,将v1上的应用迁移至v2上。添加了php和python的buildpack,并做了定制。在JAE的部署方面,由于底层的openstack环境做了较多改进,接口也发生了一些变化,Bosh原生的openstackCPI可能满足不了要求,我们决定放弃Bosh,采用更简单的capistrano来做集群部署,JAE集群数目则通过手动去扩展。总结虽然京东云擎正处于发展的初级阶段,但是我们坚信未来有充分的发展空间,我们计划后续要做的工作有:用户自定义域名的绑定;智能路由和智能启动,将负载计算多元化,更能体现后端实例的真实负载;持久化的分布式文件系统,保证应用实例保持在本地的数据不会丢失;智能启动或重启停止应用时使用snapshot,保证现场环境的完整性;.natscluster,避免nats单点;
如何提高网站的用户体验?网站建设时请务必以用户搜索为中心,以用户的需求为宗旨,制作出一份对搜索引擎友好的网站来,不然后面优化很难进行。那网站如何建设才能提高用户体验度呢?本文就给大家带来提高网站用户体验的几种办法,一起来看看吧。一、提升访问速度,确保稳定运行。没有速度,一切都是浮云,对于营销型网站建设,这就是真理。一项调查显示,网站加载时间超过5秒,三成网友会放弃等待;而超过10秒,且毫无任何提示,至少有80%的人会选择放弃;超过20秒无法打开,95%甚至更多的人就直接关闭浏览器选项标签了。不仅是浏览速度,网站运行稳定性也至关重要,不稳定的运行犹如加载速度不给力,会极大的破坏用户体验。在中国,目前三网融合只停留在口头,而没有实质进展的时候,互联互通就是一个头痛的问题,对于中小企业而言,此困境惟一的化解办法就是选择多线接入的网站主机,虽然成本略高。二、视觉先入为主,设计专业取胜。第一印象直观主要,尤其是在用户对一切尚不了解的时候。就像茅台酒、五粮液酒好,也需要好的瓶子,好的包装,好的广告宣传一样,对于企业来说网站也是一种包装宣传,尤其是营销型企业网站,更是如此。精于细节,能够完美演绎企业形象及理念价值的设计,可以有效提升网站宣传力度;同样的,一个粗制滥造的网站,也会起到宣传作用,只是这样宣传是负面的,是消极的。笔者认为在网站设计制作的问题上,无论功能简单复杂,设计一定要专业精细。宁可没有网站,给用户以想象的空间,也不要粗制滥造缺乏设计的网站。三、新闻资讯要持续有规律的更新。做网站添加资讯我们一般都会有意考虑SEO优化,但也不能为了优化堆砌关键词影响到资讯内容的可读性。因为这会严重影响读者的心情,降低了网站的用户体验度。那怎么才能既提高文章的可读性,有符合搜索引擎的要求呢?这就要求资讯内容不仅要专业、原创,也需要注意与时俱进。做网站不容易,既要满足搜索引擎的口味,更要满足访客的需要,然而想要做好企业网站建设和用户体验度,就更不容易了,要对所建设的所有网站的每一个页面都要注重起来,网站中的每一个页面都要尽量做到用户体验特别好,在建设每一个网站的时候,都要站在网站浏览者的角度去制作,只有这样才能建设出一个用户体验比较好的网站。以上就是小编整理带来的提高网站用户体验的几种办法,感谢大家的阅读,更多内容请关注站三界导航网站!
京东和阿里之间的激烈角逐,一直是电商界最抢眼的戏码。日前,阿里与国家认监委达成战略合作,通过在数据层面的互通,阿里可以直接识别平台上3C产品的真伪,矛头直指京东最核心的3C业务。该消息一出,不少评论直言京东该不淡定了,不管是评论者还是旁观者,都多虑了。且不论京东多年来在3C品牌上积累的经验、资源、口碑,单就京东围绕3C业务开展的诸多服务,就足以让京东在3C领域掌握绝对优势,并有一改现在电商格局的威势。定制化营销才是王道在电商的发展历程中,单纯的平台已经转型为营销平台,普遍采用站内搜索。然而,随着社交网络的兴起,又诞生了电商平台的站外引流,这也是为何阿里会收购优土,收购新浪等具有传播效应公司的目的。如果说站内搜索为电商平台营销1.0的话,站外引流可以说是2.0时代。1.0时代的站内搜索技术已然成熟,诸多的电商平台并不会因这一点而形成差距。2.0时代的站外引流,目前而言,京东业已同国内最大的社交平台腾讯联合,阿里也有微博、优土等媒体型平台的优势,可以说是打成平手。时代不可能不进步,满足更多平台厂商的需求才是最终目的,才能形成共赢的大好格局,要满足这一点,就需要满足商家的个性化需求,根据商家的不同,量身定制打造出与众不同的营销策略——电商平台营销3.0的定制化营销时代已然来临,而推动这一进步的就是京东。对消费者负责的3C硬货实验室不久前,京东首次联合信息产业部、国家质监局旗下的通信标准制定机构——泰尔实验室,京东3C硬货实验室。将针对入选实验室检测的产品,从质量、性能、安全性,三个方向进行深度测试,并通过京东大数据累计,对消费者日常使用中会出现的复合型情况进行情景化测试,对产品进行评估、评级。同时,京东3C硬货实验室也将跨界联合不同的产品,对入选产品进行极限测试,力图打造一档全新的互联网趣味测评栏目,在众多3C产品中甄选出真正的超级硬货,向消费者推荐真正的好的产品。该评测将面向所有在京东销售的3C品类的品牌及其产品,由厂商自行申报。凡经过测评考验的产品,也均将得到入驻京东名品堂的荣誉。在为MotoX极手机成为该项目第一个挑战者之后,让人吃惊的是,著名汽车厂商Jeep也加入测试,这次跨界营销也是让人越发的佩服京东的影响力。考虑到京东的平台实力和口碑阵地,这样的评测节目一出,必将成为消费者选购3C产品的指导内容。做商家的营销全案服务者在这样一个硬货实验室诞生的背后,我们不难发现随着京东在3C领域领先地位越发巩固,京东越发的注重替厂商提供完整的销售解决方案,尤其是在营销方面,更是不断的推陈出新。我们可以看一下,在京东策划的营销事件中,你记住了几个?NO.1:今年4月份三星GalaxyS6在京东首发,双方策划了"弯屏事件"与"密室之旅"。NO.2:今年9月,京东与苹果合作,策划了"报纸白条"事件。NO.3:今年10月,在乐视1s的首发上,有双方大楼互亮引足关注。NO.4:今年11月份,京东与小米策划了"送军粮"事件,小米为京东总部员工送上一袋袋小米以示慰问,也以此方式双方共庆小米获得京东3C双十一首日的销量冠军。NO.5:而就在前不久,中兴BladeA1在京东首发,又玩了一把“指纹迷宫”的线下事件,京东独具匠心的采用了指纹预约方式,这种全新的预约方式立刻聚焦了大众的关注,也让BladeA1的预约量猛增。为厂商提供营销资源不稀奇,但是像京东这样的针对厂商产品内容产出定制化营销的电商平台不常见,考虑到京东在3C领域的市场地位和影响力,配合京东渠道物流上的优势,再加上营销举措上的多样性,京东不再是一个销售通路、服务通路的平台,而愈发的变成了一个深耕科技品类服务体系,全面推动商家快速发展、进步的聚合平台。事实上,不论电商还是其他领域,在当今这个时代,变革速度已然非常惊人,根据形势变化做出快速反映,方能掌握绝对优势。从京东的转变来看,在电商平台打造方面,反映速度、应对策略,已经不是其他电商平台能跟得上的了。尽管阿里体量庞大,但快消、服装、食品类商品权重较大,并不能形成其核心优势——垂直细分领域的电商。随着品牌自身实力的增强,众多自有品牌纷纷选择闹“独立”、自建电商,亦或者与其他平台合作,因为对于厂商品牌来说,作为一个房客,在阿里平台上盈利多,但房租更多。反观以3C起家的京东,境况则大不同。近几年,我国,更确切地说是世界数码科技类行业明显提速,大有引领世界走向的趋势,因此成为竞相争夺的对象。尤其是物联网成为风口的当下,国家甚至将互联网+提升到国家战略高度,种种迹象表明,我们正迎来一个井喷的科技创新时代。以上就是本文的全部内容,希望对大家有所帮助。
Go语言是谷歌2009年首次推出并在2012年正式发布的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(RobPike)说:七牛之所以开发Go,是因为过去10多年间软件开发的难度令人沮丧。Google对Go寄予厚望,其设计是让软件充分发挥多核心处理器同步多工的优点,并可解决面向对象程序设计的麻烦。它具有现代的程序语言特色,如垃圾回收,帮助开发者处理琐碎但重要的内存管理问题。Go的速度也非常快,几乎和C或C++程序一样快,且能够快速开发应用程序。最初去评估Go语言最重要的原因是,七牛没有找到一门合适的语言。从云计算领域的主要技术方案看,最受欢迎的是C++和Java。七牛知道亚马逊是用了Java。我个人尝试Java做服务端开发是在2007年金山实验,Java的风格比较拘束或严谨,与我推崇的编程风格不合,并且在分布式系统开发上没有显著的优势,所以才会关注Erlang(也因此有了ECUG社区)、Go等小众语言。在我评估完Go语言后,我认为它是云计算领域最合适的开发语言。如果说到Java曾经的流行,我们会联想到SSH(Struts+Spring+Hibernate);如果提到Python,也会联想到Django;如果提到Ruby,会联想到RubyonRails;如果提到JavaScript,会联想到NodeJS;如果提到PHP,更是一堆长江后浪推前浪前浪死在沙滩上的Web开发框架。这些编程语言社区的繁荣昌盛无一例外都和Web开发息息相关,且最终沉淀下来的都是各种五花八门各有千秋的众多Web开发框架。可以说,我们当前所面临和Web开发的技术选型,从未有过如此的繁荣。繁荣的背后,衬托的是一个大江东流去不复还的PCWeb时代。稳定性来说,云计算都是假设单机是可以宕机的,要在单机的不可靠下让整个集群可靠(这种宕机甚至不为用户所感知)。七牛并不担心单个进程的稳定性,哪怕Go程序每天会挂一次,对七牛而言,也是可以接受的。Go语言入门门槛非常之低。有任何其他语言的背景,学习Go语言只需要一周的时间。**七牛面试从来不问你会不会Go语言。七牛关心的是开发者的能力与七牛业务的匹配度,比如他算法基础如何、是否擅长网络编程、是否适合创业(对事情的责任感)等等。Go语言的哪些特点最吸引人?并发Go最大的特色就是在语言层面天生支持并发,不需要像其他大多数编程语言那样需要开发者自行实现或借助第三方类库实现并发编程,Go在语言级别支持的并发编程,其逻辑简化得通俗易懂简单好上手。性能不同于大多数脚本或解释性的高阶编程语言,用Go编写的代码直接了当编译成机器码高效执行。简洁25个关键字即表达你能想到的所有招式,没有也不需要有任何多余,想干啥事就go一下。跨平台x86、AMD64(x86_64)、ARM;Linux、Windows、Darwin(OSX)、FreeBSD、Android(计划Go1.4)几乎全平台支持,真正做到一份源码,随处编译,到处运行。Go语言都有哪些常见的应用场景?作为一个Go语言的重度用户来看,当前除了不适合拿来造操作系统以外在操作系统之上应用级的事情都能干。再更具体一点,比如说适用于这样一些使用场景:系统应用以前要用C/C++做的系统应用,现在都可以用Go来写,事半功倍,而且Go完美包容C源代码,两者互相调用还可以混合编译从而无缝集成。网络应用包含了常见的服务端编程比如Web和APIService,以前用PHP/Python/Ruby/Java干的事情现在都可以用Go更加简单清晰的来写。再比如还可以拿来做一些Proxy(代理)如网络穿透软件等,你懂的。分布式系统基于Go强大的系统编程加网络编程,打造各种跨网络的分布式系统服务,Go社区有不少和分布式系统相关的开源产物。各种形态的存储和数据库应用比如groupcache,influxdb等。客户端应用包括带界面的桌面软件,以及后续可以想像的移动端应用(比如对Android的支持)。云服务(PaaS)如基于Go打造的七牛云存储(分布式对象存储系统),比如基于Go编写的Docker(一款开源的容器虚拟化产物)。Go能做的事情,包含但不限于以上罗列的使用场景。比如Web开发。大多数编程语言之上的Web开发框架都是遵照MVC的处理流程去开发Web应用:Model部分封装数据,Controller部分处理业务逻辑,View部分植入变量填充模板页面。而大部分Web框架关于MVC的三部分都是在Server-side处理,比如对View部分的处理都是在Server-side通过程序动态对模版变量求值后再拼接组装成HTML页面输出给浏览器去呈现。而Go开发Web应用,并不依赖任何Web开发框架,用内置的标准库就可以轻而易举地实现:比如使用net/http标准库就可以数行代码构建一个完整的Web骨架应用;再比如,通过关键字struct封装一个数据结构就可以表达原本MVC框架中需要用厚重的ORM(Object-RelationalMapping)才能表达的那部分。大道至简,这可以说是Go的哲学。在View这一层,Go也有相应标准库提供支持,但更推荐的做法,是当下比较流行的MVVM(Model-View-ViewModel):Server-side只输出JSON,浏览器DOM作为View层,前端JavaScript充当Contoller部分;这样,不仅减少了Server-side的资源消耗还有中间传输的网络流量,而且前端可以更灵活和更丰富,后端也可以更轻盈和更高效,也更有利于项目的分工和协作。Go语言在七牛中都开发了些什么服务?在七牛的代码量中,Go语言使用占多少比例?七牛主要使用Go开发了以下服务和工具:分布式存储系统(DistributedKey/ValueStorage)数据处理服务(DataProcessing)网络接口服务(RESTfulAPIService)消息队列服务(MessageQueueService)日志处理系统(LogService)Web网站(不含前端JavaScript)CLI命令行和GUI图形界面工具其他辅助工具总的来讲,Go在七牛七牛的工程中代码覆盖率超过90%。还有10%不能覆盖的原因是七牛给开发者自助使用的Web界面需要用JavaScript编程来实现酷炫的前端,以及七牛为开发者准备了多达超过10种编程语言的SDK。我们再来看看Go在当下这个多核时代的作为。不得不说,Go最大的特色就是在语言层面天然支持并发,在Go程序里边,你可以通过在一个函数调用前使用关键字go即可让该函数func运行成为一个独立的goroutine,goroutine可以理解成一种比线程更加轻盈更省开销的轻量级协程。Go的并发模型就是通过系统的线程来多路派遣这些独立函数的执行,使得每个用关键字go执行调用的函数可以运行成为一个单位协程。当⼀个协程阻塞的时候,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现程序的无等待并行化运行。且调度的开销非常小,单核CPU调度的规模不下于每秒百万次,这使得我们能够创建大量的goroutines,从而可以很轻松地编写并发程序达到我们想要的目的。同时,Go在语言层面还引入了channel这一内置类型来实现并发执行体goroutines之间的消息传递,通信靠channels来传递消息。Go遵循CSP(Communicatingsequentialprocesses)并发模型,通过通信来共享内存而不是用共享内存的方式进行通信。Go的并发里边没有共享内存,更没有内存锁,这一切都有利于进行更为安全和简单的并行程序编写。
分享人介绍:王团结,七牛数据平台工程师,主要负责数据平台的设计研发工作。关注大数据处理,高性能系统服务,关注Hadoop、Flume、Kafka、Spark等离线、分布式计算技术。下为讨论实录数据平台在大部分公司属于支撑性平台,做的不好立刻会被吐槽,这点和运维部门很像。所以在技术选型上优先考虑现成的工具,快速出成果,没必要去担心有技术负担。早期,我们走过弯路,认为没多少工作量,收集存储和计算都自己研发,发现是吃力不讨好。去年上半年开始,我们全面拥抱开源工具,搭建自己的数据平台。数据平台设计架构公司的主要数据来源是散落在各个业务服务器上的半结构化的日志(系统日志、程序日志、访问日志、审计日志等)。大家有没考虑过为什么需要日志?日志是最原始的数据记录,如果不是日志,肯定会有信息上的丢失。说个简单的例子,需求是统计nginx上每个域名的的流量,这个完全可以通过一个简单的nginx模块去完成,但是当我们需要统计不同来源的流量时就法做了。所以需要原始的完整的日志。有种手法是业务程序把日志通过网络直接发送出去,这并不可取,因为网络和接收端并不完全可靠,当出问题时会对业务造成影响或者日志丢失。对业务侵入最小最自然的方式是把日志落到本地硬盘上。Agent设计需求每台机器上会有一个agent去同步这些日志,这是个典型的队列模型,业务进程在不断的push,agent在不停的pop。agent需要有记忆功能,用来保存同步的位置(offset),这样才尽可能保证数据准确性,但不可能做到完全准确。由于发送数据和保存offset是两个动作,不具有事务性,不可避免的会出现数据不一致性情况,通常是发送成功后保存offset,那么在agent异常退出或机器断电时可能会造成多余的数据。agent需要足够轻,这主要体现在运维和逻辑两个方面。agent在每台机器上都会部署,运维成本、接入成本是需要考虑的。agent不应该有解析日志、过滤、统计等动作,这些逻辑应该给数据消费者。倘若agent有较多的逻辑,那它是不可完成的,不可避免的经常会有升级变更动作。数据收集流程数据收集这块的技术选择,agent是用go自己研发的,消息中间件kafka,数据传输工具flume。说到数据收集经常有人拿flume和kafka做比较,我看来这两者定位是不同的,flume更倾向于数据传输本身,kakfa是典型的消息中间件用于解耦生产者消费者。具体架构上,agent并没把数据直接发送到kafka,在kafka前面有层由flume构成的forward。这样做有两个原因1.kafka的api对非jvm系的语言支持很不友好,forward对外提供更加通用的http接口2.forward层可以做路由、kafkatopic和kafkapartitionkey等逻辑,进一步减少agent端的逻辑forward层不含状态,完全可以做到水平扩展,不用担心成为瓶颈。出于高可用考虑,forward通常不止一个实例,这会带来日志顺序问题,agent按一定规则(round-robin、failover等)来选择forward实例,即使kafkapartitionkey一样,由于forward层的存在,最终落入kafka的数据顺序和agent发送的顺序可能会不一样。我们对乱序是容忍的,因为产生日志的业务基本是分布式的,保证单台机器的日志顺序意义不大。如果业务对顺序性有要求,那得把数据直接发到kafka,并选择好partitionkey,kafka只能保证partition级的顺序性。跨机房收集要点多机房的情形,通过上述流程,先把数据汇到本地机房kafka集群,然后汇聚到核心机房的kafka,最终供消费者使用。由于kafka的mirror对网络不友好,这里我们选择更加的简单的flume去完成跨机房的数据传送。flume在不同的数据源传输数据还是比较灵活的,但有几个点需要注意1.memory-channel效率高但可能有丢数据的风险,file-channel安全性高但性能不高。我们是用memory-channel,但把capacity设置的足够小,使内存中的数据尽可能少,在意外重启和断电时丢的数据很少。个人比较排斥file-channel,效率是一方面,另一个是对flume的期望是数据传输,引入file-channel时,它的角色会向存储转变,这在整个流程中是不合适的。通常flume的sink端是kafka和hdfs这种可用性和扩张性比较好的系统,不用担心数据拥堵问题。2.默认的httpsouce没有设置线程池,有性能问题,如果有用到,需要自己修改代码。3.单sink速度跟不上时,需要多个sink。像跨机房数据传输网络延迟高单rpcsink吞吐上不去和hdfssink效率不高情形,我们在一个channel后会配十多个sink。Kafka使用要点kafka在性能和扩展性很不错,以下几个点需要注意下1.topic的划分,大topic对生产者有利且维护成本低,小topic对消费者比较友好。如果是完全不相关的相关数据源且topic数不是发散的,优先考虑分topic。2.kafka的并行单位是partition,partition数目直接关系整体的吞吐量,但parition数并不是越大越高,3个partition就能吃满一块普通硬盘io了。所以partition数是由数据规模决定,最终还是需要硬盘来抗。3.partitionkey选择不当,可能会造成数据倾斜。在对数据有顺序性要求才需使用partitionkey。kafka的producersdk在没指定partitionkey时,在一定时间内只会往一个partition写数据,这种情况下当producer数少于partition数也会造成数据倾斜,可以提高producer数目来解决这个问题。数据到kafka后,一路数据同步到hdfs,用于离线统计。另一路用于实时计算。由于今天时间有限,接下来只能和大家分享下实时计算的一些经验实时计算我们选择的sparkstreaming。我们目前只有统计需求,没迭代计算的需求,所以sparkstreaming使用比较保守,从kakfa读数据统计完落入mongo中,中间状态数据很少。带来的好处是系统吞吐量很大,但几乎没遇到内存相关问题sparkstreaming对存储计算结果的dbtps要求较高。比如有10w个域名需要统计流量,batchinterval为10s,每个域名有4个相关统计项,算下来平均是4wtps,考虑到峰值可能更高,固态硬盘上的mongo也只能抗1wtps,后续我们会考虑用redis来抗这么高的tps有外部状态的task逻辑上不可重入的,当开启speculation参数时候,可能会造成计算的结果不准确。说个简单的例子这是个把计算结果存入mongo的task这个任务,如果被重做了,会造成落入mongo的结果比实际多。有状态的对象生命周期不好管理,这种对象不可能做到每个task都去new一个。我们的策略是一个jvm内一个对象,同时在代码层面做好并发控制。类似下面。在spark1.3的后版本,引入了kafkadirectapi试图来解决数据准确性问题,使用direct在一定程序能缓解准确性问题,但不可避免还会有一致性问题。为什么这样说呢?directapi把kafkaconsumeroffset的管理暴露出来(以前是异步存入zookeeper),当保存计算结果和保存offset在一个事务里,才能保证准确。这个事务有两种手段做到,一是用mysql这种支持事务的数据库保存计算结果offset,一是自己实现两阶段提交。这两种方法在流式计算里实现的成本都很大。其次directapi还有性能问题,因为它到计算的时候才实际从kafka读数据,这对整体吞吐有很大影响。要分享的就这些了,最后秀下我们线上的规模。flume+kafka+spark8台高配机器,日均500亿条数据,峰值80wtps。
Quora使用机器学习技术有段时间了。我们始终跟进最新的法,并对现有方法做出重大改进。很有必要提醒各位注意,所有这些改进都是首先在线下运用多种不同的离线测试法进行优化和测试,但最终都要通过在线A/B测试。我将在本文说说2015年Quora会用到的一些非常重要的机器学习应用与技术。(注:本文作者XavierAmatriain是Quora工程副总。)排名排名可以说是网上最重要的机器学习应用之一了。大大小小的公司都围绕着排名建立起业务模型,例如,查询字符串返回的结果。Quora在不同的环境、为了不同的目的,使用了不同的排名算法。一个有趣的例子就是答案排名。假设一个问题有好几个答案,我们感兴趣的是,如何对它们降序排列,使得“最佳”答案在最前,而最差答案在最后。(见如下屏幕截图)。确定一个问题答案的正确排序涉及到多种特征。要确定顺序,首先我们要确定Quora如何定义“好答案”。我们的机器学习算法实现了一种特殊的机器学习排名方法,使用了多种特征,试图将与上述抽象概念相关联的多个维度进行编码。例如,我们使用了描述写作质量信息的特征,也使用了描述该答案收到的互动情况的特征(如赞、踩以及展开数量)。我们还使用了与答案作者相关的特征,比如,他在问题领域的专业性。在Quora,还有很多其他的排名应用,有些甚至不为人察觉。例如,对于一个答案点赞的用户名也是排序后显示的,目的是要将我们认为对于该问题/答案最有见识的用户排在最前。同样,对于特定问题显示可能的回答者时,那些推荐的用户也是排过序的。让我们来仔细看看机器学习排名算法的两个特例:搜索以及个性化排名。搜索算法对于Quora这样的应用,搜索算法可以被视为排名的另一个应用。实际上,搜索可以分解为两个步骤:文字匹配和排名。第一步,以某种方式返回与搜索框输入的查询字符串匹配的文档(问题)。然后,这些文档作为第二步的候选问题,进行排名,以使点击概率等方面得到优化。第二步中很多的特征可以使用,它确实是另一个机器学习排名算法的例子。包括已在最初文字匹配阶段使用过的简单文字特征,以及其它与用户行为相关的特征,或是如流行度等对象属性。个性化排名在如上文描述的一些场景中,也许一个对所有用户的全局最优排名就够用了。换句话说,我们可以假定,对于给定问题,最“有帮助”答案的排序对于阅读答案的用户来说是独立的。然而,这一假设在很多重要场合并不成立。场合之一就是QuoraFeed,从根本上说它是任意登入这一产品的用户都可见的主页。在这个主页上,我们试图为特定的用户在特定的时间挑选最“有趣”的故事,并进行排名(见下例)。这就是一个典型的机器学习个性化排名,与Netflix主页对电影和电视剧进行排名类似。而Quora的用例比Netflix电影电视剧排名更具挑战性。事实上,我们的用例可以看作是Netflix、Facebook以及GoogleNews优化个性化排名的结合体。一方面,我们要保证排名靠前的故事在主题上与用户相关。另一方面,Quora与用户之间也有明确的关系。你在“社交网络”上的行为也应当对排名有所影响。再次,Quora上的故事有时或许与正在进行的潮流事件相关联。及时性是另一个应当影响模型决策的因素,来决定一个故事的排名应当提升还是降低。正因如此,Quora的个性化排名涉及到各种不同的特征。下面列出若干:问题/答案的质量用户感兴趣的主题该用户关注的其他用户热门事件…其实,请务必记住,在Quora我们不仅对如何吸引用户来阅读有趣的内容感兴趣,也对将问题提交给能写出有趣内容的用户感兴趣。因此,我们必须将涉及答案趣味性的特征以及针对问题的特征都纳入。为了得到这些特征,我们使用从用户、作者以及对象(如答案/问题)行为推导出的信息。这些行为都被考虑在内并累计在不同的时间窗口内,并提供给排名算法。实际上,可以得到很多不同的特征来加入我们的个性化推送模型,而且我们一直尝试加入更多的特征。对于我们的Feed排名应用,另一个重要的考虑是我们需要能对用户的行为、观感,甚至是热门事件做出响应。我们数以百万的问题和答案还在不停增长,因此我们不能试图为每一个用户进行实时排名。为了优化体验,我们实现了一个多段式排名解决方案,其中提前就对候选者进行选择和排序,之后真正执行最终的排名。推荐上述的个性化排名已经是推荐的一种形式了。类似的方法用在不同的案例中。例如,广受欢迎的Quora邮件精选包括了一系列为你挑选并推荐的故事。这是一个不同的机器学习排名模型,根据不同的目标函数进行优化。除了排名算法,我们在产品的各个不同部分有其它的个性化推荐算法。例如,在好几处地方,你都可以看到人物或主题的推荐(见下图)。相关问题另一个推荐的源由是为了给用户展示与当前问题有某种关系的其他问题。相关问题由另一个机器学习模型来确定的,它考虑多种不同特征,例如,文字相似性、共享数据(co-visitdata),或是如主题等相同的特征。与流行度、或是问题质量相关的特征也要考虑。有必要指出,一个好的“相似问题”推荐,不仅是一个条目与源问题有多相似,还包括目标问题的“趣味性”。实际上,对于任何一个“相关条目”机器学习模型,最麻烦的问题是在相似性和其它关联性因素间进行权衡。相关问题这个模型对于吸引登出用户从外部搜索中访问问题页面特别有效。这也是为何至今这一推荐模型并未个性化的原因之一。重复问题重复问题是上述相关问题的极端情况。对于Quora而言,这是一个难题,因为我们要保证用户回答一个特定问题的精力会被分享,并且被集中到正确的地方。同样,有必要为想要在网站上提问的用户指出已有的答案。所以,我们花费了大量精力来检测重复问题,特别是在发起问题的阶段。我们现有的解决方案是基于使用重复/非重复标签训练的二元分类器。我们使用多种信号量,包括从文本向量空间模型到基于使用量的特征。用户可信度/专业性推断在Quora这样的应用里,掌握用户的可信度是非常重要的事情。实际上,我们并不仅仅完全局限于回答问题本身,还对其与相关主题的关联性感兴趣。某一用户也许对于某些主题知识渊博,但对于其它领域就不一定了。Quora使用机器学习技术来推断用户的专业性。我们不仅了解用户对于给定主题写了什么答案,也知道这些答案得到了多少赞、多少踩,以及什么样的评论。我们还知道这个用户在这个领域得到了多少“推荐”。推荐(Endorsements)是从其他用户角度对于某人专业性非常明确的认可。另外还有件要事要记住,可信度/专业性通过网络传播,这也需要被算法考虑。例如,如果一位机器学习专家对我在机器学习领域的回答给出一个赞,它的分量应该超过该领域非专家的随机用户给出的赞。这也同样适用于推荐以及其它用户间特征。垃圾信息检测与节制(Moderation)像Quora这样以保持内容高质量为傲的网站,必须对使用垃圾、恶意或非常低质量的内容愚弄系统的行为非常警惕。纯粹的人工审阅模式无法扩展。而问题的解决之道,正如你猜测的那样,是使用机器学习模型来检测这些问题。Quora有好些个模型来检测内容质量相关的问题。这些分类器的输出大部分情况下不会直接用作决策,而是将这些问题/答案提供给节制队列,然后进行人工审阅。内容创建的预测对Quora来说,有一点非常重要,要记住:我们对系统很多部分进行优化,不只是为了吸引读者,也是为了产出最好的质量、最受欢迎的内容。因此,我们有一个机器学习模型来预测某一用户撰写某一问题答案的可能性。这使得我们的系统能用多种方式给予这些问题优先权。其中之一就是系统的自动A2A(AsktoAnswer),它将问题通过提示发送给潜在的回答者。上述其它的排名系统也使用这个模型来预测概率。模型Quora对于前文所述不同的案例尝试过很多不同的模型。有时,我们使用开源实现,但更多时候我们最后实现了更有效、更灵活的内部版本。我不会讨论模型的细节,但会列出我们系统使用的模型:逻辑回归弹性网络梯度增强决策树随机森林神经网络LambdaMART矩阵分解向量模型以及其它自然语言处理技术…结语综上所述,Quora运用机器学习的方式多种多样。我们使用这些机器学习方法已经取得了非常重大的收益,我们坚信未来还会有更多收益,并且我们对于新技术还会持续投入。另外,在不久的将来还有激动人心的机器学习新应用,我们已经有所思考了。这些新应用包括广告排名、机器翻译以及其它自然语言处理领域,这些都将直接成为我们计划马上添加的产品新特征。
对于网站的优化推广来说,成功的关键词分析会帮助网站做好一半的工作,剩下的一半就是细节的执行和链接的优化,因为对于关键词的把握决定了我们工作的方向,方向正确,才能更快的达到我们想要达到的目标。不知道大家有没有看过boson对于关键词表现力的分析,其中对于关键词表现分为PBNW(P:Perfect,B:Branded,NB:non-branded,W:Worse)四种的上升下降做了一个很详细的解释,但是个人感觉看起来还是比较吃力的,最起码需要一定的理科功底,当然在掌握之后再用之来分析网站关键词整体的表现力会相当的实用,如果大家感兴趣可以去仔细的研究一下。这里的表现力主要是根据两类关键词——Branded和non-branded,即品牌词和非品牌词,来划分一个其在一个四方格子里面的位置,表现越好得分越高,这样通过对比就可以知道两个时间段关键词表现的升降情况,而不仅仅的只是单个关键词的排名上升下降。这里我提到这个例子并不是说要大家一定去学习这种方法,主要是为了帮助大家深入的了解关键词的表现力分析绝不只是简简单单的分析网站设置的几个关键词排名,而是分析关键词整体的一个表现力,这里还包括排名的展现和流量的点击。以前我对于关键词的研究主要体现在关键词的挖掘,关键词的选取,关键词的布局,关键词的排名等方面,对于其表现基本上没有考虑,这其实有一个非常大的缺陷。因为在SEO过程中,我们需要让网页信息尽量的满足搜索引擎和用户的双重需求,首先要满足搜索引擎相关性和权重的需求,被推荐之后再将决定权交给用户,用户体验做的越好,网站的表现自然就越好。而如果我们不研究表现力,那么关键词的优化工作就倒在最后的一个环节,因为你排名即使在第一也可能点击比不上第二,慢慢的你的排名可能还会被降低,因为你吸引不了用户点击浏览。所以这一块的研究着重表现在两个方面:关键词的排名展现以及获取的点击之间的博弈。对于这两个方面的研究,就不得不使用关键词统计的工具来辅助,如百度站长工具,谷歌站长工具,这里简单地用这百度站长工具做一个简单地分析对比。验证了百度站长工具,我们在管理界面里面查看搜索关键词查询,下面可以清晰的看到用户搜索的一些热门关键词的展现量,点击量,点击率,网页展现的链接,由于网站被降权数据比较少,这里的展现就显得不那么适合深入的分析,但是几个关键的数据已经给我们指出来了,这就是我们下一步分析的主要对象。百度站长工具统计1、热门关键词的展现量这里的热门关键词并不是说一定要指数多高,搜索结果数多高,而是说用户经常搜索的一些获得了展现的关键词,如果我们有百度推广的账户,设置了大量的行业词展现,那么通过一段时间的对比就可以很好的分析这些词哪些够热门,然后还能从中挑选哪些词是潜力词,哪些词需要弱化对其的关注。2、点击量和点击率要想网站网页被点击的多一些,那么网页展现给用户的标题就要够吸引他,这个其实很好理解,百度推广中有一个创意的概念,其实就是要求管理者在对应相关的一些页面进行一些更有创意和吸引用户的描述,让用户更乐于去点击你的页面。而关键词的点击量和点击率就是考量我们对于网站网页这一块优化的核心,虽然标题党有些可恶,但是有的时候的确要为我们排名展现的效果提升,获取更多的流量点击做一些工作。3、网页展现的链接其实这一点需要优化的就是对网站全局优化的一个把控。网页展现的链接越多说明我们的网站优化越合理,整站的优化永远比单纯的关键词优化要优秀。这里我们可以统计一段时间内网页展现的链接来分析哪些页面是我们真正想让用户直接访问带来转化的,而不想要的一些链接展现可以放之任之,也可以采取必要的措施让它“隐藏”起来。好了,对于关键词表现力的简单理解就介绍到这里,后面如果有更深入的研究会跟大家做深入的分析。
JayKreps是来自LinkedIn的首席工程师,他表示日志几乎在计算机产生的时候就存在,除了可用在分布式计算或者抽象分布式计算模型内部之外,还有广泛的用途。本文中他讲述的日志的原理和通过把日志用做单独服务来实现数据集成、实时数据处理以及分布式系统设计。文章内容非常干货,值得学习。以下是原文:我在六年前的一个令人兴奋的时刻加入到LinkedIn公司。从那个时候开始我们就破解单一的、集中式数据库的限制,并且启动到特殊的分布式系统套件的转换。这是一件令人兴奋的事情:我们构建、部署,而且直到今天仍然在运行的分布式图形数据库、分布式搜索后端、Hadoop安装以及第一代和第二代键值数据存储。从这一切里我们体会到的最有益的事情是我们构建的许多东西的核心里都包含一个简单的理念:日志。有时候也称作预先写入日志或者提交日志或者事务日志,日志几乎在计算机产生的时候就存在,同时它还是许多分布式数据系统和实时应用结构的核心。不懂得日志,你就不可能完全懂得数据库,NoSQL存储,键值存储,复制,paxos,Hadoop,版本控制以及几乎所有的软件系统;然而大多数软件工程师对它们不是很熟悉。我愿意改变这种现状。在这篇博客文章里,我将带你浏览你必须了解的有关日志的所有的东西,包括日志是什么,如何在数据集成、实时处理和系统构建中使用日志等。第一部分:日志是什么?日志是一种简单的不能再简单的存储抽象。它是一个只能增加的,完全按照时间排序的一系列记录。日志看起来如下:我们可以给日志的末尾添加记录,并且可以从左到右读取日志记录。每一条记录都指定了一个唯一的有一定顺序的日志记录编号。日志记录的排序是由“时间”来确定的,这是因为位于左边的日志记录比位于右边的要早些。日志记录编号可以看作是这条日志记录的“时间戳”。在一开始就把这种排序说成是按时间排序显得有点多余,不过,与任何一个具体的物理时钟相比,时间属性是非常便于使用的属性。在我们运行多个分布式系统的时候,这个属性就显得非常重要。对于这篇讨论的目标而言,日志记录的内容和格式不怎么重要。另外提醒一下,在完全耗尽存储空间的情况下,我们不可能再给日志添加记录。稍后我们将会提到这个问题。日志并不是完全不同于文件或者数据表的。文件是由一系列字节组成,表是由一系列记录组成,而日志实际上只是按照时间顺序存储记录的一种数据表或者文件。此时,你可能奇怪为什么要讨论这么简单的事情呢?不同环境下的一个只可增加的有一定顺序的日志记录是怎样与数据系统关联起来的呢?答案是日志有其特定的应用目标:它记录了什么时间发生了什么事情。而对分布式数据系统许多方面而言,这才是问题的真正核心。不过,在我们进行更加深入的讨论之前,让我先澄清有些让人混淆的概念。每个编程人员都熟悉另一种日志记录-应用使用syslog或者log4j可能写入到本地文件里的没有结构的错误信息或者追踪信息。为了区分开来,我们把这种情形的日志记录称为“应用日志记录”。应用日志记录是我在这儿所说的日志的一种低级的变种。最大的区别是:文本日志意味着主要用来方便人们阅读,而我所说明的“日志”或者“数据日志”的建立是方便程序访问。(实际上,如果你对它进行深入的思考,那么人们读取某个机器上的日志这种理念有些不顺应时代潮流。当涉及到许多服务和服务器的时候,这种方法很快就变成一个难于管理的方式,而且为了认识多个机器的行为,日志的目标很快就变成查询和图形化这些行为的输入了-对多个机器的某些行为而言,文件里的英文形式的文本同这儿所描述的这种结构化的日志相比几乎就不适合了。)数据库日志我不知道日志概念起源于何处-可能它就像二进制搜索一样:发明者认为它太简单而不能当作一项发明。它早在IBM的系统R出现时候就出现了。数据库里的用法是在崩溃的时候用它来同步各种数据结构和索引。为了保证操作的原子性和持久性,在对数据库维护的所有各种数据结构做更改之前,数据库把即将修改的信息誊写到日志里。日志记录了发生了什么,而且其中的每个表或者索引都是一些数据结构或者索引的历史映射。由于日志是即刻永久化的,可以把它当作崩溃发生时用来恢复其他所有永久性结构的可信赖数据源。随着时间的推移,日志的用途从实现ACID细节成长为数据库间复制数据的一种方法。利用日志的结果就是发生在数据库上的更改顺序与远端复制数据库上的更改顺序需要保持完全同步。Oracle,MySQL和PostgreSQL都包括用于给备用的复制数据库传输日志的日志传输协议。Oracle还把日志产品化为一个通用的数据订阅机制,这样非Oracle数据订阅用户就可以使用XStreams和GoldenGate订阅数据了,MySQL和PostgreSQL上的类似的实现则成为许多数据结构的关键组件。正是由于这样的起源,机器可识别的日志的概念大部分都被局限在数据库内部。日志用做数据订阅的机制似乎是偶然出现的,不过要把这种抽象用于支持所有类型的消息传输、数据流和实时数据处理是不切实际的。分布式系统日志日志解决了两个问题:更改动作的排序和数据的分发,这两个问题在分布式数据系统里显得尤为重要。协商出一致的更改动作的顺序(或者说保持各个子系统本身的做法,但可以进行存在副作用的数据拷贝)是分布式系统设计的核心问题之一。以日志为中心实现分布式系统是受到了一个简单的经验常识的启发,我把这个经验常识称为状态机复制原理:如果两个相同的、确定性的进程从同一状态开始,并且以相同的顺序获得相同的输入,那么这两个进程将会生成相同的输出,并且结束在相同的状态。这也许有点难以理解,让我们更加深入的探讨,弄懂它的真正含义。确定性意味着处理过程是与时间无关的,而且任何其他“外部的“输入不会影响到处理结果。例如,如果一个程序的输出会受到线程执行的具体顺序影响,或者受到gettimeofday调用、或者其他一些非重复性事件的影响,那么这样的程序一般最有可能被认为是非确定性的。进程状态是进程保存在机器上的任何数据,在进程处理结束的时候,这些数据要么保存在内存里,要么保存在磁盘上。以相同的顺序获得相同输入的地方应当引起注意-这就是引入日志的地方。这儿有一个重要的常识:如果给两段确定性代码相同的日志输入,那么它们就会生成相同的输出。分布式计算这方面的应用就格外明显。你可以把用多台机器一起执行同一件事情的问题缩减为实现分布式一致性日志为这些进程输入的问题。这儿日志的目的是把所有非确定性的东西排除在输入流之外,来确保每个复制进程能够同步地处理输入。当你理解了这个以后,状态机复制原理就不再复杂或者说不再深奥了:这或多或少的意味着“确定性的处理过程就是确定性的”。不管怎样,我都认为它是分布式系统设计里较常用的工具之一。这种方式的一个美妙之处就在于索引日志的时间戳就像时钟状态的一个副本——你可以用一个单独的数字描述每一个副本,这就是经过处理的日志的时间戳。时间戳与日志一一对应着整个副本的状态。由于写进日志的内容的不同,也就有许多在系统中应用这个原则的不同方式。举个例子,我们记录一个服务的请求,或者服务从请求到响应的状态变化,或者它执行命令的转换。理论上来说,我们甚至可以为每一个副本记录一系列要执行的机器指令或者调用的方法名和参数。只要两个进程用相同的方式处理这些输入,这些进程就会保持副本的一致性。一千个人眼中有一千种日志的用法。数据库工作者通常区分物理日志和逻辑日志。物理日志就是记录每一行被改变的内容。逻辑日志记录的不是改变的行而是那些引起行的内容被改变的SQL语句(insert,update和delete语句)。分布式系统通常可以宽泛分为两种方法来处理数据和完成响应。“状态机器模型”通常引用一个主动-主动的模型——也就是我们为之记录请求和响应的对象。对此进行一个细微的更改,称之为“预备份模型”,就是选出一个副本做为leader,并允许它按照请求到达的时间来进行处理并从处理过程中输出记录其状态改变的日志。其他的副本按照leader状态改变的顺序而应用那些改变,这样他们之间达到同步,并能够在leader失败的时候接替leader的工作。为了理解两种方式的不同,我们来看一个不太严谨的例子。假定有一个算法服务的副本,保持一个独立的数字作为它的状态(初始值为0),并对这个值进行加法和乘法运算。主动-主动方式应该会输出所进行的变换,比如“+1”,“*2”等。每一个副本都会应用这些变换,从而得到同样的解集。主动-被动方式将会有一个独立的主体执行这些变换并输出结果日志,比如“1”,“3”,“6”等。这个例子也清楚的展示了为什么说顺序是保证各副本间一致性的关键:一次加法和乘法的顺序的改变将会导致不同的结果。分布式日志可以理解为一致性问题模型的数据结构。因为日志代表了后续追加值的一系列决策。你需要重新审视Paxos算法簇,尽管日志模块是他们最常见的应用。在Paxos算法中,它通常通过使用称之为多paxos的协议,这种协议将日志建模为一系列的问题,在日志中每个问题都有对应的部分。在ZAB,RAFT等其它的协议中,日志的作用尤为突出,它直接对维护分布式的、一致性的日志的问题建模。我怀疑的是,我们就历史发展的观点是有偏差的,可能是由于过去的几十年中,分布式计算的理论远超过了其实际应用。在现实中,共识的问题是有点太简单了。计算机系统很少需要决定单个值,他们几乎总是处理成序列的请求。这样的记录,而不是一个简单的单值寄存器,自然是更加抽象。此外,专注于算法掩盖了抽象系统需要的底层的日志。我怀疑,我们最终会把日志中更注重作为一个商品化的基石,不论其是否以同样的方式实施的,我们经常谈论一个哈希表而不是纠结我们得到是不是具体某个细节的哈希表,例如线性或者带有什么什么其它变体哈希表。日志将成为一种大众化的接口,为大多数算法和其实现提升提供最好的保证和最佳的性能。变更日志101:表与事件的二相性。让我们继续聊数据库。数据库中存在着大量变更日志和表之间的二相性。这些日志有点类似借贷清单和银行的流程,数据库表就是当前的盈余表。如果你有大量的变更日志,你就可以使用这些变更用以创建捕获当前状态的表。这张表将记录每个关键点(日志中一个特别的时间点)的状态信息。这就是为什么日志是非常基本的数据结构的意义所在:日志可用来创建基本表,也可以用来创建各类衍生表。同时意味着可以存储非关系型的对象。这个流程也是可逆的:如果你正在对一张表进行更新,你可以记录这些变更,并把所有更新的日志发布到表的状态信息中。这些变更日志就是你所需要的支持准实时的克隆。基于此,你就可以清楚的理解表与事件的二相性:表支持了静态数据而日志捕获变更。日志的魅力就在于它是变更的完整记录,它不仅仅捕获了表的最终版本的内容,它还记录了曾经存在过的其它版本的信息。日志实质上是表历史状态的一系列备份。这可能会引起你对源代码的版本管理。源代码管理和数据库之间有密切关系。版本管理解决了一个大家非常熟悉的问题,那就是什么是分布式数据系统需要解决的—时时刻刻在变化着的分布式管理。版本管理系统通常以补丁的发布为基础,这实际上可能是一个日志。您可以直接对当前类似于表中的代码做出“快照”互动。你会注意到,与其他分布式状态化系统类似,版本控制系统当你更新时会复制日志,你希望的只是更新补丁并将它们应用到你的当前快照中。最近,有些人从Datomic–一家销售日志数据库的公司得到了一些想法。这些想法使他们对如何在他们的系统应用这些想法有了开阔的认识。当然这些想法不是只针对这个系统,他们会成为十多年分布式系统和数据库文献的一部分。这可能似乎有点过于理想化。但是不要悲观!我们会很快把它实现。请让我首先解释一下“数据集成”是什么意思,还有为什么我觉得它很重要,之后我们再来看看它和日志有什么关系。数据集成就是将数据组织起来,使得在与其有关的服务和系统中可以访问它们。“数据集成”(dataintegration)这个短语应该不止这么简单,但是我找不到一个更好的解释。而更常见的术语ETL通常只是覆盖了数据集成的一个有限子集(译注:ETL,Extraction-Transformation-Loading的缩写,即数据提取、转换和加载)——相对于关系型数据仓库。但我描述的东西很大程度上可以理解为,将ETL推广至实时系统和处理流程。你一定不会听到数据集成就兴趣盎然屏住呼吸,并且天花乱坠的想到关于大数据的概念,不过,我相信世俗的问题“让数据可被访问”是一个组织应该关注的有价值的事情。对数据的高效使用遵循一种马斯洛的需要层次理论。金字塔的基础部分包括捕获所有相关数据,能够将它们全部放到适当的处理环境(那个环境应该是一个奇妙的实时查询系统,或者仅仅是文本文件和python脚本)。这些数据需要以统一的方式建模,这样就可以方便读取和数据处理。如果这种以统一的方式捕获数据的基本需求得到满足,那么就可以在基础设施上以若干种方法处理这些数据——映射化简(MapReduce),实时查询系统,等等。很明显,有一点值得注意:如果没有可靠的、完整的数据流,Hadoop集群除了象昂贵的且难于安装的空间取暖器哪样外不会做更多事情了。一旦数据和处理可用,人们就会关心良好数据模型和一致地易于理解的语法哪些更细致的问题。最后,人们才会关注更加高级的处理-更好的可视化、报表以及处理和预测算法。以我的经验,大多数机构在数据金字塔的底部存在巨大的漏洞-它们缺乏可靠的、完整的数据流-而是打算直接跳到高级数据模型技术上。这样做完全是反着来做的。因此,问题是我们如何构建通过机构内所有数据系统的可靠的数据流。数据集成:两个并发症两种趋势使数据集成变得更困难。事件数据管道第一个趋势是增长的事件数据(eventdata)。事件数据记录的是发生的事情,而不是存在的东西。在web系统中,这就意味着用户活动日志,还有为了可靠的操作以及监控数据中心的机器的目的,所需要记录的机器级别的事件和统计数字。人们倾向称它们为“日志数据”,因为它们经常被写到应用的日志中,但是这混淆了形式与功能。这种数据位于现代web的中心:归根结底,Google的资产是由这样一些建立在点击和映像基础之上的相关管道所生成的——那也就是事件。这些东西并不是仅限于网络公司,只是网络公司已经完全数字化,所以它们更容易用设备记录。财务数据一直是面向事件的。RFID(无线射频识别)将这种跟踪能力赋予物理对象。我认为这种趋势仍将继续,伴随着这个过程的是传统商务活动的数字化。这种类型的事件数据记录下发生的事情,而且往往比传统数据库应用要大好几个数量级。这对于处理提出了重大挑战。专门的数据系统的爆发第二个趋势来自于专门的数据系统的爆发,通常这些数据系统在最近的五年中开始变得流行,并且可以免费获得。专门的数据系统是为OLAP,搜索,简单在线存储,批处理,图像分析,等等而存在的。更多的不同类型数据的组合,以及将这些数据存放到更多的系统中的愿望,导致了一个巨大的数据集成问题。日志结构数据流为了处理系统之间的数据流,日志是最自然的数据结构。其中的秘诀很简单:将所有组织的数据提取出来,并将它们放到一个中心日志,以便实时查阅。每个逻辑数据源都可以建模为它自己的日志。一个数据源可以是一个应用程序的事件日志(如点击量或者页面浏览量),或者是一个接受修改的数据库表。每个订阅消息的系统都尽可能快的从日志读取信息,将每条新的记录保存到自己的存储,并且提升其在日志中的地位。订阅方可以是任意一种数据系统——一个缓存,Hadoop,另一个网站中的另一个数据库,一个搜索系统,等等。例如,日志针对每个更改给出了逻辑时钟的概念,这样所有的订阅方都可以被测量。推导不同的订阅系统的状态也因此变得相对简单的多,因为每个系统都有一个读取动作的“时间点”。为了让这个显得更具体,我们考虑一个简单的案例,有一个数据库和一组缓存服务器集群。日志提供了一种同步更新所有这些系统,并推导出每一个系统的接触时间点的方法。我们假设写了一条日志X,然后需要从缓存做一次读取。如果我们想保证看到的不是陈旧的数据,我们只需保证没有从任何尚未复制X的缓存中读取即可。日志也起到缓存的作用,使数据生产与数据消费相同步。由于许多原因这个功能很重要,特别是在多个订阅方消费数据的速度各不相同的时候。这意味着一个订阅数据系统可以宕机,或者下线维护,之后重新上线以后再赶上来:订阅方按照自己控制的节拍来消费数据。批处理系统,如Hadoop或者是一个数据仓库,或许只是每小时或者每天消费一次数据,而实时查询系统可能需要及时到秒。由于无论是原始数据源还是日志,都没有各种目标数据系统的相关知识,因此消费方系统可以被添加和删除,而无需传输管道的变化。特别重要的是:目标系统只知道日志,不知道数据源系统的任何细节。消费方系统自身无需考虑数据到底是来自于一个RDBMS(关系型数据库管理系统RelationalDatabaseManagementSystem),一种新型的键值存储,或者它不是由任何形式的实时查询系统所生成的。这似乎是一个小问题,但实际上是至关重要的。这里我使用术语“日志”取代了“消息系统”或者“发布-订阅”,因为它在语义上更明确,并且对支持数据复制的实际实现这样的需求,有着更接近的描述。我发现“发布订阅”并不比间接寻址的消息具有更多的含义——如果你比较任何两个发布-订阅的消息传递系统的话,你会发现他们承诺的是完全不同的东西,而且大多数模型在这一领域都不是有用的。你可以认为日志是一种消息系统,它具有持久性保证和强大的订阅语义。在分布式系统中,这个通信模型有时有个(有些可怕的)名字叫做原子广播。值得强调的是,日志仍然只是基础设施。这并不是管理数据流这个故事的结束:故事的其余部分围绕着元数据,模式,兼容性,以及处理数据结构的所有细节及其演化。除非有一种可靠的,一般的方法来处理数据流运作,语义在其中总是次要的细节。在LinkedIn(SNS社交网站)在LinkedIn从集中式关系数据库向分布式系统集合转化的过程中,我看到这个数据集成问题迅速演变。现在主要的数据系统包括:搜索社交图谱Voldemort(键值存储)(译注:一种分布式数据库)Espresso(文档存储)推举引擎OLAP查询引擎(译注:OLAP联机分析技术)HadoopTerradataIngraphs(监控图表和指标服务)这些都是专门的分布式系统,在其专业领域提供先进的功能。这种使用日志作为数据流的思想,甚至在我到这里之前就已经与LinkedIn相伴了。我们开发的一个最早的基础设施之一,是一种称为databus的服务,它在我们早期的Oracle表上提供了一种日志缓存抽象,可伸缩订阅数据库修改,这样我们就可以很好支持我们的社交网络和搜索索引。我会给出一些历史并交代一下上下文。我首次参与到这些大约是在2008年左右,在我们转移键值存储之后。我的下一个项目是让一个工作中的Hadoop配置演进,并给其增加一些我们的推荐流程。由于缺乏这方面的经验,我们自然而然的安排了数周计划在数据的导入导出方面,剩下的时间则用来实现奇妙的预测算法。这样我们就开始了长途跋涉。我们本来计划是仅仅将数据从现存的Oracle数据仓库中剖离。但是我们首先发现将数据从Oracle中迅速取出是一种黑暗艺术。更糟的是,数据仓库的处理过程与我们为Hadoop而计划的批处理生产过程不适合——其大部分处理都是不可逆转的,并且与即将生成的报告具体相关。最终我们采取的办法是,避免使用数据仓库,直接访问源数据库和日志文件。最后,我们为了加载数据到键值存储并生成结果,实现了另外一种管道。这种普通的数据复制最终成为原始开发项目的主要内容之一。糟糕的是,在任何时间任意管道都有一个问题,Hadoop系统很大程度上是无用的——在错误的数据基础上运行奇特的算法,只会产生更多的错误数据。虽然我们已经以一种通用的方式创建事物,但是每个数据源都需要自定义配置安装。这也被证明是巨量错误与失败的根源。我们在Hadoop上实现的网站功能已经开始流行起来,同时我们发现我们有一长串感兴趣的工程师。每个用户都有他们想要集成的一系列系统,他们想要的一系列新数据源。有些东西在我面前开始渐渐清晰起来。首先,我们已建成的通道虽然有一些杂乱,但实质上它们是很有价值的。在采用诸如Hadoop的新的处理系统生成可用数据的过程,它开启了大量的可能性。基于这些数据过去很难实现的计算,如今变为可能。许多新的产品和分析技术都来源于把分片的数据放在一起,这些数据过被锁定在特定的系统中。第二,众所周知,可靠的数据加载需要数据通道的深度支持。如果我们可以捕获所有我们需要的结构,我就就可以使得Hadoop数据全自动的加载,这样就不需要额外的操作来增加新的数据源或者处理模式变更–数据就会自动的出现在HDFS,Hive表就会自动的生成对应于新数据源的恰当的列。第三,我们的数据覆盖率仍然非常低。如果你查看存储于Hadoop中的可用的Linked数据的全部百分比,它仍然是不完整的。花费大量的努力去使得各个新的数据源运转起来,使得数据覆盖度完整不是一件容易的事情。我们正在推行的,为每个数据源和目标增建客户化数据加载,这种方式很显然是不可行的。我们有大量的数据系统和数据仓库。把这些系统和仓库联系起来,就会导致任意一对系统会产生如下所示的客户化通道。需要注意的是:数据是双向流动的:例如许多系统诸如数据库和Hadoop既是数据转化的来源又是数据转化的目的地。这就意味着我们我们不必为每个系统建立两个通道:一个用于数据输入,一个用于数据输出。这显然需要一大群人,而且也不具有可操作性。随着我们接近完全连接,最终我们将有差不多O(N2)条管道。替代的,我们需要像这样通用的东西:我们需要尽可能的将每个消费者与数据源隔离。理想情形下,它们应该只与一个单独的数据仓库集成,并由此让他们能访问到所有东西。这个思想是增加一个新的数据系统——或者它是一个数据源或者它是一个数据目的地——让集成工作只需连接到一个单独的管道,而无需连接到每个数据消费方。这种经历使得我关注创建Kafka来关联我们在消息系统所见的与数据库和分布式系统内核所发布的日志。我们希望一些实体作为中心的通道,首先用于所有的活动数据,逐步的扩展到其他用途,例如Hadoop外的数据实施,数据监控等。在相当长的时间内,Kafka是独一无二的底层产品,它既不是数据库,也不是日志文件收集系统,更不是传统的消息系统。但是最近Amazon提供了非常类似Kafka的服务,称之为Kinesis.相似度包括了分片处理的方式,数据的保持,甚至包括在KafkaAPI中,有点特别的高端和低端消费者分类。我很开心看到这些,这表明了你已经创建了很好的底层协议,AWS已经把它作为服务提供。他们对此的期待与我所描述的吻合:通道联通了所有的分布式系统,诸如DynamoDB,RedShift,S3等,它同时作为使用EC2进行分布式流处理的基础。与ETL和数据仓库的关系我们再来聊聊数据仓库。数据仓库是清洗和归一数据结构用于支撑数据分析的仓库。这是一个伟大的理念。对不熟悉数据仓库概念的人来说,数据仓库方法论包括了:周期性的从数据源抽取数据,把它们转化为可理解的形式,然后把它导入中心数据仓库。对于数据集中分析和处理,拥有高度集中的位置存放全部数据的原始副本是非常宝贵的资产。在高层级上,也许你抽取和加载数据的顺序略微调整,这个方法论不会有太多变化,无论你使用传统的数据仓库Oracle还是Teradata或者Hadoop。数据仓库是极其重要的资产,它包含了原始的和规整的数据,但是实现此目标的机制有点过时了。对以数据为中心的组织关键问题是把原始的归一数据联结到数据仓库。数据仓库是批处理的基础查询:它们适用于各类报表和临时性分析,特别是当查询包含了简单的计数、聚合和过滤。但是如果一个批处理系统仅仅包含了原始的完整的数据的数据仓库,这就意味着这些数据对于实时数据处理、搜索索引和系统监控等实时的查询是不可用的。依我之见,ETL包括两件事:首先,它是抽取和数据清洗过程–特别是释放被锁在组织的各类系统中的数据,移除系统专有的无用物。第二,依照数据仓库的查询重构数据。例如使其符合关系数据库类型系统,强制使用星号、雪花型模式,或者分解为高性能的柱状格式等。合并这两者是有困难的。这些规整的数据集应当可以在实时或低时延处理中可用,也可以在其它实施存储系统索引。在我看来,正是因为这个原因有了额外好处:使得数据仓库ETL更具了组织级的规模。数据仓库的精典问题是数据仓库负责收集和清洗组织中各个组所生成的全部数据。各组织的动机是不同的,数据的生产者并不知晓在数据仓库中数据的使用情况,最终产生的数据很难抽取,或者需要花费规模化的转化才可以转化为可用的形式。当然,中心团队不可能恰到好处的掌握规模,使得这规模刚好与组织中其它团队相匹配,因此数据的覆盖率常常差别很大,数据流是脆弱的同时变更是缓慢的。较好的方法是有一个中心通道,日志和用于增加数据的定义良好的API。与通道集成的且提供良好的结构化的数据文件的职责依赖于数据的生产者所生成的数据文件。这意味着在设计和实施其它系统时应当考虑数据的输出以及输出的数据如何转化为结构良好的形式并传递给中心通道。增加新的存储系统倒是不必因为数据仓库团队有一个中心结点需要集成而关注数据仓库团队。数据仓库团队仅需处理简单的问题,例如从中心日志中加载结构化的数据,向其它周边系统实施个性化的数据转化等。如图所示:当考虑在传统的数据仓库之外增加额外的数据系统时,组织结构的可扩展性显得尤为重要。例如,可以考虑为组织的完整的数据集提供搜索功能。或者提供二级的数据流监控实时数据趋势和告警。无论是这两者中的哪一个,传统的数据仓库架构甚至于Hadoop聚簇都不再适用。更糟的是,ETL的流程通道的目的就是支持数据加载,然而ETL似乎无法输出到其它的各个系统,也无法通过引导程序,使得这些外围的系统的各个架构成为适用于数据仓库的重要资产。这就不难解释为什么组织很难轻松的使用它的全部数据。反之,如果组织已建立起了一套标准的、结构良好的数据,那么任何新的系统要使用这些数据仅仅需要与通道进行简单的集成就可以实现。这种架构引出了数据清理和转化在哪个阶段进行的不同观点:由数据的生产者在把数据增加到公司全局日志之前。在日志的实时转化阶段进行,这将会产生一个新的转化日志。在向目标系统加载数据时,做为加载过程的一部分进行。理想的模形是:由数据的生产者在把数据发布到日志之前对数据进行清理。这样可以确保数据的权威性,不需要维护其它的遗留物例如为数据产生的特殊处理代码或者维护这些数据的其它的存储系统。这些细节应当由产生数据的团队来处理,因为他们最了解他们自己的数据。这个阶段所使用的任何逻辑都应该是无损的和可逆的。任何可以实时完成的增值转化类型都应当基于原始日志进行后期处理。这一过程包括了事件数据的会话流程,或者增加大众感兴趣的衍生字段。原始的日志仍然是可用的,但是这种实时处理产生的衍生日志包含了参数数据。最终,只有针对目标系统的聚合需要做了加载流程的一部分。它包括了把数据转化成特定的星型或者雪花状模式,从而用于数据仓库的分析和报表。因为在这个阶段,大部分自然的映射到传统的ETL流程中,而现在它是在一个更加干净和规整的数据流集在进行的,它将会更加的简单。日志文件和事件我们再来聊聊这种架构的优势:它支持解耦和事件驱动的系统。在网络行业取得活动数据的典型方法是把它记为文本形式的日志,这些文本文件是可分解进入数据仓库或者Hadoop,用于聚合和查询处理的。由此产生的问题与所有批处理的ETL的问题是相同的:它耦合了数据流进入数据仓库系统的能力和流程的调度。在LinkedIn中,我们已经以中心日志的方式构建了事件数据处理。我们正在使用Kafka做为中心的、多订阅者事件日志。我们已经定义了数百种事件类型,每种类型都会捕获用于特定类型动作的独特的属性。这将会覆盖包括页面视图、表达式、搜索以及服务调用、应用异常等方方面面。为了进一步理解这一优势:设想一个简单的事务–在日志页面显示已发布的日志。这个日志页面应当只包括显示日志所需要的逻辑。然而,在相当多的动态站点中,日志页面常常变的添加了很多与显示日志无关的逻辑。例如,我们将对如下的系统进行集成:需要把数据传送到Hadoop和数据仓库中用于离线数据处理。需要对视图进行统计,确保视图订阅者不会攻击一些内容片段。需要聚合这些视图,视图将用于作业发布者的分析页面显示。需要记录视图以确保我们为作业推荐的使用者提供了恰当的印象覆盖,我们不想一次次的重复同样的事情。推荐系统需要记录日志用于正确的跟踪作业的普及度。等等。不久,简单的作业显示变得相当的复杂。我们增加了作业显示的其它终端–移动终端应用等–这些逻辑必须继续存在,复杂度不断的增加。更糟的是我们需要与之做接口交互的系统现在是错综复杂的–在为显示日作业而工作的工程师们需要知晓多个其它系统和它们的特征,才可以确保它们被正确的集成了。这仅仅是问题的简单版本,真实的的应用系统只会更加的复杂。“事件驱动”的模式提供了一种简化这类问题的机制。作业显示页面现在只显示作业并记录与正在显示的作业,作业订阅者相关的其它属性,和其它与作业显示相关的其它有价值的属性。每个与此相关的其它系统诸如推荐系统、安全系统、作业推送分析系统和数据仓库,所有这些只是订阅种子文件,并进行它们的操作。显示代码并不需要关注其它的系统,也不需要因为增加了数据的消费者而相应的进行变更。构建可伸缩的日志当然,把发布者与订阅者分离不再是什么新鲜事了。但是如果你想要确保提交日志的行为就像多个订阅者实时的分类日志那样记录网站发生的每件事时,可扩展性就会成为你所面临的首要挑战。如果我们不能创建快速、高性价比和可扩展性灵活的日志以满足实际的可扩展需求,把日志做为统一的集成机制不再是美好的想像,人们普遍认为分布式日志是缓慢的、重量经的概念(并且通常会把它仅仅与“原数据”类型的使用联系起来,对于这类使用Zookeeper可以适用)。但是深入实现并重点关注分类记录大规模的数据流,这种需求是不切实际的。在LinkedIn,我们现在每天通过Kafka运行着超过600亿个不同的消息写入点(如果统计镜相与数据中心之间的写入,那么这个数字会是数千亿。)我们在Kafk中使用了一些小技巧来支持这种可扩展性:日志分片通过批处理读出和写入优化吞吐力规避无用的数据复制。为了确保水平可扩展性,我们把日志进行切片:每个切片都是一篇有序的日志,但是各片之间没有全局的次序(这个有别于你可能包含在消息中的挂钟时间)。把消息分配到特定的日志片段这是由写入者控制的,大部分使用者会通过用户ID等键值来进行分片。分片可以把日志追加到不存在协作的片段之间,也可以使系统的吞吐量与Kafka聚簇大小成线性比例关系。每个分片都是通过可配置数量的复制品复制的,每个复制品都有分片的一份完全一致的拷贝。无论何时,它们中的任一个都可以做为主分片,如果主分片出错了,任何一个复制品都可以接管并做为主分片。缺少跨分片的全局顺序是这个机制的局限性,但是我们不认为它是最主要的。事实上,与日志的交互主要来源于成百上千个不同的流程,以致于对于它们的行为排一个总体的顺序是没什么意义的。相反,我们可以确保的是我们提供的每个分片都是按顺序保留的。Kafka保证了追加到由单一发送者送出的特定分片会按照发送的顺序依次处理。日志,就像文件系统一样,是容易优化成线性可读可写的样式的。日志可以把小的读入和写出组合成大的、高吞吐量的操作。Kafka一直至立于实现这一优化目标。批处理可以发生在由客户端向服务器端发送数据、写入磁盘;在服务器各端之间复制;数据传递给消费者和确认提交数据等诸多环节。最终,Kafka使用简单的二进制形式维护内存日志,磁盘日志和网络数据传送。这使得我们可以使用包括“0数据复制传送”在内的大量的优化机制。这些优化的积累效应是你常常进行的写出和读入数据的操作可以在磁盘和网络上得到支持,甚至于维护内存以外的大量数据集。到此为止,我只是描述从端到端数据复制的理想机制。但是在存储系统中搬运字节不是所要讲述内容的全部。最终我们发现日志是流的另一种说法,日志是流处理的核心。但是,等等,什么是流处理呢?如果你是90年代晚期或者21世纪初数据库文化或者数据基础架构产品的爱好者,那么你就可能会把流处理与建创SQL引擎或者创建“箱子和箭头”接口用于事件驱动的处理等联系起来。如果你关注开源数据库系统的大量出现,你就可能把流处理和一些开源数据库系统关联起来,这些系统包括了:Storm,Akka,S4和Samza.但是大部分人会把这些系统作为异步消息处理系统,这些系统与支持群集的远程过程调用层的应用没什么差别(而事实上在开源数据库系统领域某些方面确实如此)。这些视图都有一些局限性。流处理与SQL是无关的。它也局限于实时流处理。不存在内在的原因限制你不能处理昨天的或者一个月之前的流数据,且使用多种不同的语言表达计算。我把流处理视为更广泛的概念:持续数据流处理的基础架构。我认为计算模型可以像MapReduce或者分布式处理架构一样普遍,但是有能力处理低时延的结果。处理模型的实时驱动是数据收集方法。成批收集的数据是分批处理的。数据是不断收集的,它也是按顺序不断处理的。美国的统计调查就是成批收集数据的良好典范。统计调查周期性的开展,通过挨门挨户的走访,使用蛮力发现和统计美国的公民信息。1790年统计调查刚刚开始时这种方式是奏效的。那时的数据收集是批处理的,它包括了骑着马悠闲的行进,把信息写在纸上,然后把成批的记录传送到人们统计数据的中心站点。现在,在描述这个统计过程时,人们立即会想到为什么我们不保留出生和死亡的记录,这样就可以产生人口统计信息这些信息或是持续的或者是其它维度的。这是一个极端的例子,但是大量的数据传送处理仍然依赖于周期性的转储,批量转化和集成。处理大容量转储的唯一方法就是批量的处理。但是随着这些批处理被持续的供给所取代,人们自然而然的开始不间断的处理以平滑的处理所需资源并且消除延迟。例如LinkedIn几乎没有批量数据收集。大部分的数据或者是活动数据或者是数据库变更,这两者都是不间断发生的。事实上,你可以想到的任何商业,正如:JackBauer告诉我们的,低层的机制都是实时发生的不间断的流程事件。数据是成批收集的,它总是会依赖于一些人为的步骤,或者缺少数字化或者是一些自动化的非数字化流程处理的遗留信息。当传送和处理这些数据的机制是邮件或者人工的处理时,这一过程是非常缓慢的。首轮自动化总是保持着最初的处理形式,它常常会持续相当长的时间。每天运行的批量处理作业常常是模拟了一种一天的窗口大小的不间断计算。当然,低层的数据也经常变化。在LinkedIn,这些是司空见贯的,并且使得它们在Hadoop运转的机制是有技巧的,所以我们实施了一整套管理增量的Hadoop工作流的架构。由此看来,对于流处理可以有不同的观点。流处理包括了在底层数据处理的时间概念,它不需要数据的静态快照,它可以产生用户可控频率的输出,而不用等待数据集的全部到达。从这个角度上讲,流处理就是广义上的批处理,随着实时数据的流行,会儿更加普遍。这就是为什么从传统的视角看来流处理是利基应用。我个人认为最大的原因是缺少实时数据收集使得不间断的处理成为了学术性的概念。我想缺少实时数据收集就像是商用流处理系统注定的命运。他们的客户仍然需要处理面向文件的、每日批量处理ETL和数据集成。公司建设流处理系统关注的是提供附着在实时数据流的处理引擎,但是最终当时极少数人真正使用了实时数据流。事实上,在我在LinkedIn工作的初期,有一家公司试图把一个非常棒的流处理系统销售给我们,但是因为当时我们的全部数据都按小时收集在的文件里,当时我们提出的最好的应用就是在每小时的最后把这些文件输入到流处理系统中。他们注意到这是一个普遍性的问题。这些异常证明了如下规则:流处理系统要满足的重要商业目标之一是:财务,它是实时数据流已具备的基准,并且流处理已经成为了瓶颈。甚至于在一个健康的批处理系统中,流处理作为一种基础架构的实际应用能力是相当广泛的。它跨越了实时数据请求-应答服务和离线批量处理之间的鸿沟。现在的互联网公司,大约25%的代码可以划分到这个类型中。最终这些日志解决了流处理中绝大部分关键的技术问题。在我看来,它所解决的最大的问题是它使得多订阅者可以获得实时数据。对这些技术细节感兴趣的朋友,我们可以用开源的Samza,它是基于这些理念建设的一个流处理系统。这些应用的更多技术细节我们在此文档中有详细的描述。数据流图流处理最有趣的角度是它与流处理系统内部无关,但是与之密切相关的是如何扩展了我们谈到的早期数据集成的数据获取的理念。我们主要讨论了基础数据的获取或日志–事件和各类系统执行中产生的数据等。但是流处理允许我们包括了计算其它数据的数据。这些衍生的数据在消费者看来与他们计算的原始数据没什么差别。这些衍生的数据可以按任意的复杂度进行压缩。让我们再深入一步。我们的目标是:流处理作业可以读取任意的日志并把日志写入到日志或者其它的系统中。他们用于输入输出的日志把这些处理关联到一组处理过程中。事实上,使用这种样式的集中日志,你可以把组织全部的数据抓取、转化和工作流看成是一系列的日志和写入它们的处理过程。流处理器根本不需要理想的框架:它可能是读写日志的任何处理器或者处理器集合,但是额外的基础设施和辅助可以提供帮助管理处理代码。日志集成的目标是双重的:首先,它确保每个数据集都有多个订阅者和有序的。让我们回顾一下状态复制原则来记住顺序的重要性。为了使这个更加具体,设想一下从数据库中更新数据流–如果在处理过程中我们把对同一记录的两次更新重新排序,可能会产生错误的输出。TCP之类的链接仅仅局限于单一的点对点链接,这一顺序的持久性要优于TCP之类的链接,它可以在流程处理失败和重连时仍然存在。第二,日志提供了流程的缓冲。这是非常基础的。如果处理流程是非同步的,那么上行生成流数据的作业比下行消费流数据的作业运行的更快。这将会导致处理流程阻塞,或者缓冲数据,或者丢弃数据。丢弃数据并不是可行的方法,阻塞将会导致整个流程图立即停止。日志实际上是一个非常大的缓冲,它允许流程重启或者停止但不会影响流程图其它部分的处理速度。如果要把数据流扩展到更大规模的组织,如果处理作业是由多个不同的团队提供的,这种隔离性是极其重的。我们不能容忍一个错误的作业引发后台的压力,这种压力会使得整个处理流程停止。Storm和Sama这两者都是按非同步方式设计的,可以使用Kafka或者其它类似的系统作为它们的日志。有状态的实时流处理一些实时流处理在转化时是无状态的记录。在流处理中大部分的应用会是相当复杂的统计、聚合、不同窗口之间的关联。例如有时人们想扩大包含用户操作信息的事件流(一系列的单击动作)–实际上关联了用户的单击动作流与用户的账户信息数据库。不变的是这类流程最终会需要由处理器维护的一些状态信息。例如数据统计时,你需要统计到目前为止需要维护的计数器。如果处理器本身失败了,如何正确的维护这些状态信息呢?最简单的替换方案是把这些状态信息保存在内存中。但是如果流程崩溃,它就会丢失中间状态。如果状态是按窗口维护的,流程就会回退到日志中窗口开始的时间点上。但是,如果统计是按小时进行的,那么这种方式就会变得不可行。另一个替换方案是简单的存储所有的状态信息到远程的存储系统,通过网络与这些存储关联起来。这种机制的问题是没有本地数据和大量的网络间通信。我们如何支持处理过程可以像表一样分区的数据呢?回顾一下关于表和日志二相性的讨论。这一机制提供了工具把数据流转化为与处理过程协同定位的表,同时也提供了这些表的容错处理的机制。流处理器可以把它的状态保存在本地的表或索引–bdb,或者leveldb,甚至于类似于Lucene或fastbit一样不常见的索引。这些内容存储在它的输入流中(或许是使用任意的转化)。生成的变更日志记录了本地的索引,它允许存储事件崩溃、重启等的状态信息。流处理提供了通用的机制用于在本地输入流数据的随机索引中保存共同分片的状态。当流程运行失败时,它会从变更日志中恢复它的索引。每次备份时,日志把本地状态转化成一系列的增量记录。这种状态管理的方法有一个优势是把处理器的状态也做为日志进行维护。我们可以把这些日志看成与数据库表相对应的变更日志。事实上,这些处理器同时维护着像共同分片表一样的表。因为这些状态它本身就是日志,其它的处理器可以订阅它。如果流程处理的目标是更新结点的最后状态,这种状态又是流程的输出,那么这种方法就显得尤为重要。为了数据集成,与来自数据库的日志关联,日志和数据库表的二象性就更加清晰了。变更日志可以从数据库中抽取出来,日志可以由不同的流处理器(流处理器用于关联不同的事件流)按不同的方式进行索引。我们可以列举在Samza中有状态流处理管理的更多细节和大量实用的例子。日志压缩当然,我们不能奢望保存全部变更的完整日志。除非想要使用无限空间,日志不可能完全清除。为了澄清它,我们再来聊聊Kafka的实现。在Kafka中,清理有两种选择,这取决于数据是否包括关键更新和事件数据。对于事件数据,Kafka支持仅维护一个窗口的数据。通常,配置需要一些时间,窗口可以按时间或空间定义。虽然对于关键数据而言,完整日志的重要特征是你可以重现源系统的状态信息,或者在其它的系统重现。随着时间的推移,保持完整的日志会使用越来越多的空间,重现所耗费的时间越来越长。因些在Kafka中,我们支持不同类型的保留。我们移除了废弃的记录(这些记录的主键最近更新过)而不是简单的丢弃旧日志。我们仍然保证日志包含了源系统的完整备份,但是现在我们不再重现原系统的全部状态,而是仅仅重现最近的状态。我们把这一特征称为日志压缩。我们最后要讨论的是在线数据系统设计中日志的角色。在分布式数据库数据流中日志的角色和在大型组织机构数据完整中日志的角色是相似的。在这两个应用场景中,日志是对于数据源是可靠的,一致的和可恢复的。组织如果不是一个复杂的分布式数据系统呢,它究竟是什么?如果换个角度,你可以看到把整个组织系统和数据流看做是单一的分布式数据系统。你可以把所有的子查询系统(诸如Redis,SOLR,Hive表等)看成是数据的特定索引。你可以把Storm或Samza一样的流处理系统看成是发展良好的触发器和视图具体化机制。我已经注意到,传统的数据库管理人员非常喜欢这样的视图,因为它最终解释了这些不同的数据系统到底是做什么用的–它们只是不同的索引类型而已。不可否认这类数据库系统现在大量的出现,但是事实上,这种复杂性一直都存在。即使是在关系数据库系统的鼎盛时期,组织中有大量的关系数据库系统。或许自大型机时代开始,所有的数据都存储在相同的位置,真正的集成是根本不存在的。存在多种外在需求,需要把数据分解成多个系统,这些外在需求包括:规模、地理因素、安全性,性能隔离是最常见的因素。这些需求都可以由一个优质的系统实现:例如,组织可以使用单一的Hadoop聚簇,它包括了全部的数据,可以服务于大型的和多样性的客户。因此在向分布式系统变迁的过程中,已经存在一种处理数据的简便的方法:把大量的不同系统的小的实例聚合成为大的聚簇。许多的系统还不足以支持这一方法:因为它们不够安全,或者性能隔离性得不到保证,或者规模不符合要求。不过这些问题都是可以解决的。依我之见,不同系统大量出现的原因是建设分布式数据库系统很困难。通过削减到单一的查询或者用例,每个系统都可以把规模控制到易于实现的程度。但是运行这些系统产生的复杂度依然很高。未来这类问题可能的发展趋势有三种:第一种可能是保持现状:孤立的系统还会或长或短的持续一段时间。这是因为建设分布式系统的困难很难克服,或者因为孤立系统的独特性和便捷性很难达到。基于这些原因,数据集成的核心问题仍然是如何恰当的使用数据。因此,集成数据的外部日志非常的重要。第二种可能是重构:具备通用性的单一的系统逐步融合多个功能形成超极系统。这个超级系统表面看起来类似关系数据库系统,但是在组织中你使用时最大的不同是你只需要一个大的系统而不是无数个小系统。在这个世界里,除了在系统内已解决的这个问题不存在什么真正的数据集成问题。我想这是因为建设这样的系统的实际困难。虽然另一种可能的结果对于工程师来说是很有吸引力的。新一代数据库系统的特征之一是它们是完全开源的。开源提供了第三种可能性:数据基础架构不必打包成服务集或者面向应用的系统接口。在Java栈中,你可以看到在一定程度上,这种状况已经发生了。分类计价吗?Zookeeper用于处理多个系统之间的协调,或许会从诸如Helix或者Curator等高级别的抽象中得到一些帮助。Mesos和YARN用于处理流程可视化和资源管理。Lucene和LevelDB等嵌入式类库做为索引。Netty,Jetty和Finagle,rest.li等封装成高级别的用于处理远程通信。Avro,ProtocolBuffers,Thrift和umpteenzillion等其它类库用于处理序列化。Kafka和Bookeeper提供支持日志。如果你把这些堆放在一起,换个角度看,它有点像是简化版的分布式数据库系统工程。你可以把这些拼装在一起,创建大量的可能的系统。显而易见,现在探讨的不是最终用户所关心的API或者如何实现,而是在不断多样化和模块化的过程中如何设计实现单一系统的途径。因为随着可靠的、灵活的模块的出现,实施分布式系统的时间周期由年缩减为周,聚合形成大型整体系统的压力逐步消失。日志文件在系统结构中的地位那些提供外部日志的系统如今已允许个人电脑抛弃他们自身复杂的日志系统转而使用共享日志。在我看来,日志可以做到以下事情:通过对节点的并发更新的排序处理数据的一致性(无论在及时还是最终情况下)提供节点之间的数据复制提供”commit“语法(只有当写入器确保数据不会丢失时才会写入)位系统提供外部的数据订阅资源提供存储失败的复制操作和引导新的复制操作的能力处理节点间的数据平衡这实际上是一个数据分发系统最重要的部分,剩下的大部分内容与终端调用的API和索引策略相关。这正是不同系统间的差异所在,例如:一个全文本查询语句需要查询所有的分区,而一个主键查询只需要查询负责键数据的单个节点就可以了。下面我们来看下该系统是如何工作的。系统被分为两个逻辑区域:日志和服务层。日志按顺序捕获状态变化,服务节点存储索引提供查询服务需要的所有信息(键-值的存储可能以B-tree或SSTable的方式进行,而搜索系统可能存在与之相反的索引)。写入器可以直接访问日志,尽管需要通过服务层代理。在写入日志的时候会产生逻辑时间戳(即log中的索引),如果系统是分段式的,那么就会产生与段数目相同数量的日志文件和服务节点,这里的数量和机器数量可能会有较大差距。服务节点订阅日志信息并将写入器按照日志存储的顺序尽快应用到它的本地索引上。客户端只要在查询语句中提供对应的写入器的时间戳,它就可以从任何节点中获取”读写“语义。服务节点收到该查询语句后会将其中的时间戳与自身的索引比较,如果必要,服务节点会延迟请求直到对应时间的索引建立完毕,以免提供旧数据。服务节点或许根本无需知道”控制“或”投标选择(leaderelection)“的概念,对很多简单的操作,服务节点可以爱完全脱离领导的情况下提供服务,日志即是信息的来源。分发系统所需要做的其中一个比较复杂的工作,就是修复失败节点并移除几点之间的隔离。保留修复的数据并结合上各区域内的数据快照是一种较为典型的做法,它与保留完整的数据备份并从垃圾箱内回收日志的做法几乎等价。这就使得服务层简单了很多,日志系统也更有针对性。有了这个日志系统,你可以订阅到API,这个API提供了把ETL提供给其它系统的数据内容。事实上,许多系统都可以共享相同的日志同时提供不同的索引,如下所示:这样一个以日志为中心的系统是如何做到既数据流的提供者又同时加载其它系统的数据的呢?因为流处理器既可以消费多个输入的数据流,随后又可以通过其它系统对数据做索引为它们提供服务。这个系统的视图可以清晰的分解到日志和查询API,因为它允许你从系统的可用性和一致性角度分解查询的特征。这可以帮助我们对系统进行分解,并理解那些并没按这种方式设计实施的系统。虽然Kafka和Bookeeper都是一致性日志,但这不是必须的,也没什么意义。你可以轻松的把Dynamo之类的数据构分解为一致性的AP日志和键值对服务层。这样的日志使用起来灵活,因为它重传了旧消息,像Dynamo一样,这样的处理取决于消息的订阅者。在很多人看来,在日志中另外保存一份数据的完整复本是一种浪费。事实上,虽然有很多因素使得这件事并不困难。首先,日志可以是一种有效的存储机制。我们在Kafka生产环境的服务器上存储了5TB的数据。同时有许多的服务系统需要更多的内存来提供有效的数据服务,例如文本搜索,它通常是在内存中的。服务系统同样也需样硬盘的优化。例如,我们的实时数据系统或者在内存外提供服务或者使用固态硬盘。相反,日志系统只需要线性的读写,因此,它很乐于使用TB量级的硬盘。最终,如上图所示,由多个系统提供的数据,日志的成本分摊到多个索引上,这种聚合使得外部日志的成本降到了最低点。LinkedIn就是使用了这种方式实现它的多个实时查询系统的。这些系统提供了一个数据库(使用数据总线做为日志摘要,或者从Kafka去掉专用的日志),这些系统在顶层数据流上还提供了特殊的分片、索引和查询功能。这也是我们实施搜索、社交网络和OLAP查询系统的方式。事实上这种方式是相当普遍的:为多个用于实时服务的服务系统提供单一的数据(这些来自Hadoop的数据或是实时的或是衍生的)。这种方式已被证实是相当简洁的。这些系统根本不需要外部可写入的API,Kafka和数据库被用做系统的记录和变更流,通过日志你可以查询系统。持有特定分片的结点在本地完成写操作。这些结点盲目的把日志提供的数据转录到它们自己的存储空间中。通过回放上行流日志可以恢复转录失败的结点。这些系统的程度则取决于日志的多样性。一个完全可靠的系统可以用日志来对数据分片、存储结点、均衡负载,以及用于数据一致性和数据复制等多方面。在这一过程中,服务层实际上只不过是一种缓存机制,这种缓存机制允许直接写入日志的流处理。结束语如果你对于本文中所谈到的关于日志的大部内容,如下内容是您可以参考的其它资料。对于同一事务人们会用不同的术语,这会让人有一些困惑,从数据库系统到分布式系统,从各类企业级应用软件到广阔的开源世界。无论如何,在大方向上还是有一些共同之处。
“成功不是偶然,而是因为你把握住了一次偶然的机会。”——KevinGeary为什么别人做网站赚钱了,而我做网站却颗粒无收呢?在中国存在着数千万计的网站,但是绝大多数的站长都在不断的思考着这样的一个问题。那么,到底是为什么呢,作为一名从业10年的老鸟来告诉你下面的一些认知。一:你的兴趣不是别人的爱好我们常常说一句话:人各有志,每个人都有自身不同的志向,同样每个人的爱好、喜好也都是不同的。你所喜欢的,别人未必就钟意,很多人做网站往往都是凭借个人喜好来选择。你可能会说:中国人这么多,总有人的爱好与我是相同的,这一点也不否认,否则就没有:志同道合者一说了。但是,当你将这些志向进一步划分到不同的点呢?这个时候,就是一个分歧和选择,同样是那句话:你说喜欢的,不是别人的爱好。一个非常浅显的例子:为什么有的论坛某些版块非常火热,而有些版块又异常冷清呢?这是一个值得深思的话题,如果将这些版块全部带动起来,那么你离成功也就不远了。哪怕一个版块中,每天只产生:30个互动,但是有十个版块,那么就是300个互动,对于一个地方社区来讲,也算是成功了。然而,绝大多数的论坛,连这十分之一的互动量都没有。二:你所走的路别人早就走过了“芈月传”中有一集讨论的是秦国到底是攻韩国,还是伐蜀国的问题,当所有人争执不休的时候。幼子嬴稷做出的选择是:选择人少的一方来攻打。当赢驷询问嬴稷为什么,他说:大多数人知道的套路,敌人也早就知道了。做网站同样如此,你所选择的,和你所要走的,和走过的路,别人早就走过了。你再走一遍,永远也只是跟在别人的身后走,别人都有防备了,你还怎么打下这片江山呢?当然,我们不排除很多成功的站长,都是走了其他人走过的路,但是一块蛋糕就那么大,当所有人都哄抢的时候,又有多少人有机会得到呢?嗯,除非你膀大腰圆,五大三粗,才可以有一席之地吧。三:做着人心不足蛇吞象的蠢事你做网站的初衷是什么?很多人肯定幻想过:做了网站,我就可以暴富了,过几个月我就可以走上人生巅峰,抱得美人归了吧?在SEO诊断咨询中,经常有人这样问我:做了你的诊断,我的网站权重能达到5吗?而从不去说:我的网站有编辑、有技术、有推广团队,如果配合没问题的情况下,权重能到5吗?说了这么多,重点在哪里呢?一个人24小时的不舍昼夜,也抵不过一支团队的力量,何况世界上都不存在这样的人。你所期望的,总是与你能给的所成正比,不贪求,不奢望的做好眼前该做的事,才是最正确的选择。昨天有一家北京的旅行社网站,跟我说:我的网站做了你们的诊断,能保证带来多少流量?我回答他说:“如果做了SEO诊断,只要能给你带来几个客户,你就稳赚不赔了不是吗。”在我们的诊断客户中,有一家福建地区的IT网站,从0起步,到日10WIP只用了半年,如果换算成RMB,该有多少呢?可是我们的方案也仅仅是收了几千块而已,嗯,当然,我个人还收到了一盒很清香的茶叶作为感谢礼。四:铁公鸡应当远离互联网有些人花钱恨不得将一块钱都要分成两半来花,有些站长就是如此:抱着富翁的梦,却做着摆地摊的活(无歧视),结果是什么?这个不用说了。不少站长,尤其是个人站长、小企业网站都是如此,流动资金少,我们都理解,但是如果最基本的保障都没有,那么就不要在这里耽误时间了。你承诺你的房子质量肯定没问题,但是好比小区若无绿化,无公共设置,无周边配套,有多少人会去买?现在的人的生活都是追求质量的。做网站,需要满足什么条件?只要是成功的站长都会说:网站稳定流畅、网站优化至少不存在明显的大问题,甚至说:每一个细节都要求做到最好!而铁公鸡呢?往往都是选择哪些所谓的“物美价廉”,在这个社会中,有多少东西,是真的物美价廉呢?每一个物美价廉的背后,都有着更多不可告人的秘密。笔者前段时间,尝试用了一款“免费软件”,结果为电脑带来了清理不掉的弹窗,杀毒都被强制关闭了。
现在竞争日益强烈,想在同行中更被重视,就要在网站建设中不在小家子气,还是一种比较简单的模式,首页、内容页、栏目页,简单的组合一下就是一个网站。 颜色和图片加上文字组合在一起的网站无法满足用户,现在的用户都在用挑剔的眼光去看待事物,这就导致网站设计不仅仅要体现企业的介绍,还要运用多角度的思维方式来构建网站框架,排版和图片文字的搭配使用,响应式的设计,动画效果,来提升网站的气质和品质。 继续“主要看气质”的话题,无论是人还是事物,都存在着一种与生俱来的气质,奇亿小编在前几天写过一篇关于这句网络热词营销话题的文章,今天就来谈谈网站建设提升气质的方法。 一个网站能否做得耐人寻味,关键在于“气质”,它是一种由内而外散发出来的吸引力,同时也是企业形象的体现,譬如网站建设公司,若连企业自身的网站都做得毫无看点,那么又有哪个用户愿意相信你做的网站呢?可见,网站气质与带给用户的印象以及体验效果是息息相关的,企业可从几个方面来提升网站气质。 第一,网站整体页面平凡而不庸俗。企业网站不应一味追求时尚炫酷,这种炫丽效果的网页版面可能会最先给予用户视觉上的冲击,但是过于炫丽的网站最多就是一种新鲜感的体验,当用户浏览完整个网站的这种炫丽效果时则会觉得别无其他看点,再看一遍就会觉得乏味。反而平凡的网站从视觉角度来看才是经久不衰的设计,因此网站要“沉得住气”,从网站色彩搭配上宁可选择低调奢华,也不要大红大紫,整体页面效果让用户觉得舒服即能百看不厌。 第二,网站建设细节要重视。用户的浏览习惯都是从整体到细节,先把整个网站扫视一遍之后,就会认真研究网站的细节内容,这时就是真正体现气质由内而发的时候了,细节的重要性必然不可忽视。如:使用图片要合理,不要为了让网站看起来丰富而添加图片,一定要在适当的位置运用图片,这样才能更好的凸显图片的作用,当然,光有图片也不行,应适当配上文字,用户才会更加明了地知道网站所要表达的信息。 第三,网站布局的划分。不可否认,黄金比例法是公认的审美观念,网站建设最好也能遵从这一自然法则,根据网站内容的侧重不同进行版块的黄金分割,让用户进入网站就能找到视觉上的平衡点,从而清晰地了解到网站所要表达的重点。 以上三种提升网站气质的方法都是从视觉上的气质进行剖析,当然,还有网站内容上的气质表达,譬如文章内容,案例分析等等,都可以成为一大亮眼之处,能从实质内容上留住用户也是成功提升气质的方法之一。 总结:网站建设不可脱离基本原则,过于出格的创新可能会起反作用,倒不如遵守用户体验原则进行创新,让网站变得更加有内涵,有魅力。