RSS

影响力 – 从众心理

社会认同原理的根本,是人的社会存在感。周围人的目光就是人的一面镜子,人都希望镜子中的自己完美一点,不希望照出一副丑恶的相貌,所以人都会在意,即追求社会认同。人们或许会刻意表现,或许会遮遮掩掩;追求个性或抢占高枝儿的其实就想听一句称赞,埋在人群中随大流的其实只是不想被看做另类。

环境与从众心理

环境影响人。也许有少数能有所超脱,能与众不同,但大多数终归都融在了方方面面的圈子当中,与圈中的人群达成了统一。每个人在行为上都被圈中其他人的目光影响着,如果选择呆在圈中,就不得不跟其他人统一,否则他就不再属于这个圈子。从环境得到的社会证据,对人的顺从压力是十分巨大的,而且直接作用于你的潜意识,当你发现时你确实有权不顺从它,但常常你不会,更想不了那么多。

为了避免麻烦,照着别人做就变成了简便方法,久而久之,从众就成了人类的一种习惯。

来看心理学家做过的一个从众心理的实验的视频。实验安排在电梯里,利用狭小的空间创造出一个与外隔绝的环境。几个辅助实验人员跟随一个受试者走进电梯里,之后做出统一的动作,观察受试者的反应。辅助实验人员全部背对镜头,而可怜的小白鼠对一切都毫不知情。

只用“避免面对面的尴尬”的理由,怕是解释不了受试者的反应了吧!

相似性与维特效应

我们会观察周围所有的人,但当我们观察与自己情况相似的人的行为时,社会认同原理在我们身上能发挥出最大的影响力。我们的潜意识这样认为:于己相似性越高的人的选择越值得参考,源于他的社会证据越有说服力。

虽是做判断时的一念之差,但一切改变由此而生,因为人类有一项从做猿猴时就养成的本能——模仿。有时是有意识地学,有时却是无意识地盲从,总之都是从众心理地表现。

有一个句型像这样:“那谁谁的情况和你一样,后来人家如此如此做,结果就好/糟了。”广告上一个小伙子咳着嗓子,旁边大妈说:“你有这些症状吧,那是咽炎的表现,快吃X咽X宁吧,我儿子就和你一样,一吃就见效!”果然小伙儿一吃就表现出好了的样子……任谁在难受时看见了,都忍不住会拿自己类比一下吧?甚至模仿一下。这时是有意识去模仿。

另一种思路像这样:“那么多人都那样做,他们肯定比我多知道些什么,跟着他们做吧,应该没错。”下班时间拥挤的城市道路上,车辆排队挪动着,突然前面两辆车都打起转向灯,向相邻道上去;后车司机虽未见到前方有事发生,但也满腹狐疑地跟着这两辆车变了道;后面的车看到前面越来越多的车都在变道,于是对变道的疑虑更少了。结果大家都一窝蜂地想往隔壁道上去,造成交通事故和堵塞。仿照别人开车就像条件反射,自己常常意识不到。

维特效应是社会认同原理因相似性而发挥惊人影响力的著名例子,取名出自歌德的小说《少年维特之烦恼》。这本著名的小说曾经轰动一时,让歌德一夜成名;书中主人公维特自杀而告终,由此竟带动了欧洲的一阵自杀浪潮。当代的研究从数据中发现,对自杀的新闻报道常会带来当地自杀发生率的大幅提升,而对自杀事件的低调报道也成了媒体工作者必须知道地行规之一。不可否认的是,富士康系列事件里,第一个跳楼的人确实给追随他的人带了个坏头儿。

危害与避免

社会认同原理带来的危害有两方面,概括地讲就是蓄意谋利和无心之失。

蓄意地伪造社会证据,让别人因从众心理走入圈套之中,这是当“托儿”的人的基本目标。当别人用嘴说,或通过行动传达“其他人都那样做,你也应该跟着做”的信息给你时,你要闻一闻有没有人造因素在里面,敏感地察觉情况,不要轻易就相信了。还要明辨是非,尽量以事实证据做依据,不要完全依赖于观察别人身上的反馈。三人成虎的典故说的可不止是轻信人言的故事。

无心的失误常因情况不清而难以避免。也许和你处在类似情况的人们都在那么做,但家家有本经,考虑的理由未必相同;也许和你站在一起围观的人都没动静,也可能是别人看见其他人都没动静。这时最重要的是理解别人和你都可能有不确定的心理状态,都有盲从的冲动。不要总以为别人都比你掌握了更多的信息,因此才做出某种反应,那可能是从众心理,可能是多元无知效应。

 
Comments Off

Posted by in Uncategorized

 

影响力 – 多元无知效应

“不确定”

社会认同原理告诉我们:在判断何为正确时,如果自己不确定,人会根据别人的意见行事。

