分布式数据存储与管理
CAP理论
Consistency,一致性 是指所有节点在同一时刻的数据是相同的,即更新操作执行结束并响应用户完成后,所有节点存储的数据会保持相同。
Availability,可用性 是指系统提供的服务一直处于可用状态,对于用户的请求可即时响应。
Partition Tolerance,分区容错性 是指在分布式系统遇到网络分区的情况下,仍然可以响应用户的请求。网络分区是指因为网络故障导致网络不连通,不同节点分布在不同的子网络中,各个子网络内网络正常。
CAP 理论指的就是,在分布式系统中 C、A、P 这三个特征不能同时满足,只能满足其中两个。
在实际场景中,网络环境不可能百分之百不出故障,比如网络拥塞、网卡故障等,会导致网络故障或不通,从而导致节点之间无法通信,或者集群中节点被划分为多个分区,分区中的节点之间可通信,分区间不可通信。这种由网络故障导致的集群分区情况,通常被称为“网络分区”。
在分布式系统中,网络分区不可避免,因此分区容错性 P 必须满足。
CAP选择策略及应用:保 CA 弃 P、保 CP 弃 A、保 AP 弃 C
比如,对于涉及钱的交易时,数据的一致性至关重要,因此保 CP 弃 A 应该是最佳选择。而对于其他场景,大多数情况下的做法是选择 AP 而牺牲 C,因为很多情况下不需要太强的一致性(数据始终保持一致),只要满足最终一致性即可。
最终一致性指的是,不要求集群中节点数据每时每刻保持一致,在可接受的时间内最终能达到一致就可以了。
保CA弃P
在分布式系统中,现在的网络基础设施无法做到始终保持稳定,网络分区(网络不连通)难以避免。牺牲分区容错性 P,就相当于放弃使用分布式系统。
保 CP 弃 A
如果一个分布式场景需要很强的数据一致性,或者该场景可以容忍系统长时间无响应的情况下,保 CP 弃 A 这个策略就比较适合。一个保证 CP 而舍弃 A 的分布式系统,一旦发生网络分区会导致数据无法同步情况,就要牺牲系统的可用性,降低用户体验,直到节点数据达到一致后再响应用户。
保证CP的系统:Redis、HBase、ZooKeeper
ZooKeeper 集群包含多个节点(Server),这些节点会通过分布式选举算法选出一个 Leader 节点。在 ZooKeeper 中选举 Leader 节点采用的是 ZAB 算法,在 ZooKeeper 集群中,Leader 节点之外的节点被称为 Follower 节点,Leader 节点会专门负责处理用户的写请求:当用户向节点发送写请求时,如果请求的节点刚好是 Leader,那就直接处理该请求;如果请求的是 Follower 节点,那该节点会将请求转给 Leader,然后 Leader 会先向所有的 Follower 发出一个 Proposal,等超过一半的节点同意后,Leader 才会提交这次写操作,从而保证了数据的强一致性。
当出现网络分区时,如果其中一个分区的节点数大于集群总节点数的一半,那么这个分区可以再选出一个 Leader,仍然对用户提供服务,但在选出 Leader 之前,不能正常为用户提供服务;如果形成的分区中,没有一个分区的节点数大于集群总节点数的一半,那么系统不能正常为用户提供服务,必须待网络恢复后,才能正常提供服务。
这种设计方式保证了分区容错性,但牺牲了一定的系统可用性。
保 AP 弃 C
如果一个分布式场景需要很高的可用性,或者说在网络状况不太好的情况下,该场景允许数据暂时不一致,那这种情况下就可以牺牲一定的一致性了。
网络分区出现后,各个节点之间数据无法马上同步,为了保证高可用,分布式系统需要即刻响应用户的请求。但,此时可能某些节点还没有拿到最新数据,只能将本地旧的数据返回给用户,从而导致数据不一致的情况。
适合保证 AP 放弃 C 的场景有很多。比如,很多查询网站、电商系统中的商品查询等,用户体验非常重要,所以大多会保证系统的可用性,而牺牲一定的数据一致性。
采用保 AP 弃 C 的系统也有很多,比如 CoachDB、Eureka、Cassandra、DynamoDB 等。
CAP 中的 C 强调的是数据的一致性,也就是集群中节点之间通过复制技术保证每个节点上的数据在同一时刻是相同的。
ACID 中的 C 强调的是事务执行前后,数据的完整性保持一致或满足完整性约束。也就是不管在什么时候,不管并发事务有多少,事务在分布式系统中的状态始终保持一致。
CAP 中的 A 指的是可用性(Availability),也就是系统提供的服务一直处于可用状态,即对于用户的请求可即时响应。
ACID 中的 A 指的是原子性(Atomicity),强调的是事务要么执行成功,要么执行失败。
分布式数据存储系统三要素
分布式存储系统的核心逻辑,就是将用户需要存储的数据根据某种规则存储到不同的机器上,当用户想要获取指定数据时,再按照规则到存储数据的机器里获取。
当用户(即应用程序)想要访问数据 D,分布式操作引擎通过一些映射方式,比如 Hash、一致性 Hash、数据范围分类等,将用户引导至数据 D 所属的存储节点获取数据。
三要素:数据生产者 / 消费者、数据索引和数据存储。
生产和消费数据
根据数据的特征,这些不同的数据通常被划分为三类:结构化数据、半结构化数据和非结构化数据。
结构化数据通常是指关系模型数据,其特征是数据关联较大、格式固定。火车票信息比如起点站、终点站、车次、票价等,就是一种结构化数据。结构化数据具有格式固定的特征,因此一般采用分布式关系数据库进行存储和查询。
半结构化数据通常是指非关系模型的,有基本固定结构模式的数据,其特征是数据之间关系比较简单。比如 HTML 文档,使用标签书写内容。半结构化数据大多可以采用键值对形式来表示,比如 HTML 文档可以将标签设置为 key,标签对应的内容可以设置为 value,因此一般采用分布式键值系统进行存储和使用。
非结构化数据是指没有固定模式的数据,其特征是数据之间关联不大。比如文本数据就是一种非结构化数据。这种数据可以存储到文档中,通过 ElasticSearch(一个分布式全文搜索引擎)等进行检索。
数据分片技术,是指分布式存储系统按照一定的规则将数据存储到相对应的存储节点中,或者到相对应的存储节点中获取想要的数据,这是一种很常用的导购技术。这种技术,一方面可以降低单个存储节点的存储和访问压力;另一方面,可以通过规定好的规则快速找到数据所在的存储节点,从而大大降低搜索延迟,提高用户体验。
按照数据范围,采用哈希映射、一致性哈希环等对数据划分;数据特征
针对数据范围的数据分片方案是指,按照某种规则划分数据范围,然后将在这个范围内的数据归属到一个集合中。这就好比数学中通常讲的整数区间,比如 1~1000 的整数,[1,100]的整数属于一个子集、[101,1000]的整数属于另一个子集。
为了提高分布式系统的可用性与可靠性,除了通过数据分片减少单个节点的压力外,数据复制也是一个非常重要的方法。数据复制就是将数据进行备份,以使得多个节点存储该数据。
在实际的分布式存储系统中,数据分片和数据复制通常是共存的:
数据通过分片方式存储到不同的节点上,以减少单节点的性能瓶颈问题;而数据的存储通常用主备方式保证可靠性,也就是对每个节点上存储的分片数据,采用主备方式存储,以保证数据的可靠性。其中,主备节点上数据的一致,是通过数据复制技术实现的。
分布式数据库,通过表格来存储结构化数据,方便查找。常用的分布式数据库有 MySQL Sharding、Microsoft SQL Azure、Google Spanner、Alibaba OceanBase 等。
分布式键值系统,通过键值对来存储半结构化数据。常用的分布式键值系统有 Redis、Memcache 等,可用作缓存系统。
分布式存储系统,通过文件、块、对象等来存储非结构化数据。常见的分布式存储系统有 Ceph、GFS、HDFS、Swift 等。
存储介质的选择,本质就是选择将数据存储在磁盘还是内存(缓存)上:
磁盘存储量大,但 IO 开销大,访问速度较低,常用于存储不经常使用的数据。比如,电商系统中,排名比较靠后或购买量比较少、甚至无人购买的商品信息,通常就存储在磁盘上。
内存容量小,访问速度快,因此常用于存储需要经常访问的数据。比如,电商系统中,购买量比较多或排名比较靠前的商品信息,通常就存储在内存中。
业界主流的分布式数据存储系统有哪些?分布式数据库、分布式键值系统和分布式文件系统
主流的分布式数据库,主要包括 MySQL Sharding、SQL Azure、Spanner、OceanBase 等
主流的分布式存储系统,主要包括 Ceph、GFS、HDFS 和 Swift 等
数据分布方式:哈希与一致性哈希
在分布式系统中,具体是如何实现数据索引或数据分布的呢?目前最常用的方法就是哈希和一致性哈希。
数据分布设计原则-->在分布式数据存储系统中,存储方案选型时,通常会考虑数据均匀、数据稳定和节点异构性这三个维度。
数据均匀:存储的均匀与访问的均匀
从数据均匀的维度考虑,主要包括两个方面:不同存储节点中存储的数据要尽量均衡,避免让某一个或某几个节点存储压力过大,而其他节点却几乎没什么数据。比如,现在有 100G 数据,4 个同类型节点,通常希望数据存储时尽可能均衡,比如每个节点存储 25G 数据。
另外,用户访问也要做到均衡,避免出现某一个或某几个节点的访问量很大,但其他节点却无人问津的情况。比如,现在有 1000 个请求,对于上述存储数据的 4 个节点,处理用户访问请求尽量均衡,比如每个节点处理 250 个请求,当然这是非常理想的情况,实际情况下,每个节点之间相差不太大即可。
数据稳定:
从数据稳定的维度考虑,当存储节点出现故障需要移除或者扩增时,数据按照分布规则得到的结果应该尽量保持稳定,不要出现大范围的数据迁移。
节点异构性:
从节点异构性的维度考虑,不同存储节点的硬件配置可能差别很大。比如,有的节点硬件配置很高,可以存储大量数据,也可以承受更多的请求;但,有的节点硬件配置就不怎么样,存储的数据量不能过多,用户访问也不能过多。如果这种差别很大的节点,分到的数据量、用户访问量都差不多,本质就是一种不均衡。所以,一个好的数据分布算法应该考虑节点异构性。
隔离故障域:
隔离故障域,是为了保证数据的可用和可靠性。比如,我们通常通过备份来实现数据的可靠性。但如果每个数据及它的备份,被分布到了同一块硬盘或节点上,就有点违背备份的初衷了。所以,一个好的数据分布算法,应该为每个数据映射一组存储节点,这些节点应该尽量在不同的故障域,比如不同机房、不同机架等。
性能稳定性:
性能稳定性是指,数据存储和查询的效率要有保证,不能因为节点的添加或者移除,造成存储或访问性能的严重下降。
数据分布方法
哈希是指,将数据按照提前规定好的函数(哈希函数)映射到相应的存储节点,即进行一个哈希计算,得到的结果就是数据应该存储的节点。
一致性哈希同样是采用哈希函数,进行两步哈希:对存储节点进行哈希计算,也就是对存储节点做哈希映射;当对数据进行存储或访问时,首先对数据进行映射得到一个结果,然后找到比该结果大的第一个存储节点,就是该数据应该存储的地方。
哈希是一种非常常用的数据分布方法,其核心思想是,首先确定一个哈希函数,然后通过计算得到对应的存储节点。
哈希算法的一个优点是,只要哈希函数设置得当,可以很好地保证数据均匀性,但有一个较为严重的缺点,就是稳定性较差。比如,随着数据量的增加,三个节点的容量无法再满足存储需求了,需要再添加一个节点。这时,哈希函数变成了 id%4,原先存储在那三个节点的数据需要重新计算,然后存入相应节点,即需要大规模的数据迁移,显然会降低稳定性。
哈希方法适用于同类型节点且节点数量比较固定的场景。目前,Redis 就使用了哈希方法。
一致性哈希
一致性哈希是指将存储节点和数据都映射到一个首尾相连的哈希环上,存储节点可以根据 IP 地址进行哈希,数据通常通过顺时针方向寻找的方式,来确定自己所属的存储节点,即从数据映射在环上的位置开始,顺时针方向找到的第一个存储节点。
一致性哈希是对哈希方法的改进,在数据存储时采用哈希方式确定存储位置的基础上,又增加了一层哈希,也就是在数据存储前,对存储节点预先进行了哈希。
这种改进可以很好地解决哈希方法存在的稳定性问题。当节点加入或退出时,仅影响该节点在哈希环上顺时针相邻的后继节点,不会发生大规模的数据迁移。
一致性哈希方法比较适合同类型节点、节点规模会发生变化的场景。目前,Cassandra 就使用了一致性哈希方法。
一致性哈希方法虽然提升了稳定性,但随之而来的均匀性问题也比较明显,即对后继节点的负载会变大。有节点退出后,该节点的后继节点需要承担该节点的所有负载,如果后继节点承受不住,便会出现节点故障,导致后继节点的后继节点也面临同样的问题。
带有限负载的一致性哈希
带有限负载的一致性哈希方法的核心原理是,给每个存储节点设置了一个存储上限值来控制存储节点添加或移除造成的数据不均匀。当数据按照一致性哈希算法找到相应的存储节点时,要先判断该存储节点是否达到了存储上限;如果已经达到了上限,则需要继续寻找该存储节点顺时针方向之后的节点进行存储。
带有限负载的一致性哈希方法比较适合同类型节点、节点规模会发生变化的场景。目前,在 Google Cloud Pub/Sub、HAProxy 中已经实现该方法,应用于 Google、Vimeo 等公司的负载均衡项目中。
其实,哈希、一致性哈希、带有限负载的一致性哈希,都没有考虑节点异构性的问题。如果存储节点的性能好坏不一,数据分布方案还按照这些方法的话,其实还是没做到数据的均匀分布。
带虚拟节点的一致性哈希
带虚拟节点的一致性哈希方法,核心思想是根据每个节点的性能,为每个节点划分不同数量的虚拟节点,并将这些虚拟节点映射到哈希环中,然后再按照一致性哈希算法进行数据映射和存储。
带虚拟节点的一致性哈希方法比较适合异构节点、节点规模会发生变化的场景。目前 Memcached 缓存系统实现了该方法
这种方法不仅解决了节点异构性问题,还提高了系统的稳定性。当节点变化时,会有多个节点共同分担系统的变化,因此稳定性更高。
比如,当某个节点被移除时,对应该节点的多个虚拟节点均会移除,而这些虚拟节点按顺时针方向的下一个虚拟节点,可能会对应不同的物理节点,即这些不同的物理节点共同分担了节点变化导致的压力。
当然,这种方法引入了虚拟节点,增加了节点规模,从而增加了节点的维护和管理的复杂度,比如新增一个节点或一个节点故障时,对应到虚拟节点构建的哈希环上需要新增和删除多个节点,数据的迁移等操作相应地也会很复杂。
数据分片和数据分区,有何区别?
数据分区是从数据存储块的维度进行划分,不同的分区物理上归属于不同的节点。对于数据分区,可用于存储不同的数据,也可以用来存储相同的数据实现数据备份。
数据分片是从数据的维度进行划分,是指将一个数据集合按照一定的方式划分为多个数据子集,不同的数据子集存在不同的存储块上,而这些存储块可以在不同的节点上,也可以在同一节点上。具体的数据分片策略可以采用我今天和你分享的哈希、一致性哈希等方法。数据分片是实现“导购”的关键技术,目的是构建索引,为数据确定位置,包括存储数据和查询数据时确定数据位置。
数据分片和数据分区是两个不同的概念,且属于分布式存储系统中不同角色的技术,前者是实现“导购”的关键技术,后者是“货架”相关的技术,不可直接等同。一个提供确定数据索引的位置,一个提供合适的数据存储位置。
数据复制技术
在进行分布式数据存储设计时,通常会考虑对数据进行备份,以提高数据的可用性和可靠性,而实现数据备份的关键技术就是“数据复制技术”。
概括来讲,数据复制是一种实现数据备份的技术。比如,现在有节点 1 和节点 2,节点 1 上存储了 10M 用户数据,直观地说,数据复制技术就是将节点 1 上的这 10M 数据拷贝到节点 2 上,以使得节点 1 和节点 2 上存储了相同的数据,也就是节点 2 对节点 1 的数据进行了备份。当节点 1 出现故障后,可以通过获取节点 2 上的数据,实现分布式存储系统的自动容错。也就是说,数据复制技术,可以保证存储在不同节点上的同一份数据是一致的。这样当一个节点故障后,可以从其他存储该数据的节点获取数据,避免数据丢失,进而提高了系统的可靠性。
对于数据的一致性,通常是指不同节点上数据要保持一致。要实现不同节点上的数据一致,数据复制技术必不可少。为此,对于分布式存储系统中的数据复制技术来讲,也需要在一致性和可用性之间做出一些权衡。因此,这就导致出现了多种数据复制技术方法,大体上有三类:
第一类方法,比较注重一致性,比如同步复制技术;
第二类方法,则更注重可用性,比如异步复制技术;
第三类方法,是介于前两者之间的,比如半同步复制技术。
同步复制技术是指,当用户请求更新数据时,主数据库必须要同步到备数据库之后才可给用户返回,即如果主数据库没有同步到备数据库,用户的更新操作会一直阻塞。这种方式保证了数据的强一致性,但牺牲了系统的可用性。
在同步复制技术中,主数据库需要等待所有备数据库均操作成功才可以响应用户,性能不是很好,会影响用户体验,因此,同步复制技术经常用于分布式数据库主备场景(对于一主多备场景,由于多个备节点均要更新成功后,主节点才响应用于,所需时延比较长)或对数据一致性有严格要求的场合,比如金融、交易之类的场景。
异步复制技术是指,当用户请求更新数据时,主数据库处理完请求后可直接给用户响应,而不必等待备数据库完成同步,即备数据库会异步进行数据的同步,用户的更新操作不会因为备数据库未完成数据同步而导致阻塞。显然,这种方式保证了系统的可用性,但牺牲了数据的一致性。
异步复制技术大多应用在对用户请求响应时延要求很高的场景,比如很多网站或 App 等需要面向实际用户,这时后台的数据库或缓存如果采用同步复制技术,可能会流失用户,因此这种场景采用异步复制技术就比较合适。
半同步复制技术的核心是,用户发出写请求后,主数据库会执行写操作,并给备数据库发送同步请求,但主数据库不用等待所有备数据库回复数据同步成功便可响应用户,也就是说主数据库可以等待一部分备数据库同步完成后响应用户写操作执行成功。
半同步复制技术通常有两种方式:
一种是,当主数据库收到多个备数据库中的某一个回复数据同步成功后,便可给用户响应写操作完成;另一种是,主数据库等超过一半节点(包括主数据库)回复数据更新成功后,再给用户响应写操作成功。
ZooKeeper 集群采用的数据复制技术就是第二种半同步复制方案。在 ZooKeeper 集群中,写请求必须由 Leader 节点进行处理,每次写请求 Leader 会征求其他 Follower 的同意,只有当多数节点同意后写操作才可成功,因此保证了较高的一致性。
对于半同步复制技术,因为只有部分备节点更新数据后,主节点即可返回响应用户。那么,对于未回复数据更新结果的节点,如何解决可能存在的数据不一致或冲突呢?
对于这个问题,不同的场景有不同的处理方式,需要根据用户的需求进行选择,比如以最新数据为准、以最大数据为准等,没有统一的评判规则,和用户的需求紧密相关。
缓存技术
缓存技术一般是指,用一个更快的存储设备存储一些经常用到的数据,供用户快速访问。用户不需要每次都与慢设备去做交互,因此可以提高访问效率。
分布式缓存就是指在分布式环境或系统下,把一些热门数据存储到离用户近、离应用近的位置,并尽量存储到更快的设备,以减少远程数据传输的延迟,让用户和应用可以很快访问到想要的数据。
主流的分布式缓存系统 Redis 和 Memcached
Redis 分布缓存原理
以字典结构将数据存储在内存中,应用可直接到内存读写 Redis 存储的数据。Redis 集群是一个典型的去中心化结构,每个节点都负责一部分数据的存储,同时,每个节点还会进行主备设计来提高 Redis 的可靠性
支持多数据结构、支持持久化和主备同步。
第一,Redis 支持多数据结构。
Redis 是一个基于内存的 key-value 数据库,为了方便支持多应用的缓存,比如缓存文本类型、数据库的查询结果(字段与字段对应的值)等等,支持的数据结构不仅有简单的 k/v 类型,还可以支持 List、Set、Hash 等复杂类型的存储。以 Hash 这种复杂类型的存储为例,Redis 将 Hash 视作一个整体当作数据库的 value(可以是一个对象,比如结构体对象)进行存储。如果把 Hash 结构的整体看作对象的话,Hash 结构里的 key-value 相当于该对象的属性名和属性值。
第二,Redis 支持持久化。
持久化是指,将数据从内存这种易失性存储设备中写入磁盘,从而让数据永久保存。Redis 中存储的数据虽然是基于内存的,但它也提供了持久化的机制,主要有两种方式:RDB 和 AOF。
RDB(Redis DataBase),也称快照方式,简单来说就是 Redis 会定时将内存中的数据备份到磁盘中,形成一个快照,比如每天保存一下过去一周的数据。这样当节点出现故障时,可以根据快照恢复到不同版本的数据。这种方式有一个明显的缺点,是会造成数据丢失,即当节点出现故障时,新数据可能还未备份到磁盘中。
AOF(Append Only File)的出现主要弥补了 RDB 数据不一致的问题,其思想与上一讲提到的数据库复制技术中 binary log 类似,即记录下 Redis 中所有的更新操作。在 Redis 中,提供了三种实现 AOF 的策略:AOF_FSYNC_NO (不同步),即不会自动触发写操作的同步;AOF_FSYNC_EVERYSEC (每秒同步),即每隔一秒都会将写操作同步到磁盘;AOF_FSYNC_ALWAYS (每次写都同步),即每次发生写操作会立即同步到磁盘。Redis 中默认采用 AOF_FSYNC_EVERYSEC(每秒同步)的策略,因为这种策略的性能很不错,而且一旦出现故障,最多只会丢失一秒的数据。
第三,Redis 支持主备同步。
在 Redis 中,采用的是异步复制技术,但 Redis 可以通过配置 min-replicas-to-write 和 min-replicas-max-lag 这两个参数来有效地保证数据一致性。
比如,设置 min-replicas-to-write=3、min-replicas-max-lag=10,表示当至少有 3 个备数据库连接主数据库的延迟时间小于 10s 时,主数据库才可以执行写操作。延迟时间是从最后一次收到备数据库的心跳开始计算,通常每秒发送一次心跳。
除了上面对写操作的同步,在 Redis 中,还有两种情况是需要进行数据同步的:
一种情况是初次同步,即备数据库刚启动时的数据同步;
另一种情况是,因网络故障导致主备数据库断开连接,待网络恢复后的备数据库的数据同步。
完整重同步的流程如下所示:
当备服务器启动时,会向主服务器发送 SYNC 命令;
主服务器收到命令后会生成 RDB(快照)文件,并记录从现在起新执行的写操作;
RDB 生成后会发送给备服务器,备服务器通过 RDB 文件进行数据更新;
更新完成后,主服务器再将新记录的写操作发送给备服务器,备服务器执行完这些新记录的写操作,便与主服务器的数据保持一致了。
部分重同步就是,当网络恢复后,主数据库将主备数据库断开连接之后的一系列写操作发送给备服务器,备数据库执行这些写操作,从而保证数据保持一致。
在这种方式的实现中,主备数据库会共同维护一个复制偏移量,这样主数据库就知道应该将哪些写操作发给备数据库,备数据库同步时也知道应该从哪里继续执行操作。
主数据库的复制偏移量为 5000 时,向备数据库发送了 100 个字节的数据,发送结束后复制偏移量为 5100。此时主备数据库连接断开,备数据库没有接收到这 100 个字节的数据,等到备数据库重新与主数据库连接上之后,会给主数据库发送 PSYNC 命令,并带上自己的复制偏移量 5000,主数据库接收到信息后,根据接收到的复制偏移量,将 5000 之后的数据发给备数据库,从而完成数据的部分重同步。
Memcached 分布式缓存原理:Memcached 也是一个基于内存的高性能 key-value 缓存数据库。
Redis 的集群结构是每个节点负责一部分哈希槽,且每个节点可以设计主备。与 Redis 不同,Memcached 集群采用一致性哈希的思路,使用的是 Ketama 算法。该算法的主要思想就是,带虚拟节点的一致性哈希算法。
对于数据结构的支持,Memcached 仅支持简单的 k/v 数据类型,如果想要存储复杂的数据类型,比如 List、Set 和 Hash 等,需要客户端自己处理,将其转化为字符串然后进行存储。这样就导致了一个缺点,操作不灵活。比如,Memcached 存储的数组中有一个元素需要修改,则需要将整个数组的数据取出来,修改后再整体写入到数据库中 。
而对于持久化,Memcached 是不支持的。这意味着断电时,Memcached 中存储的数据将会全部丢失。因为内存是一种易失性存储设备,断电后将不会存储数据。
在 Memcached 中,服务器和服务器之间没有任何通信,即自身不支持主备。如果想要实现高可用,需要通过第三方实现。
除了分布式存储中的缓存,还有计算机体系结构和网络中的缓存,它们又分别是什么呢?
计算机体系结构中的缓存,通常是指专用的缓存设备。由于内存和 CPU 访问速度相差很大,为了提高 CPU 的性能,计算机内部在 CPU 与内存之间设置了相应的缓存。现在大多数机器分为三级缓存:L1 高级缓存、L2 高级缓存和 L3 高级缓存。就访问速度来讲,L1 高级缓存 > L2 高级缓存 > L3 高级缓存 > 内存。其中,L1 高级缓存的访问速度,几乎和 CPU 中寄存器的访问速度一样快。有了这三级缓存,很多数据不需要到内存中读取,而直接读取这三级缓存中的数据即可,缩短了数据访问的时间,使得计算机运行速度变得更快。
网络访问中的缓存,通常是指本地的“磁盘”。通过网络访问数据时,需要与远程服务器交互来进行传输,而网络间数据传输以及远程服务器对请求的响应,会耗费很多时间。如果本机器的磁盘可以对你经常访问的远程内容进行存储,这样就不用每次都与远程服务器交互,从而减少网络数据传输与服务器响应的延迟,极大地提高性能。
可以看出,缓存的概念是相对的,基于不同的背景或应用场景,缓存所映射的存储设备是不一样的。
目前,在 Google Cloud Pub/Sub、HAProxy 中已经实现该方法,应用于 Google、Vimeo 等公司的负载均衡项目中。