精华内容
下载资源
问答
  • 作者简介 陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架 构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富大规模系统构 建和基础架构研发经验,...

    bb

    作者简介 陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架 构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富的大规模系统构 建和基础架构的研发经验,善于复杂业务需求下的大并发、分布式系统设计和持续优化。作者微信公众号dongming_cdm,欢迎关注。

    GFS(Google File System)是Google公司开发的一款分布式文件系统。

    在2003年,Google 发表一篇论文详细描述了GFS的架构。GFS,MapReduce,Bigt able并称为Google的三架⻢ ⻋,推动了Google的高速发展。其他互联公司和开源领域纷纷模仿,构建自己的系统。可以 这么说,GFS,MapReduce,Bigt able引领了互联网公司的分布式技术的发展。但GFS架构设 计并不是一个完美的架构设计,它有诸多方面的问题,一致性的欠缺就是其中的一个问题。

    本文探讨一下GFS架构设计、分析其在一致性方面的设计不足,并且看一下一致性对分布式系统 的重要性。

    bb

    我们从GFS的接口设计说起。

    接口

    GFS采用了人们非常熟悉的接口,但是被没有实现如POSIX的标准接口。通常的一些操作包 括:create, delete, open, close, read, write, record append等。create,delete,open,close 和POSIX的接口类似,这里就不强调说了。这里详细讲述一下write, record append提供的语意。

    • write操作可以将任意⻓度len的数据写入到任意指定文件的位置off set

    • record append操作可以原子的将len<=16MB的数据写入到指定文件的末尾

    之所以GFS设计这个接口,是因为record append不是简单的offset等于文件末尾的write操作。 record append是具有原子特性的操作,本文后面会详细解释这个原子特性。

    write和record append操作都允许多个客户端并发操作。

    架构

    GFS架构如下图。(摘自GFS的论文)

    bb

    主要的架构部件有GFS client, GFS master, GFS chunkserver。一个GFS集群包括:一个 master,多个chunkserver,集群可以被多个GFS client访问。

    GFS客户端(GFS client)是运行在应用(Application)进程里的代码,通常以SDK形式 存在。

    GFS中的文件被分割成固定大小的块(chunk),每个块的⻓度是固定64MB。GFS chunkserver把这些chunk存储在本地的Linux文件系统中,也就是本地磁盘中。通常每个 chunck会被保存3个副本(replica)。一个chunkserver会保存多个块,每个块都会有一个 标识叫做块柄(chunk handle)

    GFS 主(mast er)维护文件系统的元数据(met adat a),包括名字空间(namespace, 也就是常规文件系统的中的文件树),访问控制信息,每个文件有哪些chunk构成,chunk 存储在哪个chunkserver上,也就是位置(locat ion)。

    bb

    在这样的架构下,文件的读写基本过程简化、抽象成如下的过程:

    写流程

    1.client 向mast er发送creat e请求,请求包含文件路径和文件名。mast er根据文件路径和文件 名,在名字空间里创建一个对象代表这个文件。

    2.client 向3个chunkserver发送要写入到文件中的数据,每个chunkserver收到数据后,将数据 写入到本地的文件系统中,写入成功后,发请求给mast er告知mast er一个chunk写入成功, 与此同时告知client 写入成功。

    3.mast er收到chunkserver写入成功后,记录这个chunk与机器之间的对应关系,也就是chunk 的位置。

    4.client 确认3个chunkserver都写成功后,本次写入成功。

    这个写流程是一个高度简化抽象的流程,实际的写流程是一个非常复杂的流程,要考虑到写入 类型(即,是随机写还是尾部追加),还要考虑并发写入,后面我们继续详细的描述写流程, 解释GFS是如何处理不同的写入类型和并发写入的。

    bb

    读流程

    1.应用发起读操作,指定文件路径,偏移量(off set )

    2.client 根据固定的chunk大小(也即64MB),计算出数据在第几个chunk上,也就是chunk索 引号(index)

    3.client 向mast er发送一个请求,包括文件名和索引号,mast er返回3个副本在哪3台机器上, 也就是副本位置(location of replica)。

    4.client 向其中一个副本的机器发送请求,请求包换块柄和字节的读取范围。 

    5.chunkserver根据块柄和读取范围从本地的文件系统读取数据返回给client

    这个读流程未做太多的简化和抽象,但实际的读流程还会做一些优化,这些优化和本文主题关 系不大就不展开了。

    bb

    写流程详述

    我们详细的讲一下写入流程的几个细节。

    1.名字空间管理(namespace management)和锁保护(locking)

    写入流程需要向主发送creat e这样请求,来操作保存在主上的名字空间。 如果有多个客户端同时进行写入操作,那么这些客户端也会同时操作向主发送creat e请求。主 在同一时间收到多个请求,通过加锁的方式,防止多个客户端同时修改同一个文件的元数据。

    2.租约(Lease)

    client 需要向3个副本写入数据,在并发的情况下会有多个client 同时向3个副本写入数据。GFS 需要一个规则来管理这些数据的写入。 这个规则简单来讲,每个chunk都只有一个副本来管理多个client 的并发写入。也就是说,对 于一个chunk,mast er会授予其中一个副本一个租约(lease),具有租约的副本来管理所有要写 入到这个chunk的数据写入,这个具有租约的副本称之为首要副本(primary)。其他的副本称之 为二级副本(secondary)

    3.变更次序(Mutation Order) 

    将对文件的写入(不管是在任意位置的写入,还是在末尾追加)称之为变更(Mut at ion)。 Primary管理所有client 的并发请求,让所有的请求按照一定顺序(Order)应用到chunk上。

    bb

    4.基本变更流程

    1).client 询问mast er哪个chunkserver持有这个chunk的lease,以及其他的副本的位置。如果 没有副本持有lease,mast er挑选一个副本,通知这副本它持有lease。

    2).mast er回复client ,告述客户端首要副本的位置,和二级副本的位置。客户端联系首要副 本,如果首要副本无响应或者回复客户端它不是首要副本,则客户端重新联系主。 

    3).客户端向所有的副本推送数据。客户端可以以任意的顺序推送。每个chunkserver会缓存这 些数据在缓冲区中。 

    4).当所有的副本都回复说已经收到数据后,客户端发送一个写入请求(write request)给首 要副本,这个请求里标识着之前写入的数据。首要副本收到请求后,会给写入分配一个连续的 编号,首要副本会按照这个编号的顺序,将数据写入到本地磁盘。 

    5).首要副本将这个带有编号写入请求转发给其他二级副本,二级副本也会按照编号的顺序, 将数据写入本地,并且回复首要副本数据写入成功。 

    6).当首要副本收到所有二级副本的回复时,说明这次写入操作成功。 

    7).首要副本回复客户端写入成功。在任意一个副本上遇到的任意错误,都会报告给客户端失败。

    前面讲的writ e接口就是按照这个基本流程进行的。 下图描述了这个基本过程。(摘自GFS的论文)

    bb

    5.跨边界变更 

    如果一次写入的数据量跨过了一个块的边界,那么客户端会把这次写入分解成向多个chunk的 多个写入。

    6.原子记录追加(Atomic Record Appends)

    Record Appends在论文中被称之为原子记录追加(Atomic Record Appends),这个接口也 遵循基本的变更流程,有一些附加的逻辑:客户端把数据推送给所有的副本后,客户端发请求 给首要副本,首要副本收到写入请求后,会检查如果把这个record附加在尾部,会不会超出块 的边界,如果超过了边界,它把块中剩余的空间填充满(这里填充什么并不重要,后面我们会 解释这块),并且让其他的二级副本做相同的事,再告述客户端这次写入应该在下一块重试。 如果记录适合块剩余的空间,则首要副本把记录追加尾部,并且告述其他二级副本写入数据在 同样的位置,最后通知客户端操作成功。

    bb

    原子性

    讲完架构和读写流程,我们开始分析GFS的一致性,首先从原子性开始分析。

    Write和Atomic Record Append的区别 前面讲过,如果一次写入的数量跨越了块的边界,那么会分解成多个操作,writ e和record append在处理数据跨越边界时的行为是不同的。我们举例2个例子来说明一下。

    例子1,文件目前有2个chunk,分别是chunk1, chunk2。

    Client 1要在54MB的位置写入20MB数据。这写入跨越了边界,要分解成2个操作,第一个操 作写入chunk1最后10 MB,第二个操作写入chunk2的开头10MB。Client 2也要在54MB的位置写入20MB的数据。这个写入也跨越边界,也要分解为2个操作, 作为第三个操作写入chunk1最后10 MB,作为第四个操作写入chunk2的开头10MB。

    2个客户端并发写入数据,那么第一个操作和第三个操作在chunk1上就是并发执行的,第二个 操作和第四个操作在chunk2上并发执行,如果chunk1的先执行第一操作再执行第三个操作, chunk2先执行第四个操作再执行第二个操作,那么最后,在chunk1上会保留client 1的写入的 数据,在chunk2上保留了client 2的写入的数据。虽然client 1和client 2的写入都成功了,但最 后既不是client 1想要的结果,也不是client 2想要的结果。最后的结果是client 1和client 2写入 的混合。对于client 1和client 2来说,他们操作都不是原子的。

    例子2,文件目前有2个chunk,分别是chunk1, chunk2。

    Client 要在54MB的位置写入20MB数据。这写入跨越了边界,要分解成2个操作,第一个操作 写入chunk1最后10 MB,第二个操作写入chunk2的开头10MB。chunk1执行第一个操作成功 了,chunk2执行第二个操作失败了,也就是写入的这部分数据,一部分是成功的,一部分是 失败的,这也不是原子操作。

    接下来看record append。由于record append最多能写入16MB的数据,并且当写入的数据量 超过块的剩余空间时,剩余的空间会被填充,这次写入操作会在下个块重试,这2点保证了 record append操作只会在一个块上生效。这样就避免了跨越边界分解成多个操作,从而也就 避免了,写入的数据一部分成功一部分失败,也避免了并发写入数据混合在一起,这2种非原 子性的行为。

    bb

    GFS原子性的含义 

    所以,GFS的原子性不是指多副本之间原子性,而是指发生在多chunk上的多个操作的的原子性。可以得出这样的推论,如果Writ e操作不跨越边界,那么没有跨越边界的writ e操作也满足GFS 所说的原子性。

    GFS多副本不具有原子性 

    GFS一个chunk的副本之间是不具有原子性的,不具有原子性的副本复制,它的行为是:

    一个写入操作,如果成功,他在所有的副本上都成功,如果失败,则有可能是一部分副本 成功,而另外一部分失败。

    在这样的行为如下,失败是这样处理的:

    • 如果是write失败,那么客户端可以重试,直到write成功,达到一致的状态。但是如果在 重试达到成功以前出现宕机,那么就变成了永久的不一致了。

    • Record Append在写入失败后,也会重试,但是与writ e的重试不同,不是在原有的off set 上重试,而是接在失败的记录后面重试,这样Record Append留下的不一致是永久的不一 致,并且还会有重复问题,如果一条记录在一部分副本上成功,在另外一部分副本上失 败,那么这次Record Append就会报告给客户端失败,并且让客户端重试,如果重试后成 功,那么在某些副本上,这条记录就会成功的写入2次。

    我们可以得出,Record Append保证是至少一次的原子操作(at least once atomic)。

    bb

    一致性

    GFS把自己的一致性称为松弛的一致性模型(relaxed consistency model)。这个模型分析元 数据的一致性和文件数据的一致性,松弛主要是指文件数据具有松弛的一致性。

    元数据的一致性
    元数据的操作都是由单一的mast er处理的,并且操作通过锁保护,所以是保证原子的,也保 证正确性的。

    文件数据的一致性 

    在说明松弛一致性模型之前,我们先看看这个模型中的2个概念。对于一个文件中的区域:

    • 如果无论从哪个副本读取,所有的客户端都能总是看到相同的数据,那么就叫一致的 (consist ent );

    • 在一次数据变更后,这个文件的区域是一致的,并且客户端可以看到这次数据变更写入的 所有数据,那么就叫界定的(defined)。

    GFS论文中,用下面的这个表格总结了松弛一致性:


    Write

    Record Append

    Serial success

    defined

    defined interspersed with inconsistent

    Concurrent successes

    consistent but undefined

    Failure

    inconsistent

    分别说明表中的几种情况:

    1.在没有并发的情况下,写入不会有相互干扰,成功的写入是界定的,那么必然也就是一致的 

    2.在有并发的情况下,成功的写入是一致的,但不是界定的,也就是我们前面所举的例子2。 

    3.如果写入失败,那么副本之间就会出现不一致。

    4.Record Append能够保证是界定的,但是在界定的区域之间夹杂着一些不一致的区域。 Record Append会填充数据,不管每个副本是否填充相同的数据,这部分区域都会认为是 inconsist ent 的。

    bb

    如何适应松弛的一致性模型

    这种松弛的一致性模型,实际上是一种不能保证一致性的模型,或者更准确的说是一致性的数 据中间夹杂不一致数据。

    这些夹杂其中的不一致数据,对应用来说是不可接受的。在这种一致性下,应该如何使用GFS 那?GFS的论文中,给出了这样几条使用GFS的建议:依赖追加(append)而不是依赖覆盖 (overwrite),设立检查点(checkpointing),写入自校验(write self-validating),自记录标识 (self-identifying records)。

    使用方式1:只有单个写入的情况下,按从头到尾的方式生成文件。 

    • 方法1.1:先临时写入一个文件,再全部数据写入成功后,将文件改名成一个永久的名 字,文件的读取方只能通过永久的文件名访问到这个文件。 

    • 方法1.2:写入方按一定的周期,写入数据,写入成功后,记录一个写入进度检查点 (checkpoint ),这个检查点包括应用级的校验数(checksum)。读取方只去校验、处理检查点之前的数据。即便写入方出现宕机的情况,重启后的写入方或者新的写入方,会 从检查点开始,继续重新写入数据,这样就修复了不一致的数据。

    使用方式2:多个写入并发向一个文件尾部追加,这个使用方式就像是一个生产消费型的消息 队列,多个生产者向一个文件尾部追加消息,消费者从文件读取消息

    方法2.1:使用record append接口,保证数据至少被成功的写入一次。但是应用需要应对 不一致数据,和重复数据。

    • 为了校验不一致数据,给每个记录添加校验数(checksum),读取方通过校验数识别 出不一致的数据,并且丢弃不一致的数据。

    • 如果应用读取数据没有幂等处理,那么应用就需要过滤掉重复数据。写入方写入记录时 额外写入一个唯一的标识(ident ifier),读取方读取数据后通过标识辨别之前是否已经 处理过这个标识的数据。

    bb

    GFS的设计哲学

    可以看出基于GFS的应用需要通过一些特殊的手段来应对GFS松弛的一致性模型带来的各种问 题。GFS的一致性保证对于使用者是非常不友好的,很多人第一次看到这样的一致性保证都是 比较吃惊的。

    那么GFS为什么要设计这样的一致性模型那?GFS在架构上选择这样的设计有它自己的设计哲 学。GFS追求的是简单、够用的原则。GFS主要要解决的问题是如何使用廉价的服务器存储海 量的数据,并且达到非常高的吞吐量(GFS非常好的做到了这2点,但不是本文的主题,这里 就不展开了),并且文件系统本身的实现要简单,能够快速的实现出来(GFS的开发者在开发 完GFS之后,很快就去开发BigT able了)。GFS很好的完成了完成了这样的目标。但是留下了 一致性问题,给使用者带来的负担。但是在GFS应用的前期,一致性不是问题,GFS的主要使 用者(BigT able)就是GFS开发者,他们深知应该如何使用GFS,这种不一致在BigT able中被 很好屏蔽掉(采用上面所说的方法),BigT able提供了很好的一致性保证。

    但是随着GFS使用的不断深入,GFS简单够用的架构开始带来很多问题,一致性问题仅仅是其 中的一个。主导了GFS很⻓时间的Leader Sean Quinlan在一次采访中,详细说明了在GFS度 过了应用的初期之后,这种简单的架构带来的各种问题[1]。

    开源分布式文件系统HDFS,清晰的看到了GFS的一致性模型给使用者带来的不方便,坚定地 摒弃了GFS的一致性模型,提供了很好的一致性保证。HDFS达到了怎样的一致性,这里就不 在展开了,另外再做详细的讨论。

    bb

    总之,保证一直性对于分布式文件系统,甚至所有的分布式系统都是很重要的。

    1.GFS: Evolution on Fast-forward, Sean Quinlan, 2009, 

    https://queue.acm.org/detail.cf m?id=1594206

    来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31562044/viewspace-2646753/,如需转载,请注明出处,否则将追究法律责任。

    转载于:http://blog.itpub.net/31562044/viewspace-2646753/

    展开全文
  • 自古以来关于UI设计一致性的重要性已经有很多论述,这是有充分理由的。不一致的用户界面通常会丧失用户体验对用户粘性也会造成极大的损失,甚至会对产品前途和本质产生不可估量的影响。  但是,UI设计的一致...

    UI设计中一致性为什么这么重要?自古以来关于UI设计一致性的重要性已经有很多论述,这是有充分理由的。不一致的用户界面通常会丧失用户体验对用户粘性也会造成极大的损失,甚至会对产品前途和本质产生不可估量的影响。

    UI设计中一致性为什么这么重要

     

     

      但是,UI设计的一致性到底是什么?UI设计的一致性涉及确保用户界面中的元素统一。它们的外观和行为方式相同。这有助于不断证明用户对用户界面权限的假设,从而产生一种控制感,熟悉度和可靠性。

      为了提高UI设计的一致性,您应力求与UI规范和行为,其他类似的应用程序(竞品)以及您自己的设计保持一致。

      用户界面准则和行为

      在设计时,不同的平台具有不同的UI和可用性准则。例如,如果要设计iOS应用程序的用户界面,则应熟悉iOS人机界面指南,并努力遵守它们。

      竞品一般做法

      您的用户会花时间在其他应用(竞品)上已经不是什么秘密了。结果,他们将熟悉并习惯于它们或其他地方使用的流行模式,规则和交互。考虑到这一点并考虑到它们对设计进行建模是增加可用性的好方法。您可以“带回”用户从以前的经验中积累的知识,而不必担心新的或不熟悉的用户界面会使他们感到迷茫。

      这并不意味着剽窃别人的设计。您也不是临摹其他应用。您想使自己熟悉使用了哪些UI模式以及在其他地方进行了哪些操作来改进自己的设计。

    UI设计中一致性为什么这么重要

     

     

      考虑一下电子商务网站及其上购物车的位置。我们通常会在下面查看要购买的商品,如果要设计电子商务网站的用户界面,则需要考虑将购物车放在类似的位置。

      UI设计一致性

      布局,样式,类型选择和布局只是在整个用户界面中应保持一致的一些元素。如果您已将导航元素放置在屏幕A的应用程序标题中,请不要将其放置在屏幕B的页脚中。移动,更改或丢失元素不仅会让你的用户感到迷茫,甚至可能激励他们放弃使用自己的产品。

      但是,嘿,如果我给产品加点情感化的设计呢?有策略地这样做。适度使用不一致之处以改善设计或增加用户界面的可用性。如果至关重要的是,用户必须注意用户界面中的某个特定元素,或者您需要引起注意,UI设计中一致性为什么这么重要https://www.aaa-cg.com.cn/ui/2873.html?seo1请使其与众不同。想要打破繁琐的设计吗?使用适度的不一致来增加视觉兴趣,只要它们不会影响操作。

      UI设计一致性的好处

      那么,在与UI准则和行为,其他类似应用程序/网站,您自己的设计为应用程序和用户所做的目标是什么?一些主要好处是:

      可用性提高

      一致性使您的用户可以更轻松地浏览和使用您的应用程序,因为他们不必学习新的知识。他们知道会发生什么,因为他们之前已经在您的应用程序或其他地方学到了它。自然,这将使您的用户感到愉悦,并激发他们继续与您的应用互动。

      消除混乱

      一致的用户界面可促进通信。使用视觉一致性来确定内容的优先级,使其可导航或突出显示其中的重要部分。通过使用一致性来创建逻辑结构并明确定义用户可以在哪里找到的内容,您可以减少用户的考虑时间,提升用户体验。

      引起情绪反应

      我们已经提到过,UI设计的一致性可以使用户更轻松地浏览和使用您的应用程序。这将使您的用户对自己管理拇指下的内容的能力充满信心,并会因愉快的体验而引起积极的情感反应。

      实践中的一致性

      如果您不熟悉UI世界,那么其中许多概念可能很难形象化。为了更好地理解在实践中可以转化为一致性的内容,请查看以下完全具有一致性的应用示例。

      出色的应用程式:清除

      我不记得有多少次我引用或使用 Clear作为一个示例示例,该示例示例了UI设计中要达到的许多优秀品质。如果您不了解,可以去AAA教育官网查看相关文章!

      从一致性角度来看,它所做的不只是外观相同。我已经在几种不同的设备上使用了该应用程序,并且喜欢在所有这些设备上导航所需的简单手势几乎都相同,即使在Mac上也是如此。它使我在如何使用该应用程序方面积累的知识可以转移到所有设备上,从而提高了可用性。

      如Duolingo APP

      Duolingo是一款有趣的应用程序,宗旨是帮助任何人学习一种新语言。它不仅使学习变得有趣,而且还展示了如何在用户界面中实现有益的样式一致性。

      应用程序中的按钮,字体,导航元素甚至插图均经过精心设计,目的是彼此视觉上保持一致。颜色,灯光和形状的设计旨在使整个应用程序以及围绕应用程序的所有材料(例如其网站)保持一致。它不仅使该应用程序易于浏览,而且使其具有品牌感和专业性。

      Duolingo在视觉上令人愉悦且易于使用,使该应用程序能够唤起强烈而积极的情感反应。

     

    摘自:https://www.aaa-cg.com.cn/ui/2873.html?seo1

    展开全文
  • 作者简介 陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架 构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富大规模系统构 建和基础架构研发经验,...

    7dd031fc5fb38f294d8a5128cabd5218.png

    作者简介 陈东明,饿了么北京技术中心架构组负责人,负责饿了么的产品线架构设计以及饿了么基础架 构研发工作。曾任百度架构师,负责百度即时通讯产品的架构设计。具有丰富的大规模系统构 建和基础架构的研发经验,善于复杂业务需求下的大并发、分布式系统设计和持续优化。作者微信公众号dongming_cdm,欢迎关注。

    GFS(Google File System)是Google公司开发的一款分布式文件系统。

    在2003年,Google 发表一篇论文详细描述了GFS的架构。GFS,MapReduce,Bigt able并称为Google的三架⻢ ⻋,推动了Google的高速发展。其他互联公司和开源领域纷纷模仿,构建自己的系统。可以 这么说,GFS,MapReduce,Bigt able引领了互联网公司的分布式技术的发展。但GFS架构设 计并不是一个完美的架构设计,它有诸多方面的问题,一致性的欠缺就是其中的一个问题。

    本文探讨一下GFS架构设计、分析其在一致性方面的设计不足,并且看一下一致性对分布式系统 的重要性。

    7c4a686dd5699d2ce0dd687284efe936.png

    我们从GFS的接口设计说起。

    接口

    GFS采用了人们非常熟悉的接口,但是被没有实现如POSIX的标准接口。通常的一些操作包 括:create, delete, open, close, read, write, record append等。create,delete,open,close 和POSIX的接口类似,这里就不强调说了。这里详细讲述一下write, record append提供的语意。

    • write操作可以将任意⻓度len的数据写入到任意指定文件的位置off set

    • record append操作可以原子的将len<=16MB的数据写入到指定文件的末尾

    之所以GFS设计这个接口,是因为record append不是简单的offset等于文件末尾的write操作。 record append是具有原子特性的操作,本文后面会详细解释这个原子特性。

    write和record append操作都允许多个客户端并发操作。

    架构

    GFS架构如下图。(摘自GFS的论文)

    c90ab960994fc260b88cecf25484f9e2.png

    主要的架构部件有GFS client, GFS master, GFS chunkserver。一个GFS集群包括:一个 master,多个chunkserver,集群可以被多个GFS client访问。

    GFS客户端(GFS client)是运行在应用(Application)进程里的代码,通常以SDK形式 存在。

    GFS中的文件被分割成固定大小的块(chunk),每个块的⻓度是固定64MB。GFS chunkserver把这些chunk存储在本地的Linux文件系统中,也就是本地磁盘中。通常每个 chunck会被保存3个副本(replica)。一个chunkserver会保存多个块,每个块都会有一个 标识叫做块柄(chunk handle)

    GFS 主(mast er)维护文件系统的元数据(met adat a),包括名字空间(namespace, 也就是常规文件系统的中的文件树),访问控制信息,每个文件有哪些chunk构成,chunk 存储在哪个chunkserver上,也就是位置(locat ion)。

    dc82695a8bfe6ed67aecbcff82f0fa8f.png

    在这样的架构下,文件的读写基本过程简化、抽象成如下的过程:

    写流程

    1.client 向mast er发送creat e请求,请求包含文件路径和文件名。mast er根据文件路径和文件 名,在名字空间里创建一个对象代表这个文件。

    2.client 向3个chunkserver发送要写入到文件中的数据,每个chunkserver收到数据后,将数据 写入到本地的文件系统中,写入成功后,发请求给mast er告知mast er一个chunk写入成功, 与此同时告知client 写入成功。

    3.mast er收到chunkserver写入成功后,记录这个chunk与机器之间的对应关系,也就是chunk 的位置。

    4.client 确认3个chunkserver都写成功后,本次写入成功。

    这个写流程是一个高度简化抽象的流程,实际的写流程是一个非常复杂的流程,要考虑到写入 类型(即,是随机写还是尾部追加),还要考虑并发写入,后面我们继续详细的描述写流程, 解释GFS是如何处理不同的写入类型和并发写入的。

    6b3755256af7bf294618946d6e5d9788.png

    读流程

    1.应用发起读操作,指定文件路径,偏移量(off set )

    2.client 根据固定的chunk大小(也即64MB),计算出数据在第几个chunk上,也就是chunk索 引号(index)

    3.client 向mast er发送一个请求,包括文件名和索引号,mast er返回3个副本在哪3台机器上, 也就是副本位置(location of replica)。

    4.client 向其中一个副本的机器发送请求,请求包换块柄和字节的读取范围。 

    5.chunkserver根据块柄和读取范围从本地的文件系统读取数据返回给client

    这个读流程未做太多的简化和抽象,但实际的读流程还会做一些优化,这些优化和本文主题关 系不大就不展开了。

    838bceb4ffdffb041e86f10d9bed6466.png

    写流程详述

    我们详细的讲一下写入流程的几个细节。

    1.名字空间管理(namespace management)和锁保护(locking)

    写入流程需要向主发送creat e这样请求,来操作保存在主上的名字空间。 如果有多个客户端同时进行写入操作,那么这些客户端也会同时操作向主发送creat e请求。主 在同一时间收到多个请求,通过加锁的方式,防止多个客户端同时修改同一个文件的元数据。

    2.租约(Lease)

    client 需要向3个副本写入数据,在并发的情况下会有多个client 同时向3个副本写入数据。GFS 需要一个规则来管理这些数据的写入。 这个规则简单来讲,每个chunk都只有一个副本来管理多个client 的并发写入。也就是说,对 于一个chunk,mast er会授予其中一个副本一个租约(lease),具有租约的副本来管理所有要写 入到这个chunk的数据写入,这个具有租约的副本称之为首要副本(primary)。其他的副本称之 为二级副本(secondary)

    3.变更次序(Mutation Order) 

    将对文件的写入(不管是在任意位置的写入,还是在末尾追加)称之为变更(Mut at ion)。 Primary管理所有client 的并发请求,让所有的请求按照一定顺序(Order)应用到chunk上。

    344f185b1942907a19c5abe730751fc3.png

    4.基本变更流程

    1).client 询问mast er哪个chunkserver持有这个chunk的lease,以及其他的副本的位置。如果 没有副本持有lease,mast er挑选一个副本,通知这副本它持有lease。


    2).mast er回复client ,告述客户端首要副本的位置,和二级副本的位置。客户端联系首要副 本,如果首要副本无响应或者回复客户端它不是首要副本,则客户端重新联系主。 

    3).客户端向所有的副本推送数据。客户端可以以任意的顺序推送。每个chunkserver会缓存这 些数据在缓冲区中。 

    4).当所有的副本都回复说已经收到数据后,客户端发送一个写入请求(write request)给首 要副本,这个请求里标识着之前写入的数据。首要副本收到请求后,会给写入分配一个连续的 编号,首要副本会按照这个编号的顺序,将数据写入到本地磁盘。 

    5).首要副本将这个带有编号写入请求转发给其他二级副本,二级副本也会按照编号的顺序, 将数据写入本地,并且回复首要副本数据写入成功。 

    6).当首要副本收到所有二级副本的回复时,说明这次写入操作成功。 

    7).首要副本回复客户端写入成功。在任意一个副本上遇到的任意错误,都会报告给客户端失败。

    前面讲的writ e接口就是按照这个基本流程进行的。 下图描述了这个基本过程。(摘自GFS的论文)

    b13069f8816960851bd90a0987374fb2.png

    5.跨边界变更 

    如果一次写入的数据量跨过了一个块的边界,那么客户端会把这次写入分解成向多个chunk的 多个写入。

    b70e009f6917e9d0d166d226b7055488.png

    6.原子记录追加(Atomic Record Appends)

    Record Appends在论文中被称之为原子记录追加(Atomic Record Appends),这个接口也 遵循基本的变更流程,有一些附加的逻辑:客户端把数据推送给所有的副本后,客户端发请求 给首要副本,首要副本收到写入请求后,会检查如果把这个record附加在尾部,会不会超出块 的边界,如果超过了边界,它把块中剩余的空间填充满(这里填充什么并不重要,后面我们会 解释这块),并且让其他的二级副本做相同的事,再告述客户端这次写入应该在下一块重试。 如果记录适合块剩余的空间,则首要副本把记录追加尾部,并且告述其他二级副本写入数据在 同样的位置,最后通知客户端操作成功。

    1a14457351a5f1211ef5ccba174ef6c4.png

    原子性

    讲完架构和读写流程,我们开始分析GFS的一致性,首先从原子性开始分析。

    Write和Atomic Record Append的区别 前面讲过,如果一次写入的数量跨越了块的边界,那么会分解成多个操作,writ e和record append在处理数据跨越边界时的行为是不同的。我们举例2个例子来说明一下。


    例子1,文件目前有2个chunk,分别是chunk1, chunk2。

    Client 1要在54MB的位置写入20MB数据。这写入跨越了边界,要分解成2个操作,第一个操 作写入chunk1最后10 MB,第二个操作写入chunk2的开头10MB。Client 2也要在54MB的位置写入20MB的数据。这个写入也跨越边界,也要分解为2个操作, 作为第三个操作写入chunk1最后10 MB,作为第四个操作写入chunk2的开头10MB。

    2个客户端并发写入数据,那么第一个操作和第三个操作在chunk1上就是并发执行的,第二个 操作和第四个操作在chunk2上并发执行,如果chunk1的先执行第一操作再执行第三个操作, chunk2先执行第四个操作再执行第二个操作,那么最后,在chunk1上会保留client 1的写入的 数据,在chunk2上保留了client 2的写入的数据。虽然client 1和client 2的写入都成功了,但最 后既不是client 1想要的结果,也不是client 2想要的结果。最后的结果是client 1和client 2写入 的混合。对于client 1和client 2来说,他们操作都不是原子的。

    例子2,文件目前有2个chunk,分别是chunk1, chunk2。

    Client 要在54MB的位置写入20MB数据。这写入跨越了边界,要分解成2个操作,第一个操作 写入chunk1最后10 MB,第二个操作写入chunk2的开头10MB。chunk1执行第一个操作成功 了,chunk2执行第二个操作失败了,也就是写入的这部分数据,一部分是成功的,一部分是 失败的,这也不是原子操作。

    接下来看record append。由于record append最多能写入16MB的数据,并且当写入的数据量 超过块的剩余空间时,剩余的空间会被填充,这次写入操作会在下个块重试,这2点保证了 record append操作只会在一个块上生效。这样就避免了跨越边界分解成多个操作,从而也就 避免了,写入的数据一部分成功一部分失败,也避免了并发写入数据混合在一起,这2种非原 子性的行为。

    a81c0943f4bc10f673e691abe53fdf18.png

    GFS原子性的含义 

    所以,GFS的原子性不是指多副本之间原子性,而是指发生在多chunk上的多个操作的的原子性。可以得出这样的推论,如果Writ e操作不跨越边界,那么没有跨越边界的writ e操作也满足GFS 所说的原子性。

    GFS多副本不具有原子性 

    GFS一个chunk的副本之间是不具有原子性的,不具有原子性的副本复制,它的行为是:

    一个写入操作,如果成功,他在所有的副本上都成功,如果失败,则有可能是一部分副本 成功,而另外一部分失败。

    在这样的行为如下,失败是这样处理的:

    • 如果是write失败,那么客户端可以重试,直到write成功,达到一致的状态。但是如果在 重试达到成功以前出现宕机,那么就变成了永久的不一致了。

    • Record Append在写入失败后,也会重试,但是与writ e的重试不同,不是在原有的off set 上重试,而是接在失败的记录后面重试,这样Record Append留下的不一致是永久的不一 致,并且还会有重复问题,如果一条记录在一部分副本上成功,在另外一部分副本上失 败,那么这次Record Append就会报告给客户端失败,并且让客户端重试,如果重试后成 功,那么在某些副本上,这条记录就会成功的写入2次。

    我们可以得出,Record Append保证是至少一次的原子操作(at least once atomic)。

    007ced83b0a28712f8b393fd7da61336.png

    一致性

    GFS把自己的一致性称为松弛的一致性模型(relaxed consistency model)。这个模型分析元 数据的一致性和文件数据的一致性,松弛主要是指文件数据具有松弛的一致性。

    元数据的一致性元数据的操作都是由单一的mast er处理的,并且操作通过锁保护,所以是保证原子的,也保 证正确性的。

    文件数据的一致性 

    在说明松弛一致性模型之前,我们先看看这个模型中的2个概念。对于一个文件中的区域:

    • 如果无论从哪个副本读取,所有的客户端都能总是看到相同的数据,那么就叫一致的 (consist ent );

    • 在一次数据变更后,这个文件的区域是一致的,并且客户端可以看到这次数据变更写入的 所有数据,那么就叫界定的(defined)。

    GFS论文中,用下面的这个表格总结了松弛一致性:

    Write

    Record Append

    Serial success

    defined

    defined interspersed with inconsistent

    Concurrent successes

    consistent but undefined

    Failure

    inconsistent

    分别说明表中的几种情况:

    1.在没有并发的情况下,写入不会有相互干扰,成功的写入是界定的,那么必然也就是一致的 

    2.在有并发的情况下,成功的写入是一致的,但不是界定的,也就是我们前面所举的例子2。 

    3.如果写入失败,那么副本之间就会出现不一致。

    4.Record Append能够保证是界定的,但是在界定的区域之间夹杂着一些不一致的区域。 Record Append会填充数据,不管每个副本是否填充相同的数据,这部分区域都会认为是 inconsist ent 的。

    49e339ef4e7e3b7fa3098c420053fb92.png

    如何适应松弛的一致性模型

    这种松弛的一致性模型,实际上是一种不能保证一致性的模型,或者更准确的说是一致性的数 据中间夹杂不一致数据。

    这些夹杂其中的不一致数据,对应用来说是不可接受的。在这种一致性下,应该如何使用GFS 那?GFS的论文中,给出了这样几条使用GFS的建议:依赖追加(append)而不是依赖覆盖 (overwrite),设立检查点(checkpointing),写入自校验(write self-validating),自记录标识 (self-identifying records)。

    使用方式1:只有单个写入的情况下,按从头到尾的方式生成文件。 

    • 方法1.1:先临时写入一个文件,再全部数据写入成功后,将文件改名成一个永久的名 字,文件的读取方只能通过永久的文件名访问到这个文件。 

    • 方法1.2:写入方按一定的周期,写入数据,写入成功后,记录一个写入进度检查点 (checkpoint ),这个检查点包括应用级的校验数(checksum)。读取方只去校验、处理检查点之前的数据。即便写入方出现宕机的情况,重启后的写入方或者新的写入方,会 从检查点开始,继续重新写入数据,这样就修复了不一致的数据。

    使用方式2:多个写入并发向一个文件尾部追加,这个使用方式就像是一个生产消费型的消息 队列,多个生产者向一个文件尾部追加消息,消费者从文件读取消息

    方法2.1:使用record append接口,保证数据至少被成功的写入一次。但是应用需要应对 不一致数据,和重复数据。

    • 为了校验不一致数据,给每个记录添加校验数(checksum),读取方通过校验数识别 出不一致的数据,并且丢弃不一致的数据。

    • 如果应用读取数据没有幂等处理,那么应用就需要过滤掉重复数据。写入方写入记录时 额外写入一个唯一的标识(ident ifier),读取方读取数据后通过标识辨别之前是否已经 处理过这个标识的数据。

    6c3edcc7e11ef8556a77e2cbc36d66ec.png

    GFS的设计哲学

    可以看出基于GFS的应用需要通过一些特殊的手段来应对GFS松弛的一致性模型带来的各种问 题。GFS的一致性保证对于使用者是非常不友好的,很多人第一次看到这样的一致性保证都是 比较吃惊的。

    那么GFS为什么要设计这样的一致性模型那?GFS在架构上选择这样的设计有它自己的设计哲 学。GFS追求的是简单、够用的原则。GFS主要要解决的问题是如何使用廉价的服务器存储海 量的数据,并且达到非常高的吞吐量(GFS非常好的做到了这2点,但不是本文的主题,这里 就不展开了),并且文件系统本身的实现要简单,能够快速的实现出来(GFS的开发者在开发 完GFS之后,很快就去开发BigT able了)。GFS很好的完成了完成了这样的目标。但是留下了 一致性问题,给使用者带来的负担。但是在GFS应用的前期,一致性不是问题,GFS的主要使 用者(BigT able)就是GFS开发者,他们深知应该如何使用GFS,这种不一致在BigT able中被 很好屏蔽掉(采用上面所说的方法),BigT able提供了很好的一致性保证。

    但是随着GFS使用的不断深入,GFS简单够用的架构开始带来很多问题,一致性问题仅仅是其 中的一个。主导了GFS很⻓时间的Leader Sean Quinlan在一次采访中,详细说明了在GFS度 过了应用的初期之后,这种简单的架构带来的各种问题[1]。

    开源分布式文件系统HDFS,清晰的看到了GFS的一致性模型给使用者带来的不方便,坚定地 摒弃了GFS的一致性模型,提供了很好的一致性保证。HDFS达到了怎样的一致性,这里就不 在展开了,另外再做详细的讨论。

    7f3b23ecc9b7fd3a368fa4050400dfd0.png

    总之,保证一直性对于分布式文件系统,甚至所有的分布式系统都是很重要的。

    1.GFS: Evolution on Fast-forward, Sean Quinlan, 2009, 

    https://queue.acm.org/detail.cf m?id=1594206

    往期推荐:

    • 微服务的历史与陷阱

    • 侵入式服务治理方案,读这一篇就够

    • OpenResty 完全开发指南:构建百万级别并发的 Web 应用

    • 阿里高级技术专家:研发效能的追求永无止境

    • 案例诊断:“交易耗时8S”缉凶记

      

    技术琐话 

    以分布式设计、架构、体系思想为基础,兼论研发相关的点点滴滴,不限于代码、质量体系和研发管理。

    f565b890ca44b3ebe9f9187315965d79.png

    展开全文
  •  我们遵循一致性的原则目的是为了减少用户认知负荷,用户能够轻易上手使用产品,熟悉的导航路径,熟悉的设计模式。  我们知道,我们的用户是忙碌的,没有耐心,他们不愿意花更多时间来学习使用你的产品。所以我们...

      为什么一致性在UI设计中很重要,我们平常挂嘴边的一致性原则到底是什么?一致性原则如何影响用户行为?价值在哪里?

      今天我就带大家探讨我们在处理界面的时候,如何遵循一致性原则,该如何去做?

      一致性原则的优势

      我们遵循一致性的原则目的是为了减少用户认知负荷,用户能够轻易上手使用产品,熟悉的导航路径,熟悉的设计模式。

      我们知道,我们的用户是忙碌的,没有耐心,他们不愿意花更多时间来学习使用你的产品。所以我们在做设计时候,就尽量多遵循常用的UI Patterns,它是什么?是一种常用可用性问题的一种通用解决方案。

      但是如果一味遵循常有的Design Patterns,会导致我们界面看起来无创新,那么该什么时候突破这种界限,下面我会简单举例说明。

      影响它的关键要素

      颜色、间距、字体大小、图标一致性、规则一致性、交互操作等,我们在做界面设计时,如何科学把控这些?

      这里就要告诉大家一个常用的设计法则“重复”“节奏”“韵律”,学过平面设计的同学应该知道,这几个点吧,在平面设计中运用比较多的种设计方法。

      举一个例子,重复如何运用在UI设计中?

      重复间距

    UI设计中的一致性原则

     

    UI设计中的一致性原则

     

     

      上两图中,我们看可以看出里面设计采用的间距都是基于8的倍数,并重复运用。有节奏、有韵律的重复使用这些间距,可以产生节奏美。

      重复控件

    UI设计中的一致性原则

     

     

      上图facebook截图,UI设计中的一致性原则https://www.aaa-cg.com.cn/ui/2651.html按钮表象层圆角基因一致。如果有大小差异,它们使用参数化原则去定义圆角,大一点的控件圆角大一些,反之亦然。

      布局规则

    UI设计中的一致性原则

     

     

      上图是腾讯视频界面截图,我们可以看到他们在布局上制定了一些规则。

      一致性原则影响着用户行为

      如导航模式;一级导航,二级导航,如果采用常用设计模式,用户基本可以很轻松的找到自己想要的内容。

      再来说下颜色如何影响用户行为:比如系统里面定义蓝色是可点击的颜色,那么我们在做设计是时候就要注意,哪些可点击,颜色使用是否合理,同类颜色,表达相同的含义,就不能用在其他意义的元素上。

      大原则:相同含义的元素在不同的地方执行相同的操作时候,反馈机制需要一致。

    UI设计中的一致性原则

     

     

      上图左边是ios的开关,右边是materials design 材质设计系统的开关,这两种开关大同小异,它符合用户心理表真,我们日常生活中家里灯开关不就和这个类似吗?所以在我们设计这些就可以尽量遵循用户的心里表真,保持内部外部一致性。

      再比如在ios系统里面在对应列表上左滑动是可以对该列表操作的,那么在安卓里面的列表设计就需要慎用左滑操作。

      总结

      一致性设计大方向为产品有更杰出的体验,在保证用户体验良好的同时,我们需要与同类产品做出差异化竞争设计,这就需要我们平时多观察互联网设计趋势,国外设计趋势,集合自己品牌去打造一套好用的产品。

      在产品设计中我们时刻留意着关键元素的一致性的运用,确保产品整体体验一致。

      1.颜色:在使用颜色上需要严格去定义,比如绿色用于正确颜色,红色用语错误颜色,蓝色是可以点击颜色,这些都是常用的设计模式。

      2.布局/排版:布局遵循最小化设计原则,导航路径清晰可见,一级导航和二级导航一定要区分清楚,二者不可混用,排版布局上尽量遵循格式塔心理学原理。

      3.字体:一个app使用一种字体贯穿整个产品设计,字体大小运用重复原则,重复可以使其保持一致性。

      4.交互:这里我简单说下,操作模式,反馈机制要符合用户心理表真,常用功能操作流程要和外部环境保持一致性,比如我点击界面上蓝色文字这时候就要有正确反馈机制,而不是出一个弹窗。

      5.图标:图标一致性我相信大家都懂吧,以前写了一篇关于图标规范的,有兴趣的可以去看下,5招轻松打造系统图标规范。

    展开全文
  • 在大数据场景下,分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库满足数据库最基本的ACID特性中的“一致性”(Consistency)的保障,在分布式技术发展下,数据一致性的解决方法和技术也...
  • 产品设计中所涉及的产品结构设计,主要是产品的外部壳体结构设计。...拉深件结构设计,其外形应均匀对称,轮廓变化柔和、顺滑,顶部凸缘宽度一致,底部孔大小合适,整体结构设计合理,工艺良好。冲裁件...
  • 如果不进行终端一致性测试,那么多厂商终端的一致性和互联互通性将成为制约TD-SCDMA产业化和商业运营关键因素之一,所以尽早开展终端一致性测试方面工作就显得尤为重要。  一、GMM协议规范介绍  GMM是非接入层...
  • 摘要:产品标准规定了各种试验项目和... 电子元器件质量一致性检验包括:对每个检验批进行A组(包括元器件目检和尺寸检验以及元器件主要特性试验)和B组(包括其他重要特性试验)以及在固定时间间隔内从已通过逐
  • 一致性读实现原理

    2020-11-24 11:30:52
    现在,主流关系数据库产品基本实现了MVCC特性,快照在MVCC中起着重要的作用,代表某一时刻数据版本,它是实现一致性基础。在更新操作没提交前,数据前镜像存储在Undo中,利用Undo可以实现一致性读,事务...
  • 先有著名CAP理论定义过分布式环境下二者不可兼得关系,又有神秘Paxos协议号称是史上最简单分布式系统一致性算法并获得图灵奖,再有开源产品ZooKeeper实现ZAB协议号称超越Paxos。 在大数据场景下,分布式...
  • 1)zookeeper实际上是yahoo开发,用于分布式中一致性处理框架。 2)背景介绍:最初其作为研发Hadoop时产品。由于分布式系统中一致性处理较为困难,其他分布式系统没有必要 费劲重复造轮子,故随后分布式...
  • 1)zookeeper实际上是yahoo开发,用于分布式中一致性处理框架。 2)背景介绍:最初其作为研发Hadoop时产品。由于分布式系统中一致性处理较为困难,其他分布式系统没有必要 费劲重复造轮子,故随后...
  • 摘要:产品标准规定了各种试验... 电子元器件质量一致性检验包括:对每个检验批进行A组(包括元器件目检和尺寸检验以及元器件主要特性试验)和B组(包括其他重要特性试验)以及在固定时间间隔内从已通过逐批检
  • 先有著名CAP理论定义过分布式环境下二者不可兼得关系,又有神秘Paxos协议号称是史上最简单分布式系统一致性算法并获得图灵奖,再有开源产品ZooKeeper实现ZAB协议号称超越Paxos。 在大数据场景下,分布式...
  • 1)zookeeper实际上是yahoo开发,用于分布式中一致性处理框架。 2)背景介绍:最初其作为研发Hadoop时产品。由于分布式系统中一致性处理较为困难,其他分布式系统没有必要 费劲重复造轮子,故随后...
  • 现在,主流关系型数据库产品基本都实现了MVCC特性,快照在MVCC中起着重要的作用,代表某一时刻数据版本,它是实现一致性基础。在更新操作没提交前,数据前镜像存储在Undo中,利用Undo可以实现一致性读,...
  • 现在主流关系型数据库产品基本都实现了MVCC特性,快照在MVCC中起着重要的作用,代表某一时刻数据版本,它是实现一致性基础。在更新操作没提交前,数据前镜像存储在Undo中,利用Undo可以实现一致性读,事务...
  • 这次准备聊聊分布式系统中关注点:一致性问题。文章中间穿插着输出一些产品、运营、以及个人深度思考。本文从普遍认为分布式系统中,最最最重要的数据一致性开始。内容适合人群...
  • MySQL是一个RDBMS(关系型数据库管理系统),由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下...随着互联网高速发展,互联网服务可用变得越发重要,数据容灾也随之成为各企业关键任务。在数据容灾中,数据库集
  • 元数据是什么在大数据治理、应用背景下,数据即资产,简单说元数据实现了对数据资产统一标准化管理。...元数据一致性测试场景有哪些场景1:元数据迁移在数据迁移中,一般包含数据(表)、结构(字段)、关系(...
  • 新浪科技通过商家页面体验了WEB窗口下京东IM,发现其与淘宝旺旺等IM界面基本一致,但目前仅提供满意度评价、消息记录和加入购物车等基本功能。     据悉,京东IM正式向客户推出时间将视测试情况而定,...
  • 10G网络变压器从研发到目前批量生产还仅有少数厂家具备相对成熟生产工艺和测试系统,华强盛近几年也开始大量投入10G网络变压器产器生产研究...网络变压器生产中最重要品质认定就是产品系统电气一致性项目测试...
  • 这项由独立小组研究公司“立即研究”开展的调查揭示了企业中事务一致性的状态,以及企业为了更快地部署产品和解决方案而愿意牺牲哪些客户体验。 调查发现,近70%的信息技术决策者和开发人员认为可靠的数据库事务和...
  • 现在,主流关系型数据库产品基本都实现了MVCC特性,快照在MVCC中起着重要的作用,代表某一时刻数据版本,它是实现一致性基础。在更新操作没提交前,数据前镜像存储在Undo中,利用Undo可以实现一致性读,...
  • 我感觉代码质量很重要,现在很多出来程序员非常不重视代码质量,很多时候大家以为只要做出来功能就够了,但实际上是远远不够。我感觉这样写出来代码根本不是产品,而是toy program。 大家好像都不太...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 871
精华内容 348
关键字:

产品一致性的重要性