精华内容
下载资源
问答
  • 自古以来关于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

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

    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/

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

    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

    展开全文
  • 一致性读实现原理

    2021-03-07 16:42:14
    现在,主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,...

    现在,主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,事务回滚以及异常恢复等操作,下面就聊聊MySQL事务,MVCC,快照及一致性读的原理与实现。

    MySQL中的事务

    事务在RDBMS系统中概念基本都是一样的,是由一组DML语句构的工作单元,要么全部成功,要么全部失败。
    在这里插入图片描述
    开发过程中,比较关心长事务,即包含DML语句多的工作单元,事务太长会导致一些错误,例如可能由于事务数据包大小超过参数max_allowed_packet设置会导致程序报错,也可能有事务中某个SQL对应接口报错,导致整个服务调用失败,在程序设计时,应该考虑避免长事务带来的业务影响。

    事务的ACID

    在这里插入图片描述
    原子性是事务隔离的基础,隔离性和持久性是手段,最终目的是为了保持数据的一致性。

    数据库的一致性:是指数据库从一个一致性状态变到另一个一致性状态。

    事务的并发问题

    • 脏读:事务A读取了事务B未提交的数据。
    • 不可重复度:事务A多次读取同一份数据,事务B在此过程中对数据修改并提交,导致事务A多次读取同一份数据的结果不一致。
    • 幻读:事务A修改数据的同时,事务B插入了一条数据,当事务A提交后发现还有数据没被修改,产生了幻觉。

    不可重复读侧重于update或者delete操作,幻读侧重于insert。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。可以用行锁解决不可重复读,用间隙锁解决幻读,这里的幻读指的是当前读。

    事务隔离级别

    事务隔离是数据库处理的基础之一,隔离级别在多个事务同时进行更改和执行查询时,对性能与结果的可靠性、一致性和可再现性之间的平衡进行调整,InnoDB利用不同的锁策略支持不同隔离级别。MySQL中有四种隔离级别,分别是读未提交(READ UNCOMMITTED),读已提交(READ COMMITTED),可重复读(REPEATABLE READ)以及串行化(SERIALIZABLE)。mysql的默认隔离级别是可重复读。
    在这里插入图片描述

    InnoDB并发控制

    MVCC特性

    InnonDB是一个支持行锁的存储引擎,为了提供更好支持的并发,使用了非锁定读,不需要等待访问数据上的锁释放,而是读取行的一个快照,该方法是通过InnonDB MVCC特性实现的。

    MVCC是Multi-Version Concurrency Control的简称,即多版本并发控制,作用是让事务在并行发生时,在一定隔离级别前提下,可以保证在某个事务中能实现一致性读,也就是该事务启动时根据某个条件读取到的数据,直到事务结束时,再次执行相同条件,还是读到同一份数据,不会发生变化。

    mvcc的优点

    读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,可以增加系统的并发性能。

    在MVCC中,有两种读操作:快照度和当前读。
    在这里插入图片描述

    MVCC快照

    MVCC内部使用的一致性读快照称为Read View,在不同的隔离级别下,事务启动时或者SQL语句开始时,看到的数据快照版本可能也不同,在RR、RC隔离级别下会用到 Read view。
    在这里插入图片描述
    InnoDB 里面每个事务有一个唯一的事务ID,称为Transaction ID,它是在事务开始的时候向InnoDB的事务系统申请的,是按申请顺序严格递增的。而每行数据都有多个版本。每次事务更新数据的时候,都会生成一个新的数据版本Read View,并且把Transaction ID赋值给这个数据版本的事务 ID,标记为 row_trx_id。同时旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它,数据表中的一行记录,其实可能有多个数据版本 ,每个版本有自己的 row_trx_id。

    InnoDB行格式

    目前InnoDB默认的行格式Dynamic,是Compat格式的增强版,记录头结构信息占用5个字节,事务ID和回滚指针分别占用6和7个字节,行格式如下:
    在这里插入图片描述
    记录头结构
    在这里插入图片描述
    数据行存储

    #创建表
    mysql> create table store_users (id int not null auto_increment primary key comment '主键id',name varchar(20) not null default '' comment '姓名');
    # 查看表状态信息
    mysql> show table status like 'store_users'\G
         Row_format: Dynamic    #默认行格式为Dynamic
               Rows: 0          #行数
     Avg_row_length: 0          #平均行长度
        Data_length: 16384      #初始化段大小16K
        
    #开启事务,插入数据
    mysql> begin;
    mysql> insert into store_users values(null, 'aaaaa'),(null, 'bbbbb');
    #查看InnoDB分配的事务ID
    mysql> select trx_id from information_schema.innodb_trx\G
    trx_id: 8407246  #事务ID
    

    分析表的行头信息以及隐藏的事务ID和回滚指针。

    用Linux下的工具hexdump进行分析

    $ hexdump -C -v /usr/local/var/mysql/test/store_users.ibd > store_users.txt
    $ vi store_users.txt
    00010060 02 00 1b 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00 |…infimum…|
    00010070 73 75 70 72 65 6d 75 6d 05 00 00 10 00 1c 80 00 |supremum…|
    00010080 00 01 00 00 00 80 48 ce 83 00 00 01 d8 01 10 61 |…H…a| #Record Header信息
    00010090 61 61 61 61 05 00 00 18 ff d6 80 00 00 02 00 00 |aaaa…|
    000100a0 00 80 48 ce 83 00 00 01 d8 01 1d 62 62 62 62 62 |…H…bbbbb|
    000100b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |…|

    00010070 73 75 70 72 65 6d 75 6d 05 00 00 10 00 1c 80 00 |supremum…|

    00010080 00 01 00 00 00 80 48 ce83 00 00 01 d8 01 1061 |…H…a|

    00010090 61 61 61 61 05 00 00 18 ff d6 80 00 00 02 00 00 |aaaa…|

    1. 10表示变长字段长度,只有一个varchar(20)没有超过256字节,且没有NULL值。
    2. 00代表NULL标志位,第一行没有为NULL数据。
    3. 字符a的十六进制是61,即61 61 61 61 61代表的是字段值aaaaa
    4. 00 00 00 80 48 ce 6个字节就是Transaction ID,转换成十进制8407246,正是上面information_schema.innodb_trx.trx_id列的值,trx_id: 8407246 。
    5. 83 00 00 01 d8 01 10 7个字节是Rollback Pointer。
    6. 1c 80 00 00 01 是5个字节,代表Record Header信息。

    隔离级别与快照

    REPEATABLE READ

    默认的隔离级别,一致读快照(Read View)是在第一次SELECT发起时建立,之后不会再发生变化。如果在同一个事务中发出多个非 锁定SELECT语句,那么这些SELECT语句在事务提交前返回的结果是一致的。
    在这里插入图片描述
    在RR下快照Read View不是事务发起时创建,而是在第一个SELECT发起后创建。
    在这里插入图片描述
    READ COMMITTED

    在READ COMMITTED读已提交下,一致读快照(Read View)是在每次SELECT后都会生成最新的Read View,即每次SELECT都能读取到已COMMIT的数据,就会存在不可重复读、幻读 现象。
    在这里插入图片描述
    Undo回滚段
    在这里插入图片描述
    当开启事务执行更新语句(insert/update/deeldte),会经过Server层的处理生成执行计划,然后调用存储引擎层接口去读写数据,用户没有触发COMMIT或ROLLBACK之前,这些Uncommitted Data的数据称为前镜像(Post Image),数据存储在Undo Log,以便用户回滚或者MySQL Server Crash的恢复,同时Undo Log是循环覆盖使用。

    #开启事务,更新账户余额,不提交事务。
    mysql> start transaction;
    mysql> update account set balance = 100000 where account_no = 10001;
    Rows matched: 1  Changed: 1  Warnings: 0
    

    上面在RR隔离级别下,开启一个事务,做update更新操作,不提交事务,通过show engine innodb status\G查看undo情况。

    Trx id counter 8407258
    Purge done for trx's n:o History list length 33
    ......
    ---TRANSACTION 8407257, ACTIVE 154 sec
    2 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 1
    

    Trx id counter 8407258当前的事务ID,undo log entries 1使用了的undo entries,ACTIVE 154 sec事务持续时间,事务commit后,会调用Purge Thread把undo中的老数据清理掉。

    回滚记录

    insert:反向操作是delete,undo里记录的是delete相关信息,存储主键id即可。

    udpate:反向操作是update,undo里记录的是update前的相关数据。

    delete:反向操作是insert,undo里记录的是insert values(……)相关的记录。

    从这里可以知道,更新操作占用Undo空间的大小排序如下:

    delete > update > insert

    所以不建议物理delete删除数据,会产生大量的Undo Log,Undo快被写满就会发生切换,在次期间会有大量的IO操作,导致业务的DML都会变得很慢。

    一致性读

    MySQL官方文档对一致读的描述:
    在这里插入图片描述
    读操作基于某个时间点得到一份那时的数据快照,而不管同时其他事务对数据的修改。查询过程中,若其他事务修改了数据,那么就需要从 undo log中获取旧版本的数据。这么做可以有效避免因为需要加锁(来阻止其他事务同时对这些数据的修改)而导致事务并行度下降的问题。

    在可重复读(REPEATABLE READ,简称RR)隔离级别下,数据快照版本是在第一个读请求发起时创建的。在读已提交(READ COMMITTED,简称RC)隔离级别下,则是在每次读请求时都会重新创建一份快照。

    一致性读是InnoDB在RR和RC下处理SELECT请求的默认模式。由于一致性读不会在它请求的表上加锁,其他事务可以同时修改数据不受影响。
    在这里插入图片描述
    一行数据有多个版本,每个数据版本有自己的trx_id,每个事务或者查询通过trx_id生成自己的一致性视图。普通select语句是一致性读,一致性读会根据row trx_id和一致性视图确定数据版本的可见性,图中UR1,UR2就是undo,存储在Undo Log中,每次查询时根据当前data page和 Undo page构造出一致性数据页(Consistent Read Page),通过读取CR Page将数据返回给用户。

    总结

    介绍了MySQL事务,快照,MVCC以及Undo,虽然这些东西比较抽象,但是搞清楚这些东西是一件很有意义的事,能够帮助我们更好的理解和使用MySQL,也可以把这种设计思想用在自己业务系统中。其中Undo在MySQL中的作用很重要,它是MVCC能够快速创建快照基础,支撑系统的高并发。

    展开全文
  • 为什么一致性在UI设计中很重要,我们平常挂嘴边的一致性原则到底是什么?一致性原则如何影响用户行为?价值在哪里?  今天我就带大家探讨我们在处理界面的时候,如何遵循一致性原则,该如何去做?  一致性原则的优势...
  • 1)zookeeper实际上是yahoo开发的,用于分布式中一致性处理的框架。 2)背景介绍:最初其作为研发Hadoop时的副产品。由于分布式系统中一致性处理较为困难,其他的分布式系统没有必要 费劲重复造轮子,故随后的分布式...
  • 先一句话概括下zookeeper:zookeeper可谓是目前使用最广泛的分布式组件了。其功能和职责单一,但却非常重要。...由于分布式系统中一致性处理较为困难,其他的分布式系统没有必要 费劲重复造轮子,故随后的分布式系...
  • 摘要:产品标准规定了各种试验... 电子元器件质量一致性检验包括:对每个检验批进行A组(包括元器件的目检和尺寸检验以及元器件的主要特性试验)和B组(包括其他重要特性试验)以及在固定的时间间隔内从已通过逐批检
  • 先有著名的CAP理论定义过分布式环境下二者不可兼得的关系,又有神秘的Paxos协议号称是史上最简单的分布式系统一致性算法并获得图灵奖,再有开源产品ZooKeeper实现的ZAB协议号称超越Paxos。在大数据场景下,分布式...
  • 新浪科技通过商家页面体验了WEB窗口下的京东IM,发现其与淘宝旺旺等IM的界面基本一致,但目前仅提供满意度评价、消息记录和加入购物车等基本功能。     据悉,京东IM正式向客户推出的时间将视测试情况而定,...
  • 如果不进行终端一致性测试,那么多厂商终端的一致性和互联互通性将成为制约TD-SCDMA产业化和商业运营的关键因素之一,所以尽早开展终端一致性测试方面的工作就显得尤为重要。  一、GMM协议规范介绍  GMM是非接入层...
  • 产品设计中所涉及的产品结构设计,主要是产品的外部壳体结构设计。...拉深件的结构设计,其外形应均匀对称,轮廓变化柔和、顺滑,顶部凸缘宽度一致,底部孔大小合适,整体结构设计合理,工艺良好。冲裁件...
  • 现在主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,事务...
  • 这次准备聊聊分布式系统中的关注点:一致性问题。文章中间穿插着输出一些产品、运营、以及个人的深度思考。本文从普遍认为的分布式系统中,最最最重要的数据一致性开始。内容适合人群...
  • 摘要:产品标准规定了各种试验项目和... 电子元器件质量一致性检验包括:对每个检验批进行A组(包括元器件的目检和尺寸检验以及元器件的主要特性试验)和B组(包括其他重要特性试验)以及在固定的时间间隔内从已通过逐
  • 10G网络变压器的从研发到目前批量生产还仅有少数厂家具备相对成熟的生产工艺和测试系统,华强盛近几年也开始大量投入10G网络变压器产器的生产研究...网络变压器的生产中最重要品质认定就是产品系统的电气一致性项目测试...
  • 这项由独立小组研究公司“立即研究”开展的调查揭示了企业中事务一致性的状态,以及企业为了更快地部署产品和解决方案而愿意牺牲哪些客户体验。 调查发现,近70%的信息技术决策者和开发人员认为可靠的数据库事务和...
  • 现在,主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,...
  • 在大数据场景下,分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库满足数据库最基本的ACID特性中的 “一致性”(Consistency)的保障,在分布式技术发展下,数据一致性.
  • 现在,主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,...
  • 先有著名的CAP理论定义过分布式环境下二者不可兼得的关系,又有神秘的Paxos协议号称是史上最简单的分布式系统一致性算法并获得图灵奖,再有开源产品ZooKeeper实现的ZAB协议号称超越Paxos。 在大数据场景下,分布式...
  • 先一句话概括下zookeeper:zookeeper可谓是目前使用最广泛的分布式组件了。其功能和职责单一,但却非常重要。...由于分布式系统中一致性处理较为困难,其他的分布式系统没有必要 费劲重复造轮子,故随后的分布式系...
  • 现在,主流关系型数据库产品基本都实现了MVCC的特性,快照在MVCC中起着重要的作用,代表某一时刻数据的版本,它是实现一致性读的基础。在更新操作没提交前,数据的前镜像存储在Undo中,利用Undo可以实现一致性读,...

空空如也

空空如也

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

产品一致性重要性