人在遇到某种情况时,如果自己不确定,会本能地观察周围人的反应,从他们身上搜集社会证据来修正自己的判断。

多元无知效应

类似于下面的情形,相信你一定遇见过。一件事在众人身边发生,大家都发现了,我只是不清楚到底怎么了,于是瞄一瞄其他人,发现其他人没什么反应,就不当回事儿了;其实情况很紧急,但看到身边的人都不怎么上心的样子,自己也就觉得没那么紧急,如果喊出来反而会被人觉得是大惊小怪了。

比如见到一个人坐倒在街边,前面来来往往的人都看一看走过了,你有多大的几率会停下来问他的情况呢?几乎没有吧?有人说,这是我们社会在变无情,人们在变冷漠。诚然,城市居民疏远的事实让我们承认:城市里,人与周围人的距离越来越远,尤其对陌生人,会以沉着的方式隐藏自己,忽略别人身上所发生的事。但我要为这些扣上“冷漠”的帽子的人们开脱开脱,也包括为我自己。

这种集体冷漠真的是因为在场的所有人都没有动念头、都各扫门前雪吗?不是,起码不全是。每个人都是独立的个体,每个人都被社会认同原理影响着,也就是说,当我发觉事情不正常时,其他人也发现了,所有人都不能确定情况;我在观察周围人的反应时,其他人也在观察;我在搞清楚之前会毫无举动,其他人也在保持冷静;我们所有人都看到其他人没什么反应,所以告诉自己,不需要担心不需要管,只要和别人保持一致就可以了;结果就出现了集体的冷漠。

这就是多元无知效应!每个人都得出判断:“既然没人在乎,那就应该没什么问题。”于是紧急的事在人眼中变得不紧急。

除非,事情紧急得达到了某一程度,人的判断才不再会参考其他人的反应,也就通常所说的“看不下去了,必须出手了”。这个紧急程度因人而异,与社会责任感有很大关系,比如新闻报道的“女老外跳入西湖救人,众中国爷们集体围观”的事。不作评论了,只是想说,多元无知效应发生在任何国度,但不同背景的人的素质有差别。

责任分散原理

与多元无知效应结合紧密的是责任分散原理:当分担所有责任的人越少时,每个个体身上的责任越明确,他的责任感越强,立即行动的可能性也越大;反之,当越多人分担全部责任时,每个个体身上的责任越模糊,他的责任感就不那么强,也未必会有行动。

面对发生在众人面前的事件,大家都会先观察周围人的反应,同时评估自己身上应承担的责任,以此来判断是否该做出某种行为。比如大家都有做出响应的责任,但我清楚大家都有这样的责任,而我不是直接责任人,何况“也许有人已经做了”,“只是我没看到、不了解”,“我不是非这么做不可”,“有这么多人,为什么非要我做”。众多心思,成就了一致的“冷漠”。即使最终悲剧了,我也会说“又不是我一个人的事”而不那么自责。相信每个人都体会过中国式课堂上,“一人提问众人无声”的尴尬吧?

如何避免?

清楚了多元无知效应与责任分散原理,你已经对那种情形下众人的心思有所了解了,接下来就是应对。我分为两方面来说,一是作为“旁观者”,另一是作为“求助者”。

作为旁观者,

  • 我们不要随便忽略自己对事件的第一感觉,不要随大流就算了,因为你已经明白社会认同原理是怎样操纵你的判断了,事实就是事实,别人不在乎不代表着你也应该不在乎。
  • 不要让多元无知效应轻易发生,我们应该敏感地意识到且勇敢地打破它。不要怕被认为是大惊小怪,告诉别人你注意到了什么,站出来引导众人面对现实,而不是躲在假装冷漠的面具之下。
  • 我们应当主动发挥责任感,即便是唐突地多此一举,也应核实下确实有人在承担这份责任了。

作为求助者,

  • 要让周围人明确地知道我需要立即帮助,让周围人从不确定中走出来,意识到事态紧急。
  • 要让责任集中于某人或某几个人身上,避免责任分散,让帮你的人意识到“应该帮他的确实是我”。
  • 告诉帮你的人如何做,消除他不清楚如何做的不安。

为求助者加上一个例子,比如你在街上意外倒下了,周围人看着你,也许他们眼神很关切,但在弄清楚“怎么了”之前他们不会帮你去医院;你痛苦地呻吟着,并且把手伸向四面,围观的人可能会像看要饭的一样看你了;如果你拉住一个人,不停地说“帮帮我,帮帮我”,他只会惊慌地想“该怎么办”,如果没有得到答案,他宁可推开你走掉。所以,从开始求助那一刻,你不要死等什么耐心的志愿者了,明确地说出自己突然病了,请“穿XX颜色衣服的先生”帮忙打个电话叫救护车。

