- 浏览: 318658 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
完善自我:
支持一下!
揭秘IT人才特点:中美印日四国程序员比较 -
悲剧了:
好文,看玩thinking in java的提到的异常处理,看 ...
高效的Java异常处理框架(转) -
yin_bp:
开源框架bbossgroups页支持组件异步方法调用哦,详情请 ...
Spring 3中异步方法调用 -
flyjava:
sun的悲哀
Apache怒了,威胁说要离开JCP
原文:http://www.infoq.com/cn/articles/write-behind-caching
介绍
应用程序通常使用数据缓存来提高性能,尤其针对那些大量应用只读事务的应用程序更是如此。当数据发生变化时,这些应用程序会直接更新数据库。问题在于随着负载的增加,响应时间将随着更新的增长而延长。数据库并不擅于执行大量处理少量记录的并发事务。相对而言,处理批量事务才是数据库的强项。
敏捷中国大会2010四大主题:业务敏捷、管理实践、技术实践、组织变革,为技术团队搭建开放的交流平台。现在报名,九折优惠!Powered by ThoughtWorks
实际上,随着额外负载的增加,响应时间急剧攀升,数据库就会耗用CPU或者磁盘。传统方式下,内存中缓存(in-memory caches)的存储会被限制,以满足JVM的空余内存空间。一旦我们需要缓存更多数量的数据,缓存就会不停地释放数据,从而为其他数据留出存储空间。而且,所需的记录必须被不停地读取,从而使得缓存无效,并将数据库直接暴露给完整的读操作负载。
目前已有多个可用的产品,包括IBM? WebSphere? eXtreme Scale,Oracle Coherence和Gigaspaces,它们均支持将一簇JVM的空闲内存作为缓存,而不是单个的JVM。这就使得合并JVM越多,缓存支持的规模就越大。如果这些JVM都是额外的具有CPU、存储器和网络的服务器,那么读请求的服务就是可伸缩的。通过使用write-behind技术,这些产品还提供更新请求的可伸缩服务。write-behind缓存的可伸缩性使得它可以解决极端事务处理(extreme transaction processing, XTP)场景。Gartner将XTP定义为:“一种应用风格,目的在于支持对分布式事务处理应用程序的设计、开发、部署、管理和维护,其特点在于对性能、可伸缩性、可用性、安全、可管理与可靠性的特别要求。”
本文将使用IBM WebSphere eXtreme Scale演示如何利用write-behind模式优化应用程序的性能。write-behind功能能够根据用户配置的间隔时间,异步地对后端数据库进行批量更新。这一方式具备的明显优势就是能够减少数据库调用,从而减少事务负载,更快地访问网格(grid)中的对象。它比write-through 缓存具有更快的响应时间,后者对缓存的更新会导致对数据库的及时更新。使用write-behind,不再要求事务等待数据库的写操作完成。此外,它能够避免应用程序出现数据库错误,因为write-behind缓冲通过内存复制单元来保持变化,直到它将其传输给数据库。
定义和配置关键概念
什么是“write-behind”缓存
在write-behind缓存中,数据的读取和更新通过缓存进行,与write-through缓存不同,更新的数据并不会立即传到数据库。相反,在缓存中一旦进行更新操作,缓存就会跟踪脏记录列表,并定期将当前的脏记录集刷新到数据库中。作为额外的性能改善,缓存会合并这些脏记录。合并意味着如果相同的记录被更新,或者在缓冲区内被多次标记为脏数据,则只保证最后一次更新。对于那些值更新非常频繁,例如金融市场中的股票价格等场景,这种方式能够很大程度上改善性能。如果股票价格每秒钟变化100次,则意味着在30秒内会发生30 x 100次更新。合并将其减少至只有一次。
在WebSphere eXtreme Scale中,脏记录列表会被复制,以保证JVM退出时仍然存在,用户可以通过设置同步和异步复制的数字,指定复制级别。同步复制意味着JVM退出时,没有数据丢失,但由于主进程必须等待获得变更信息的复制品,因此速度会慢一些。异步复制更快,但如果JVM在复制之前就退出,就会导致最近事务发生的变化可能会丢失。脏记录列表将使用大型的批事务写入到数据源中。如果数据源不可用,则网格会继续处理请求,之后再重新尝试。网格能够随着规模的变化提供更短的响应时间,因为变化会单独地提交到网格,即使数据库被停止,事务仍然能够提交。
Write-behind缓存并不能放之四海而皆准。write-behind的本质注定用户看到的变化,即使被提交也不会立即反映到数据库中。这种时间延迟被称为“缓存写延迟(cache write latency)”或“数据库fubai(database staleness)”;发生在数据库变更与更新数据(或者使得数据无效)以反映其变更的缓存之间的延迟则被称为“缓存读延迟(cache read latency)”或“缓存fubai(cache staleness)”。如果系统的每部分在访问数据时都通过缓存(例如,通过公共接口),那么,由于缓存总是保持最新的正确记录,采用write- behind技术就是值得的。可以预见,采用write-behind的系统,作出变更的唯一路径就只能是缓存。
不管是稀疏的缓存还是完整的缓存,都可以用于write-behind特性。稀疏缓存仅存储数据的子集,可以被延迟填充。它通常使用关键字进行访问,因为缓存中并非所有的数据都能够使用,使用缓存进行查询可能无法执行。完整缓存包含了所有的数据,但在首次加载的时候耗时更长。第三种可行之策则是兼取二者所长。首先在短时间内预装载数据的子集,然后延迟加载其余数据。预装载的子集数据大约在总数的20%,但它能够满足80%的请求。
采用这一方式使用缓存的应用程序适用的场景为:适用简单CRUD(创建,读取,更新和删除)模式的分区数据模型。
配置write-behind功能
对于WebSphere eXtrem Scale而言,在objectgrid.xml配置中,通过将writeBehind属性添加到backingMap元素,就启用了write- behind功能,如下所示。参数的值使用语法“"[T(time)][;][C(count)]",用以指定数据库更新发生的时间。当到达设置的时间,或者队列集中的变化次数达到设定的count值,更新就会被写入到持久存储中。
列表1:write-behind配置的示例
<objectGrid name="UserGrid"> <backingMap name="Map" pluginCollectionRef="User" lockStrategy="PESSIMISTIC" writeBehind="T180;C1000" />
JPA加载器
WebSphere eXtreme Scale使用了加载器读取内存中缓存的数据,以及将数据写入到数据库中。从WebSphere eXtreme Scale的6.1.0.3版本开始,包含了两个内建的加载器,它们与JPA提供器相交互,负责将关系数据映射到ObjectGrid集中,这两个内建的加载器分别为JPALoader和JPAEntityLoader。JPALoader用于缓存中存储POJO,JPAEntityLoader则用于缓存中存储ObjectGrid实体。
若要配置JPA加载器,就必须修改添加到META-INF目录下的objectgrid.xml和persistence.xml文件。加载器 bean可以与必要的实体类名一起被加入到objectgrid.xml中。在objectgrid.xml中必须定义事务的回调函数,这样就可以接收事务提交或回滚的事件,并将其发送到JPA层。persistence.xml文件则表示一个特殊的JPA提供器,它针对具有提供器的特定属性的持久化单元。
考察一个商业案例
考察一个在线的银行网站,当用户数增长时,响应时间变慢,且存在可伸缩性问题。他们需要在现有硬件环境下支持客户需求。接下来,我们就以这一案例来展示write-behind特性是如何帮助他们解决这一问题的。
用例:门户个性化
与直接从数据库中拉取用户个人信息不同,我们首先会将数据库中取出的个人信息,预先加载到缓存中。这意味着缓存是为读请求服务,而不是数据库。在旧系统中,个人信息的更新同样是直接写入到数据库。在可接受的响应时间内,随着数据库服务器的超负荷,每秒钟发生的并发更新数将受到限制。新的系统则是将个人信息的变更写入到网格中,然后使用write-behind技术将这些变更推到数据库中。这就保证了服务的质量和性能,并完全解除了单实例数据库与读写个人信息操作之间的耦合。现在,客户只需要将更多的JVMs/server添加到网格中,就可以扩大个人信息服务的规模。数据库不再成为瓶颈,因为发送到后端的事务数得到了锐减。更快的响应时间带来更快的页面加载,大大改善了用户体验,有效地利用了个人信息服务器的规模,提高了可用性,因为数据库不再成为单一失败点。
对于本用例,我们对DB2O数据库采用了WebSphere eXtreme Scale以及OpenJPA提供器。这一场景的数据模型为User与UserAccount以及UserTransaction之间的一对多关系。下面为User类的代码片段,展现了这样一种关系:
列表2:用例的实体关系
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = { Cas-cadeType.ALL }) private Set<UserAccount> accounts = new HashSet<UserAccount>(); @OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = { Cas-cadeType.ALL }) private Set<UserTransaction> transactions = new HashSet<UserTransaction>();
1.生成数据库
示例代码包含了PopulateDB类,它能够加载某些用户数据到数据库中。DB2数据库的连接信息被定义在之前展示的 persistance.xml文件中。在persistence.xml中的持久单元名(persistence unit name)将用于创建JPA EntityManagerFactory。用户对象会被创建,然后被批量地持久化到数据库中。
2. 准备缓存
一旦数据库被加载,数据网格代理(data grid agents)就会预先加载缓存。记录被批量写入到缓存中,因此在客户端与服务器之间几乎没有产生通信。还可以使用多客户端(multiple clients)来加快准备时间。在准备缓存时,一些“热门”数据可以作为所有记录的子集,其余数据则可以采用延迟加载。预先加载缓存提高了缓存命中的几率,减少了从后端层中获取数据的需要。在这个例子中,匹配数据库记录的数据会被插入到缓存中,而不是从数据库中加载,从而加快了执行时间。
3.在网格上生成加载
示例代码包含一个客户端驱动器,模仿在网格上的操作,用以演示write-behind缓存功能如何提高性能。客户端包含多个选项调整加载行为。下面的命令使用了10个线程,以每个线程200个请求将500k的记录加载到“UseGrid”网格中。
$JAVA_HOME/bin/java -Xms1024M -Xmx1024M -verbose:gc -classpath $TEST_CLASSPATH ogdriver.ClientDriver -m Map -n 500000 -g UserGrid -nt 10 -r 200 -c $CATALOG_1
4.结果
使用write-behind特性能够显著提高性能。我们分别使用了write-through和write-behind技术运行示例代码,比较了各自的响应时间以及数据库的CPU占用率。插入到缓存中的数据与数据库中的记录相匹配,这就避免了缓存的准备时间,保证读取的响应时间一致,这样才能比较写的响应时间。列表3展示了write-through场景下的响应时间,读取数据花费了不到10ms,而写花费的时间达到了450——550ms。在执行过程中,网络跳转与磁盘I/O操作耗费了大多数时间。列表4展示了write-behind场景下的响应时间,在这种情况下所有的事务都被提交到网格中。从图表中可以看出,它所消耗的读和写的响应时间几乎相同,都消耗了2.5-5ms。这两个图表极为明显地说明,对于更新而言,write- through响应时间更长,而write-behind耗费的更新时间几乎与读取操作相同。如果添加更多的JVM,则能够增加缓存的容量,无需改变响应时间,数据库也不再成为瓶颈。
列表3:采用write-through缓存的响应时间图表
列表4:采用write-behind缓存的响应时间图表
数据库的CPU占用率图表展现了使用write-behind对后端加载的改善。列表5是一幅采用write-through产生的数据库CPU占用图。可以看见,在运行及时写入数据库的所有更新时,CPU的使用是连续的。使用时,CPU空闲状态的波动在4%到10-12%之间。采用write- through技术,后端加载保持了恒定的值。如果采用write-behind,在满足缓存的间隔时间内,后端的加载耗费了更低的CPU占用率,如列表 6所示。该图显示,当数据库较为空闲时,占用率为4%,在三分钟间隔时间结束,或者更新记录数达到峰值时,会批量地将更新写入到磁盘中,此时CPU占用率会在短时间内达到12-16%。write-behind的配置可以调整,以满足自己的运行环境,这其中包括写事务的比例,相同记录更新的频率,以及数据库的更新延迟。
列表5:采用write-through缓存的数据库CPU占用率图表
列表6:采用write-behind缓存的数据库CPU占用率图表
结论
本文重新审视了write-behind缓存技术,并展示了如何在WebSphere eXtreme Scale下实现这一特性。write-behind缓存功能减少了后端加载,降低了事务的响应时间,并将应用程序与后端失败隔离开。这些优势以及它配置的简单性,都使得write-behind缓存异常的强大。
参考
- Gartner RAS Core Research Note G00131036, Gartner Group - http://www.gartner.com/
- Gartner RAS核心研究备忘录G00131036,Gartner组织- http://www.gartner.com/
- User’s Guide to WebSphere eXtreme Scale
- WebSphere eXtreme Scale用户指南
- WebSphere eXtreme Scale Wiki
资源
- WebSphere eXtreme Scale free trial download
- WebSphere eXtreme Scale V7.0 on Amazon Elastic Compute Cloud (EC2)
致谢
感谢Billy Newport,Jian Tang,Thuc Nguyen,Tom Alcott和Art Jolin对撰写本文给予的帮助。
查看英文原文:Extreme Transaction Processing Patterns: Write-behind Caching
发表评论
-
Qi4j和NoSql运动
2010-11-16 23:00 162524日一篇Qi4j and the NoSQL ... -
Threaded vs Evented Servers
2010-11-16 22:48 956Threaded vs Evented Servers ... -
BASE: An Acid Alternative
2010-11-16 21:13 983In partitioned databases, tra ... -
eBay 的Scalability最佳实践
2010-11-16 20:52 931用什么来衡量一天没 ... -
Scalability Best Practices: Lessons from eBay
2010-11-16 20:45 874At eBay, one of the primary a ... -
SmugMug 的架构介绍
2010-11-16 20:36 899本文介绍的 SmugMug 是一家提供付费图片 ... -
来自淘宝的架构经验
2010-11-16 18:07 1248日前参加了一场淘宝网 架构师黄裳带来的技术分享,在最后他 ... -
可伸缩性最佳实战
2010-11-16 17:50 607异步 同步调用使得组件和组件之间紧密耦合起来,这样就使得 ... -
伸缩性和可用性反模式
2010-11-16 17:48 740这篇文章讲了伸缩性 和可用性方面的反模式,也按照自己的理 ... -
使用qi4j实现DCI架构
2010-11-16 17:24 2933我曾经DCI架构是什么? 在一文中提到Qi4j框架实现DCI ... -
DCI架构是什么?
2010-11-16 17:07 2050DCI是数据Data 场景Context 交互Interact ... -
纵向扩容 vs. 横向扩容
2010-11-02 09:58 5441该文原版著作权属于Malc ... -
云计算在电信应用中的思考
2010-11-01 17:59 972云计算是在网格(Grid)、效用(Utility)和 ... -
真正的线性可伸缩性需要新的模式和中间件架构吗?
2010-11-01 17:27 978在构建线性可收缩应用 ... -
性能与可伸缩性的概念及其关键影响因素
2010-11-01 17:22 1158性能与可伸缩性常常决定企业应用的成败,尤其在 ... -
构建的可伸缩性和达到的性能
2010-11-01 17:19 1009实现伸缩性和性能调优的经验所保有的价值容易被低估。两者都是“晚 ... -
可伸缩性的最差实践
2010-11-01 17:02 796引言 在扩展大量大型 ... -
可伸缩性,美妙的可伸缩性
2010-11-01 16:37 1439可伸缩性带来的好处 ... -
大型门户网站架构设计的可伸缩性
2010-11-01 16:34 911我们知道,对于一个大型门户网站来说,可伸缩性是非常重要的,怎么 ... -
可伸缩性设计
2010-11-01 16:27 1012好的设计是实现高度可 ...
相关推荐
标题《Segment-Based Recovery: Write-ahead logging revisited》表明本文是对传统写前日志(Write-Ahead Logging,WAL)技术的重新审视,尤其是针对分段恢复(Segment-Based Recovery)的应用。WAL是一种确保数据库...
Starting and stopping cache flushing levels是Write-back方式下生效的两个设置,它们影响控制器如何处理未写入磁盘的缓存内数据。缓存内数据写入磁盘称为flushing。可以配置Starting and stopping cache flushing ...
我的keil5是MDK524版本,在使用JLink调试时出现JLink Warning:mis-aligned memory write:address:0x20000000,numbytes:2,alignment:2(halfword-aligned)的警告。找到c:\Keil_v5\ARM\segger(Keil安装目录)下的JL2...
Write-through 模式处理流程: 1. 数据更新 2. 同时写入缓存 Cache 和后端存储 3. 数据写入完毕 Write-back 模式处理流程: 1. 数据更新 2. 只写入缓存 Cache 3. 缓存中的数据被替换出缓存时,被修改的缓存数据才...
3. **错误处理**:如果在写入或重命名过程中发生错误,`fs-write-stream-atomic`会清理临时文件,避免留下无用的数据。 4. **兼容性**:这个库旨在与Node.js的`fs.createWriteStream`接口保持一致,因此开发者可以...
Write-Color是Write-Host的包装,使您可以创建带有彩色输出的漂亮脚本。 变更日志 0.87.3-2021.04.12 :light_bulb: 禁用文件外出功能的WhatIf功能,这将阻止记录到文件 :light_bulb: 添加了LogRetry (2)以提供...
新版MDK-RAM_v5.25.2使用JLink下载调试““**JLink Warning: Mis-aligned memory read: Address: ......”错误解决
### 错误解析:Caused by: android.system.ErrnoException: write failed: ENOSPC (No space left 在Android开发过程中,可能会遇到“Caused by: android.system.ErrnoException: write failed: ENOSPC (No space ...
CSS3中的`:read-write`和`:read-only`选择器是两个非常重要的伪类选择器,它们主要用于处理用户可编辑和不可编辑元素的样式。这两个选择器对于创建动态和交互式的网页设计至关重要,尤其是在处理表单元素如`input`和...
####EhCache Spring 如何##Recipe 15(Spring 缓存抽象) 在这个秘籍中,您将看到如何在 Spring 3.1 及更高版本的最新缓存抽象 API 中使用内置的 EhCache 支持。 我们将使用基于注释的方法,但将遵循传统的 EhCache...
本文将深入探讨Coherence提供的四种数据管理模式:Read-Through、Write-Through、Refresh-Ahead以及Write-Behind,并分析它们的特点及适用场景。 #### 二、Coherence简介 Coherence是Oracle公司推出的一款面向企业...
4. **错误处理**:`csv-write-stream` 提供了错误处理机制,当数据处理过程中出现错误时,可以捕获并处理这些异常。 5. **集成其他库**:这个库可以很好地与其他Node.js库结合使用,例如与`readable-stream` 或 `...
- **Write Behind Caching**:更新数据时,仅更新缓存,定时异步地将缓存中的修改同步到数据库。 4. **版本号机制**: - 在缓存中为每个数据项增加一个版本号字段,每次更新数据时都更新版本号。读取数据时,先...
2. **写分配(write allocate)**:写操作会分配新的缓存块,与write back搭配,更新缓存并设置脏位。 **实验中的实现**: 本实验实现的是一级Cache,采用Two-way Associated结构,使用LRU替换算法,并结合write back...
"Write-around"缓存策略是一种设计模式,它在主存储器无法满足高速访问需求时,允许数据绕过主存储器直接写入更快的存储层,从而提高数据存取速度。 **缓存系统在Web开发中的作用** 在Web开发中,缓存是提升应用...
** PURPOSE This class can read, write and watch one serial port. ** It sends messages to its owner when something happends on the port ** The class creates a thread for reading and ...
1980年代,微处理器还没有内置缓存,但到1995年,二级缓存已成为微处理器的标准配置。随着处理器性能每年以55%的速度增长,而DRAM(动态随机存取内存)的提升速度仅为7%,两者之间的性能差距以50%的年增长率扩大,这...
- **SQL查询**:学习如何编写基本的SQL查询语句以及更复杂的事务处理。 - **安全性**:讨论如何避免SQL注入攻击和其他常见的安全问题。 ##### 3. API (Application Programming Interfaces) 随着互联网的发展,API...
### 写前日志(Write-ahead Logging)技术详解 #### 一、引言与目标 **写前日志**(Write-ahead Logging, WAL)是一种广泛应用于数据库系统中的技术,旨在提高系统的高可用性、数据一致性和故障恢复能力。通过在修改...
\n\n缓存的工作机制包括写策略(Write Policy)和替换策略(Replacement Policy)。写策略决定如何处理缓存与主存的数据一致性,如写直达、写回、写一次等。替换策略则决定了当缓存满时,如何选择要替换的块,如LRU...