|
|
51CTO旗下网站
|
|
移动端

2.3.5.4 Reliable Collections 使用

《Microsoft Azure 管理与开发(下册)平台服务PaaS》本书由世纪互联蓝云Microsoft Azure 开发技术支持团队的资深工程师们编写,主要阐述MicrosoftAzure PaaS 服务的开发应用,涉及计算服务、集成认证服务、数据存储服务、大数据服务等方面的内容。本节为大家介绍Reliable Collections 使用。

作者:世纪互联蓝云公司来源:电子工业出版社|2018-07-12 17:53

2.3.5.4 Reliable Collections 使用

为了方便开发高可用、可缩放且低延迟的应用程序,Service Fabric 提供了ReliableCollections 数据结构。借助它,就可以像编写普通程序一样,调用Reliable Collections 的API 在本地管理状态数据,并能够保证高可用和可缩放的特性。

Reliable Collections 与其他高可用技术最大区别是,它将状态数据以本地方式存储在服务实例内,同时也能实现高可用。这就意味着,他比其他高可用技术更加高效。

(1) 所有的读操作均在本地进行,可保障读取的低延迟和高吞吐量。

(2) 所有的写入只会产生少量的网络IO,可保障写入的低延迟和高吞吐量。

可以将Reliable Collections 认为是 System.Collections 的演变,它们是一种新的集合,专门为云应用程序和分布式应用程序设计,且不会给开发人员增加复杂度。目前ReliableCollections 支持以下四个特性。

(1) 可复制性:在多个副本之间复制以实现高可用性。

(2) 可保存:数据会保存至本地磁盘,可在发生大规模中断(例如:数据中心断电)时保持持续性。

(3) 异步:API 采用异步模式,以确保在I/O 时不会阻塞线程。

(4) 事务性:API 利用事务抽象方法,可以在一个服务内管理多个Reliable Collections。

1. Reliable Collections 事务特性

Reliable Collections 的事务提供全新的强一致性。为了达到强一致性,Service Fabric确保多数副本(多数仲裁)记录整个事务后,才能够完成事务提交。Reliable Collections事务支持以下两种隔离级别。

(1) 可重复的读取:当前事务多次读取指定数据,前后都是一致,在当前事务提交之前,不允许其他事务修改当前事务修改的数据。

(2) 快照:当事务开始时,会将读取的数据做一个快照,之后的读取都是跟快照保持一致,即使此时其他事务对该数据做了修改,当前事务也没法得知修改。

Reliable Collections 将在事务创建时根据副本的操作和角色,自动选择事务使用隔离级别。表2.3.5-2 描述了Reliable Dictionary 和Reliable Queue 操作的默认隔离级别。

表2.3.5-2

Reliable Collections 所有的事务在中止或者提交事务之前,不会释放所获取的锁。Reliable Dictionary 对所有单个实体的操作都使用行级锁,Reliable Queue 使用操作级别锁,允许出栈的事务和入栈的事务同时进行,但为了保证FIFO 特性,如果出栈后,发现队列为空,入栈操作就会锁定。两种集合写入操作都是采用排他锁,对于读取操作,锁定取决于几个因素。使用快照读取的数据都是无锁定的。任何可重复的读默认都是采用共享锁。即允许并发事务读取同一个资源,任何其他事务都不能修改该资源。

但是对于任何支持可重复读操作的读取操作,如果读取数据后想要更新该数据,就应使用更新锁,而非排他锁。一次只有一个事务可以获得资源的更新锁,并且更新锁是一种非对称的锁,用于防止当并发事务为了后续的更新操作而锁定资源时发生死锁。另外,请注意,可靠集合的API 的超时参数可以用作死锁检测。例如两个事务正在同时尝试读取和更新同一资源时,他们有可能发生死锁,因为他们最后都拥有共享锁,在这种情况下,其中一个操作或者两个操作会将超时,从而防止死锁。

2. 持久化模型

可靠状态管理器和Reliable Collection 都以检查点和增量日志的方式作为持久化模型。在该模型中,每个状态修改的日志都将被记录到磁盘上,类似于MySQL 的Binlog,这种增量的备份,记录的操作日志有很多冗余,而且会占用很大的磁盘空间。所以Service Fabric又加入了检查点的方式,当持久化备份文件达到一定大小时,可靠状态管理器就会截断日志,并重新创建新的文件来记录新的操作,然后针对当前Reliable Collections 的插入检查点,对在该点之前的数据进行整理,形成一个完整备份,每当日志记录达到一定大小时,都会触发检查点机制,如图2.3.5-10 所示。

3. Reliable Dictionary 和Reliable Queue

目前,Reliable Collections 下主要有以下两个集合。

(1) Reliable Dictionary:表示可复制,事务性,异步的键/值对即可,类似于ConcurrentDictionary,键和值都可以是任何类型。

(2) Reliable Queue:表示可复制,事务性,异步的严格的FIFO 队列。

在之前的示例中,使用了Reliable Dictionary,并向里面存储了计数结果。以下是示例代码,基本所有的Reliable Dictionary 的操作都需要一个事务对象,在一个事务中,对资源的所有操作都具有关联性。可以通过调用分区ITransaction 的StateManager 的CreateTransaction 方法创建事务对象,当事务对象传递给Reliable Dictionary 的AddAsync方法内部,因为AddAsync 是修改Dictionary 的对应键的值,所以会在修改时锁定该键,如果有其他事务来修改,则会被阻塞。在默认情况下,方法最多被阻塞4 秒,超时后会报出TimeoutException,可以捕获该异常,在程序中实现重试机制。在调用commitAsync 后,提交所有事务的操作。具体而言,它将提交信息附加到本地节点的日志文件,同时提交记录到所有的辅助副本中,辅助副本在接受记录后,会回复主副本。当多数副本(包含主副本)都成功后,所有的数据修改就会被认为成功持久化,并释放ITransaction 对象所占用的锁,使其他线程可以操作相同的键值。

示例代码:

  1. try {  
  2. using (ITransaction tx = base.StateManager.CreateTransaction()) {  
  3. await m_dic.AddAsync(tx, key, value, cancellationToken);  
  4. await tx.CommitAsync();  
  5. }  
  6. }  
  7. catch (TimeoutException) {  
  8. await Task.Delay(100, cancellationToken); goto retry;  

这里需要注意,当调用AddAsync 修改Dictionary 的值,之后再修改其属性值,代码如下,在普通的.NET 程序中,第二步操作,将数据存放到Dictionary,然后修改该数据的属性,这样可以修改该数据的属性值,同样也会改变Dictionary 内的值,但是对于ReliableDictionary 这样操作是错误的。因为Reliable Collections 的添加会将数据序列化,然后存储到磁盘中,用于同步到其他副本,而第二步的修改只是针对内存中的值。当服务重启时,该值就会恢复到上次保存的值。这样就会造成数据丢失,引起业务异常引发的系统崩溃。

  1. await m_dic.AddAsync(tx, name, user);  
  2. user.LastLogin = DateTime.UtcNow; // 错误! 


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

基于Project2003的项目管理

本书的上一版本《基于Project 2002的项目管理》上市以后得到了读者的欢迎,为了更好地将Project 2003新版本的应用介绍给读者,我们重新进行...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