如果你不懂这些,悲剧可能隔天见报;如果你明白了,那你肯定也懂了如何写高效的求助邮件。

 

 
Comments Off

Posted by in Uncategorized

 

影响力 – 知觉对比心理

人类社会发展到今天,人们都说文明进步了许多,我却觉得现在的人比前人更没有安全感。是因为犯罪依然在身边发生么?是因为战争的手段更加复杂么?是因为一不小心就“知道得太多了”么?不是。对老百姓而言,是自己敢放心去做的事越来越少了。

英国著名的哲学家阿尔弗雷德·诺斯·怀特海德曾说:“文明的进步,就是人们在不假思索中可以做的事情越来越多。”想想我们的生活中,怎么越来越多的事情都要仔细小心才敢做?不禁感慨,要考虑的时候太多了。更不幸的是,我们不得不考虑下去,因为我们要生存,要适应。我们不愿加入到那群在社会上把水搅浑的人中,我们想坚持正义与善良。理解影响力怎样作用于人们的心理,会让我们学会如何抵御牟利者的影响力花招,同时善意地帮助或影响身边的人。

回归正题。

什么是知觉对比心理?

知觉对比心理是人类在判断时会参考对比物找到依据的心理。因为对比,人们常扭曲了自己对事物原本的认识。期中考试100分但期末考试98分的学生竟然是退步的;本来5块一碗的面放在菜单上和海鲜一比,卖15也不觉的贵了;常常看美女模特照片的哥们,去相亲时一个个的长相都看不上了。这都是知觉对比心理带来的麻烦。

知觉对比心理如何被人利用?

仅以商品价值为例。这个时代的社会已经不渐渐尊重价值了,越来越多的人敢跳出来做推手,一是因为他们唯利是图,二是因为人们无法像古人一样很快地能鉴定物品的价值,第三是因为人们心中“一分价钱一分货”的善良心理尚未泯灭。有些人玩起了这样的手段:

同样的商品,凭借稍稍华丽的装饰,卖高出许多的价钱,客人无法立刻判断东西质量的好坏,只要价钱还可接受,本能地相信“买贵一点的应该没错”。尤其是那些买礼品的客人。

去买西服,导购小姐先带你看10000元的高档货,然后才带你看你要的3000元的档次,这时你会觉得3000的便宜多了,质量也只差一点点,更容易就接受了;接着导购小姐推荐你一件400元的毛背心搭配,你一试穿确实挺好看,买了。如果一上来你先看400的毛背心,也许就已经觉得不值了,再看3000的西服时,就更不能接受这价格了。

如何应对或使用?

如果你是被影响的一方,大多数时候我们都是,就不得不用理性的思考与自己的本能战斗。你应该及时意识到可能是知觉对比心理在作怪,这是关键,然后试着抛开对比去做判断。当你身处对比之中时,可试着去想“如果没有参考做比较,我觉得它怎么样”,这个方法很有效,尤其对有选择困难综合的人群。

如果你是手持影响力武器的一方,以不作假骗人为前提,你已经找了一条很好的说服手段,就是引入对比,让对方的知觉对比心理悄悄生效,让别人的思路导向你有利的方向。为了让你更有把握,还要结合其他影响力的手段,之后会提到。

 
Comments Off

Posted by in Uncategorized

 

经历性能问题后的一点总结

Reporting项目是我在做的Rails项目,因为性能问题,我们经历曲折坎坷的调优过程,为能否按计划发布而担心。庆祝完发布,我得把一些总结写下来。

故事是这样

  • 项目开始于今年三月份,预计在十一月中旬有个大的发布。
  • 早在四月份,团队就开始为每个请求、每个查询加benchmark,目的是监视执行时间,但并没有验收条件。
  • 八月份,使用Apache Benchmark tool为所有请求在staging环境上做了性能测试,发现有5个图表性能低,甚至在选择地区数目很大(数百个)时,响应时间呈指数增长。之后做了两件事,一是在做功能开发的同时坚持做性能优化,目标就是这些过慢的请求;二是限制地区数目选择的上限到100,以控制最坏情况下的性能。
  • 九月份,优化之后对那些重点请求重新进行了并发级别为1的性能测试,结果是响应时间减少了70%~85%,Tom对此很高兴,我们以为性能问题不复存在了。十月二十日,我们开始重新做全面的压力测试,发现一些请求的并发访问性能确实成问题。我们立即告知了客户这个问题。我们没有利用起这期间的时间,发现问题时已经很晚了,离发布只剩1月。
  • 接着我们就分析原因,然后就发现数据库的并发查询性能是问题的核心,因为数据库执行时间占了请求响应时间的70%,在并发查询时,数据库反应时间增长地很快,直接导致请求的响应时间增长很快。我们需要DBA帮忙,但Paul的全部时间已经在另外一个项目上了,我们向客户争取来了Paul的部分时间,后来客户为我们安排了另一位DBA专门来帮忙。
  • 请DBA帮忙的方式是,我们告诉他某个查询的sql语句,以及目前的执行时间和我们期望的时间,他们来帮忙做优化。这样做的好处是他们立刻知道要干什么,不耽误时间。
  • 我们在staging环境上的测试越来越好,理论上产品数据库上的测试结果应更好才对,但是不是这样,惊喜了。在产品数据库上存在一个首次访问响应时间的问题,就是说在时隔若干时间之后的头次访问,响应时间非常慢,但是紧接着第二次访问页面就会很快。这个问题在staging上是没有的,而且我们也无法在产品数据库上重现,不知道这个间隔时间是多少,所以很难请DBA监视。
  • 如今,所有查询的优化已经结束了,在产品环境上所有请求在并发测试中的中位数响应时间是在要求之内的。虽然首次访问响应时间的问题还在,但是我们和DBA都没有找到办法能合理地重现它,客户同意的解决方案是:如果需要的话,向用户提示相关信息。
  • 昨天成功发布了。

我们学到了什么

如何处理问题?

  • 发现问题后,应该及时让客户和DM知道情况,因为这样的问题对项目发布有直接的影响。
  • 通过一些手段,比如profiler等工具,来检测应用,诊断出性能问题发生的部位和原因。
  • 性能调优需要有一个指标,应该在调优前就向客户、甚至客户的客户要这个指标。不仅要与客户的业务人员谈,还要和技术人员去谈,因为性能指标在这两方人眼中可能差异很大。
  • 自己去研究是对的,但应设定时间限制;不应该让讨论只发生在团队内部,应该去请教专家,效率会更高。
  • 同时应该让其他项目的同事也了解我们目前面临的问题,因为他们可能就有这方面的经验,也可能以后会遇到相似的情况。
  • 对于数据库的问题,我们需要客户的DBA帮忙,一方面要争取他们的时间不断催促他们做事,另一方面要做足准备,告诉DBA最直接的需要做的任务是什么,这样他们也会效率更高。比如告诉他们sql是什么,目前运行时间是多久,期望时间是多久。
  • 合理地与客户“谈判”,找到折中的解决方案。这个谈判不是推诿,而是坐在一起讨论,我们的提议要有足够的业务理由做支持。

如何避免问题?

  • 我们应该从一开始就把性能纳入考虑,在编写代码时注意到它,而不是专门做优化时被迫重写部分代码
  • 我们应该把性能测试和调优的着眼点放在产品环境上,这样可以降低最后得到惊喜的风险
  • 我们应该尽早地参考性能指标设计包括压力测试在内的性能测试策略
  • 对新版本的探索性测试时,应当对性能表现留心,更早地察觉并意识到问题,这应该叫做持续体验(continuous experience)

当前发布中正在做的事

  • 在技术选型时为性能做更多的考虑
  • 先做包括可能出现性能问题的故事在内的高风险故事
  • 在第一个页面可访问之后就设计性能测试策略
  • 在做更多的故事之前就为性能做统筹考虑
 
Comments Off

Posted by in Uncategorized

 

影响力

看完《盗梦空间》(《Inception》)那部电影时,头一次觉得让一个人跟着给他的一个念头走,竟是那么困难的一件事。

我们通常只是跟着自己的直觉去说服别人,或顺从别人。似乎有些人有一些经验总结,知道一个请求怎么提别人会答应的几率更大,知道有些心理学的玩意在作怪,然而我看到的只是树木,case by case地考虑,从没想过有森林这回事。

《影响力》(《Influence: The Psychology of Persuasion》)才将我引上了前往森林的路。原来影响一个人根本不需要植入一个念头这么复杂。我们人类的本能,我们的直觉,我们的社会存在感,结合在一起形成了人身上复杂的条件反射,它已经给了想影响我们的人足够的操作空间。

作为影响力的武器有三点特性,第一,它抓住人类具有的复杂的条件反射机制,满足条件以触发相应的某些行为;第二,这种触发条件反射而造成的影响力是压倒性的,若无防备极难抵挡,甚至始终不自觉;第三,有用心的人利用影响力武器可从中得利。

明白影响力在自己周围是如何发生的,识别之后应明白如何避免不利的损害,还应学为己用去无害地影响别人,这是我们读这本书的目的

为什么促销活动被提前终止,为了低价而来又感觉受骗的你仍在这里买了平常价钱的东西?

为什么看了餐馆的海鲜价格之后,觉得地摊上5块一碗的油泼面在这儿25块钱也不贵?

为什么对决定在明天说分手的男朋友,还要请他好吃好喝大为破费?

为什么情景戏剧里的观众假笑让人一想就觉得假,但人们还是不自觉地跟着傻笑?

为什么同样一件事实,德高望重的人说着听起来那么有道理?

为什么很多学生的学习动力起于压力而最终更止于压力?

为什么你对自己在世界杯上下赌注的球队莫名地增加了信心?

如果事先让你知道,你只要做一点儿事情就可以让成功说服别人的几率增加50%,你会不做吗?

如果事后你才明白,你只要做一点儿事情就可以避免明知被骗还无法脱身的窘境,你会不做吗?

一本书就能让你明白这么多事,那真是太值了。

 
Comments Off

Posted by in Uncategorized

 

异步Database Replication的更新延迟问题

被最广泛使用的异步Database Replication有可能因更新延迟(lag)而出现问题:当查询请求被slave处理时,如果slave因更新延迟而包含尚未更新的陈腐数据,会导致查询结果不准确。

例如OLTP(On-Line Transaction Processing,联机事物处理)型的查询请求要求极高的实时性,如在博客中发表完一篇文章就应立即看到它出现在文章列表中,slave上的replication通常无法及时做完,这时如果查询请求由slave来处理,返回的就是错误的陈腐数据(stale data)。Replication的延迟虽然通常很小,但毕竟不是实时同步,在slave上查不到最新数据的情况会存在的,何况在master高负载时向slave更新的延迟会更大。

当某slave的Replication延迟过大时,应将此slave移出服务后强制同步数据。不过在延迟存在但还不算过大时,如何在保证查询准确性的前提下合适地使用slave来分担负载呢?下面讨论下Peter Zaitsev在他的文章中提到了三个方法,至于它们之间的混合使用就不在讨论之内了。

根据查询类型决定如何分派查询请求

根据查询对数据的实时性要求,将查询分为time critical和non time critical两种,前者受Replication延迟的影响很大,如前文提到的OLTP型的查询;后者对Replication的延迟不敏感,对最新数据没有迫切的要求,如多为报表使用的OLAP(On-Line Analytical Processing,联机分析处理)型查询。

在分派查询请求时,识别该查询请求的实时性要求,将non time critical的查询交给slave处理,而将time critical的查询交master处理。可见,只读性质的数据分析式查询越多,slave所分担的载荷就越多,这种方案就越有效。

根据session为访问者指派数据库副本

这种考虑是从两个事实出发的。

(1)刚刚做过更新操作的访问者需要实时获得更新后的数据

做完更新操作的访问者应在一定时间段内只从master读取数据,以保证他能读到可能由他自己写入的最新数据。这个时间段应长于所有slave上Replication的最长时间,以保证他写的数据已经replicate给了slave。

(2)刚刚查询过数据的访问者应当在再次做相同查询时看到基本相同的数据

如果一个访问者的两次只读查询请求是由两个slave分别处理的,那么第一次读到的数据有可能在第二次读时找不到,因为不同slave的Replication延迟是不同的,存在被查询的数据在一个slave中被更新了但尚未更新到另一个slave中的情况。所以,给访问者session,让他在这一段时间内持续访问同一个slave。

这种方法说起来容易做起来难。而且,在session的时间段内访问者无法摆脱所指派的slave,失去了在请求之间切换到其它slave上获取较新数据的机会。

根据访问对象指派数据库副本

根据所查询数据的最后更改时间(last updated time)决定将查询请求发给master或slave。数据的最后更改时间离当前时间越近,它出现在slave上的几率就越小,这种请求只能由master出马;反之,则可使用slave处理请求。

一个例子:博客上的文章有最后更新时间,查询某篇文章时,先查该文章的新旧,如果文章很新那向master请求数据,如果文章已经不那么新了,那就由slave处理查询请求。

这意味着数据查询请求被执行之前需要额外查询一次其最后更新时间?没错。幸运的是,我们可以使用memcached之类的对象缓存系统来代替直接向master做这个查询。

这中方法的思想很美,不过适用范围较窄。对于可追踪最后更新时间的对象,如博客文章、评论等,单个查询其数据时可采用此方法;如果查询这样的对象集合,那就要参考实时性要求去考虑了。在复杂性方面,缓存的维护以及与Replication时间之间的权衡为该方法增加了难度,任何没有更新到所有slave上的数据对象都需要维护在cache中,而已经更新至所有slave上的数据对象理论上都需要从cache中移除,以清理cache空间。

References

  • Peter Zaitsev的文章,http://www.mysqlperformanceblog.com/2007/02/14/getting-use-of-slave-in-mysql-replication/
 
Comments Off

Posted by in Uncategorized

 

Database Replication的数据同步方式

为保证数据在各数据库副本上的一致性,Replication需要频繁同步数据,下文谈谈三种同步方式,以MySQL上的master-slave模型为例。

同步方式(Synchronous)

如果master接收更新请求后,在自身执行的同时将信息传播给所有slave,并要等收到所有slave获得更新信息的反馈之后才返回,那此同步过程会大大拖累性能。这个道理很容易理解,而MySQL Cluster号称拥有Synchronous Replication的特性,我确实还没搞清它怎样能做到。

异步方式(Asynchronous)

典型MySQL上的Replication是异步的,master处理完更新请求后返回,不等待slave获取到更新信息。借用51CTO.com的这张图来介绍下异步Replication的过程吧。

  1. master上有更新到来,先将更新存入binary-log中;
  2. master上的sql进程执行Database更新,同时master将有新更新的消息散播出去,让各slave随时来请求,这个散播互动的过程通常是基于publish-subscription的;
  3. 某slave向master发来IO请求,指定要binary-log上某偏移量之后的跟更新信息;
  4. master接受IO请求,并返回所请求的更新信息,以及binray-log上当前的偏移量;
  5. slave收到IO反馈,将收到的更新信息追加到relay-log末尾,并将binray-log偏移量记录到master-info文件中,然后向master返回Acknowledge消息;
  6. slave的sql进程监测到relay-log中有新内容后,会立即在database上执行更新。

根据binary-log的信息存储形式,Replication又可区分为如下三种级别,相应都在MySQL上有配置。

  • Row level – Binary Log 中会记录成每一行数据被修改的形式,然后在 Slave 端再对相同的数据进行修改,不用在乎执行的sql语句的上下文相关的信息。显然此方法log中数据量巨大。
  • Statement level – 每一条会修改数据的 Query 都会记录到 Master的 Binary Log 中。log中不存在大量数据了,但它不得不记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端杯执行的时候能够得到和在master端执行时候相同的结果。这种结果常因为query语句无法完美Replicate而出现数据不一致。
  • Mixed level – 它是上两种方法的折中,会根据执行的每一条具体的 Query 语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。

半同步方式(Semi-synchronous)

又是一个典型的折中。因为上面提到的异步方式下,master不管slave数据更新的进度,若slave出现明显的落后(Lag),数据不一致的问题和单点故障的风险都会被放大;而完全同步的方式对性能的损害又过大。

借用orczhou.com的图片如下来解释半同步方式。

在半同步的方式下,master等待至少一个slave收到更新,即等待其Acknowledge消息,以此保证至少有一个slave在master突然宕机的情况下能够不丢失数据,并迅速代替master机器。不过如果等待时间超过限制,半同步模式会自动转为异步模式,不再等待slave。

Reference

  • 半同步方式的更多解释,http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html
  • master-slave在MySQL上的配置,http://members.cox.net/midian/howto/mysqlReplication.htm
 
Comments Off

Posted by in Uncategorized

 

Database Replication与应用模型介绍

Database Replication是一个在冗余数据库之间分享数据,以维护多个数据一致的数据库副本(Replica)的方法,目的是提高可靠性、容错性和可访问性。其目的和方式,直白地说,是以冗余数据的方式提高容错能力,以实时维护数据库副本的方式保证宕机时热切换,同时分散数据查询的载荷以提高性能,而所有的一切对外部用户是透明的。当然,不同的应用背景对数据库的期望是不同的,可能偏重于上述的某些个能力,并不是兼有。

例如分支团队希望在远程得到一部分数据库数据,而不是实时访问主数据库,那么可通过Replication为其建一个主数据库中某些表的副本,这个副本中的数据可隔一定时间同步一次。

Replication不是数据库备份技术,数据库备份的要旨在于将某一个时间节点上的数据库状态备份起来,供未来的数据恢复或参考用;而Replication的数据库副本对所做的更新都是无条件执行的,至于执行之后的数据状态是好是坏,它们不关心。不过Replication有助于数据库备份,后文介绍master-slave模式时会提及。

从数据一致性的维护上讲,应用Replication要首先安排所有数据库副本的责任角色,谁能接收更改请求并分享出来,谁仅读取其他副本的数据更新。称前者为master,称后者为slave,通常有master-slave和multi-master两种应用模型,下面首先介绍这两种模型。

master-slave

一个server上的DB做master,其他所有server上的DB副本都作为slave。任何时候都由master接收更新请求并首先执行,然后将更新的信息传递给slave,slave上再应用更新。slave仅用来接收查询请求,当master宕机时会按照切换策略将一个slave升级为master,而原master在修复之后则作为slave重新加入。

借用来自MySQL Reference Manual的下图说明master-slave模型的Replication的应用场景。

图中的应用场景是一个大量数据库查询的web应用,使用master-slave的首要目的是分担载荷。

  1. 用户的request先由Load Balancer分派到某一较轻负载的web应用实例上;
  2. 根据request中对数据的不同操作类型,web应用实例将数据实时性要求较宽松的只读请求发给slave处理,而将数据实时性要求高的读操作或写操作发给master处理;
  3. 写操作的信息在master数据库上执行的同时,被Replicate给各个slave。

另外,上文提到Replication并不属于数据库备份技术,但数据库备份操作确实可从中受益。master-slave模型中,可在某一slave更新数据后将它从slave阵列中切出,暂时不再接受任何request或replication,这时可对此slave数据库进行备份。备份过程可专心进行,相比直接对服务中的数据库做备份,难度降低许多。备份完毕的这台server可主动请求master的数据,更新完毕后可重新作为slave加入阵列继续提供服务。

multi-master

“能够接收更新请求并首先执行”是具有master角色的标准,该应用模型中所有的server上的DB副本都是master,可接收更新请求或数据查询请求,因为宕机时的切换成本比master-slave要小。这种应用模型的在副本数据更新的信息来源上也分两种方式。

1. Active Replication

任何更新请求都分别发给各个副本执行,这种主动行为的好处在于简化了副本间的数据同步,却让负载同时发生,失去了副本间并发响应查询请求的性能。

2. Passive Replication

任何更新请求只发给某一个副本,它接收到之后会立即执行,然后将自己的状态传播给其他副本,其他副本在此过程中只被动等待。这种副本间传递信息的方式比master-slave更要复杂,因为这张网上的任一节点都能当做其他节点的信息来源,而且两条对临界数据的修改可能随时出现,所以需要分布式并发控制。常见的方法有两个,一个基于锁机制,将修改所涉及到的资源的加锁,以同步不同master上收到的更改的执行顺序;另一个基于时间戳和事务回滚,各副本先应用事物所描述的更新,在其他副本的信息到来后发现冲突时,再依时间戳为据选择是否回滚前面的更新。

Reference

  • Replication的解释,http://en.wikipedia.org/wiki/Database_replication
  • 在负载均衡上的应用,http://dev.mysql.com/doc/refman/5.6/en/replication-solutions-scaleout.html
  • 在宕机时切换上的应用,http://dev.mysql.com/doc/refman/5.6/en/replication-solutions-switch.html
 
Comments Off

Posted by in Uncategorized

 

中秋月圆

在把家庭生活看得越来越淡、对待邻里关系若有实无的如今,中秋节不算个什么重要时节了,甚至过年也变得只是走走过场而已。我本打算埋头宅在家啃书,独自抵御阴雨的寒冷,却意外地度过了温暖的三天假期。

妻只休第一天,让她好好睡一个奢侈的懒觉吧~ 她却仍然被无情的电话吵醒,无奈地赶去单位处理事情。中午接到她,说想吃肉丸呼啦汤,立刻满足。饭后决定带她散散心,哪怕雨大天阴,驱车奔浐灞而去。停车,沿浐河边信步而行,雨声沙沙,河床树顶的白鹭却不因阴雨而烦闷,或嬉戏、或悠悠然~ 忽然发现垃圾箱边一只小笨狗注视着我们,在雨中颤巍巍的,饿么?不能让这小家伙即离了家人又没有饭吃,中秋的月饼送上。不够吗?这就买肉去!借这石板搭一个雨棚吧,虽然不忍离去。后赶往高新,接老妈去奶奶家,团圆的晚饭其乐融融。愿长辈健康、大家开心~

次日一早醒来,窝在沙发里拽本书看。眼光扫扫家里,未扔的垃圾袋、半箱腐坏的水果、洗衣机上一堆的衣物、斑点的地板、冰箱里的剩食、歪斜的沙发衬垫,不能再忍了。平时早出晚归,我俩人确实不够勤快,现今是收拾的时候了,等妻下班了就是一惊喜。心中既怀此念,动手时更加有劲,挨个清除,逐一料理,整顿完毕已是困意连连……被电话叫醒时,我才记起和三位发小儿早有约。晚餐时对炖羊肉一番大快朵颐,把酒谈论最近的境遇。饭后怀念起从前一起游戏的日子,遂往网吧去,早已不熟悉的网吧中,《生死四人组》的世界里我们团结配合、相互帮扶,真是只有最知心的朋友们才能达到的境地啊,当游戏完毕,我们更加惺惺相惜~ 朋友们,加油!在自己的人生长跑里,可以吊吊车尾、可以呼呼喘气,但一定要努力下去,大步流星的终究还会是我们!

最后一天假期,天似乎晴了,被窝里坐着看书挺惬意。老妈的电话里问我有什么安排,我听得出来,其实是想让我开车载她们出去散散心,老爸也终于休假了,这半天的假期让我为他们再拆分吧。于是立即答应,来吧,把小舅也叫上一起,我带你们去呼吸雨后的新鲜空气。车过灞河桥,这宽阔的水面、暗流里翻出的浊浪,却是平日里瞧不见的光景,多亏这一阵雨。沿河东行驶,一片环绿的湖水吸引了我们,以及先到的若干钓鱼爱好者。湖水宁静,丝毫不似河水的昏黄;草地、小丘天然生成,全是清洗过的碧绿。长辈们哄然称好,这确是个十个农家鱼塘也不换的宝地。雨后的阳光倾泻着,我们尽兴之后也不得不返回了。送回父母,我还要赶去我另一对父母那里,中秋佳节,他们也想女儿、女婿。说说时事,聊聊家常,互相问各种“缺不缺”、“好不好”,话里绝不是寒暄,心里却有各种温馨~ 末了出门,回我们的小家去。

车在立交上,看云里透出的淡淡圆月,心中温暖畅快,无须言语~

 

Tags: ,

Mock,有人爱它我偏恨

一次又一次地在项目中用Mock写测试,每次都是无奈和不情愿。

对话一

Me: 为什么要用Mock呢?
Dev: 因为客户要求只有Model中的代码才能touch数据库。
Me: 构造数据做其他层次的测试而不是mock,这不可以吗?
Dev: …测试数据构造很麻烦。我们用Mock分离其依赖层次的代码,这样就可以专心写当前方法的测试了。
Me: 依赖的低层次方法全都Mock了理想返回值,接下来直接断言结果就好了?高层次的测试过了但低层的反而没过!
Dev: ……Mock不是保证了各层依赖的方法真的被调用了嘛。
Me: 产品代码里我能看见谁被调用,可代码集成后结果到底对不对呢?集成测试在哪呢,怎么知道产品代码放在一起真能work?
Dev: ………Cucumber测试……
Me: Holy crap!

你应懂得:

  • Mock应该作为分离模块和模块之间的手段,以降低测试的难度,例如Mock数据查询,返回自己构造的测试数据而不是访问模块之外的资源。
  • 模块内的层次之间的关联在测试中未必非要由Mock打断,在一定数据的基础之上,为一个原子功能做跨越一二个类的单元测试,更能从集成的角度证明代码的正确性。
  • 比证明“某些依赖确实被调用到”更有意义的是证明“对给定的输入数据能得出期待的结果”。不要把基于结果断言的测试变成用Mock描述实现过程。
  • 如果已经知道是delegate方法到其他方法上,那就省了Mock的测试吧,就像拿着标准答案答考题,过家家一样毫无意义,除非你不幸要完成变态且愚昧的“100%测试覆盖率”。
  • 如果对“某层次代码能否间接访问到数据库”没有苛刻要求,那么有必要的话,可为每个开发机器配置独立数据库,并区分开test数据库和development数据库,让test数据库只跑测试。这样在写访问数据相关的测试时,就可大胆预置测试数据,之后清除也方便,让测试能够“所见即所得”从而更加真实。

对话二

Me: Mock的代码这么多,还对应着产品代码里的实现细节,这不容易写更不容易看懂啊!
Dev: 这也不算多,构造测试数据才麻烦呢。被测方法里调的其他对象方法你不得不Mock啊,不然会报错。
Me: 但是我要用测试来驱动开发啊,这中间的细节我需要到真正写出产品代码时才能确定,这样的测试也太难写了吧?
Dev: …是有点麻烦,不然你先写好断言部分,产品代码需要时再补上Mock吧。
Me: 这是先开发后补测试啊!
Dev: ……一点一点写的…最终反正是有效的测试啦。
Me: 如果被Mock的方法被更改了实现呢,你能及时发现吗?测试全过了可应用启动却废了,这事发生过吧?
Dev: ………改代码时细心一点,多搜索下检查检查,启动应用看一看……
Me: Holy crap!

你应懂得:

  • Mock在测试中必然会构建假设,通常如“某类的某方法在某条件下调用时应返回某结果”。应该将其控制到所测功能的数据源头处,而不是任其泛滥成为实现过程在测试中的描述。
  • Mock的假设在描述时必然会牵扯到所测方法的实现细节,这在一定程度上为先写测试后写代码增加了难度。
  • 过多地使用Mock会降低测试代码的可读性,更重要的是其可维护性。错误的假设不易分辨,因为真实改变时假设还保持不变,无法通过测试的失败而被发现,而代码检查、集成测试以及人工测试成为了代价昂贵的补偿方法。
 
Comments Off

Posted by in Uncategorized