Terracotta 分布式缓存机制深入

article/2025/11/8 7:25:02
Terracotta已收购Ehcache 

数据缓存:(无缝集成,代码注入方式,不需修改原代码)
     Terracotta 功能(JVM级POJO集群):DSO(jvm本地线程加锁外,JVM集群上加排它锁)
1) 堆级的复制:集群时需要拷贝的对象在堆之间进行(跨节点session复制)
2) 超大的虚拟堆:由于是JVM层次的集群,所以堆要比单个JVM大很多
3) 多种集群锁语法:distributed wait/notify and synchronized
4) 运行实时监控
5) 无需序列化实现集群
6) Find-Grained Changes:由于集群时,terracotta不要求序列化,所以对象拷贝可以细化到对象中的每一个字段,就是说在进行复制的时候,当对象发生变化的时候,
不需要整个对象进行拷贝,只需要拷贝发生变化的那个field。
如:HTTP Session复制,分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式,所以你不需要修改任何)
Terracotta 优势
 1 大部分web服务器使用java序列化和数据广播方式,消耗大量CPU和内存资源,当节点超过4个集群吞吐量线性下降。session数据库共享带来数据库压力。Terrocotta避免序列化和广播机制,只把被修改的字段的数据传递给服务器和使用节点,大大减少CPU和内存消耗。
 2  利用服务器实现网络扩展内存,线性扩展内存。
 3  数据保存在服务器端,因此客户端JVM宕机不会造成数据丢失。
 4  增量数据传递,智能数据推送,最大限度减少对网络的负担,使得客户端JVM可以横向扩展
 5 服务器实现共享数据持久化,通过服务器集群实现容错等
 6 广泛支持各种应用服务器,插件集成
 7 无需学习API,降低开发成本
 8  服务器分片,实现服务器数据存储及数据吞吐量横向扩展
注入与字节码机制:
普通的应用程序是怎么获得这种分布式的集群行为呢?当应用程序类在被JVM加载的时候,它们通过字节码增强技术被偷偷注入了分布式集群行为(通过配置文件配置后获得)。这种字节码增强注入技术其实很常用,在很多AOP框架中都得以采用,比如AspectJ和AspectWerkz。类的字节码在加载的时候由Terracotta库进行解析和检查。然后这些字节码会被传递到JVM重新构造成一个类,在此之前这些字节码会根据配置被修改。
为了维护对象的修改,PUTFIELD和GETFIELD字节指令被进行了重载。PUTFIELD指令被替换了,能够存储对一个分布式对象的各个域的修改。GETFILED字节指令重载后能够在需要的时候从服务器获取对象的域数据,但这么做的前提是此时它还没有从服务器的查询中获取到被这个域所引用的对象,此时该域引用的对象还没有在JVM堆中被实例化。也就是说GETFIELD是一个lazy initialize模式,如果域为空才会加载域数据,否则不会加载。
为了管理线程之间的协调,MONITORENTER和MONITOREXIT字节码指令也被重载了,INVOKEVIRTUAL指令也会被重载,这些指令会被各种各样的object.wait()和objecti.notify()方法用到。MONITORENTER意味着某一个线程对某一个对象monitor的请求。一个线程会阻塞在这条指令上,直到它获得了对该对象的锁。一旦获得了锁,那么线程就会持有该对象的排他锁,直至针对该对象的MONITOREXIT指令被执行。如果在MONITORENTER请求查询monitor的时候这个对象碰巧是一个集群对象-DSO,Terracotta会保证:除了请求这个对象在本地JVM里的本地锁之外,线程还会在这个DSO对象上的整个JVM集群上的排他锁,在此之前,该线程会一直阻塞。当线程释放本地JVM上对该DSO对象的本地锁的时候,他也会释放相应的整个JVM集群上的锁
      Terracotta的应用程序中,所有的synchronized方法和synchronized块往往会被被配置成“autolocking”(我们可以看到在测试的例子中运用到了synchronized,配置文件中对其进行”autolocking”配置
       
       

这就意味着MONITORENTERMONITOREXIT方法被进行了字节码增强处理。当然有些开发人员可能不太愿意用显式的synchronized关键字,那么可以在Terracotta配置文件中声明一个方法为一个locked方法,从而使得应用程序获得集群同步特性(如上图配置)。

对象wait()和notify()方法相应的字节码指令也会被进行字节码增强。当某一个共享对象的wait()方法被调用时,terracotta服务器会把调用这个wait()方法的线程加入到一个线程队列中去,这个线程队列记录了整个JVM集群中所有等待该对象锁的所有线程。当这个对象的notify方法被调用时,服务器会确保整个集群中所有阻塞在该对象上的线程会被通知到。一旦该对象的notify在一个JVM中被调用时,terracotta服务器会选择一个阻塞在该对象上的线程,然后唤醒通知它。当notifyAll被调用时,terracotta服务器会让所有JVM中等待在该DSO上的所有线程都被唤醒。(terracotta服务器管理阻塞线程队列)




Terracotta 使用:
terracotta运用了bytecode instrumentation的技术,所以我们现有的项目基本上不需要做任何修改。Terracotta提供一个配置文件tc-config.xml,我们只需要在这个配
置文件里配置一些必须参数就可以实现集群。

Terracotta实现:
Terracotta Server最重要的一个功能就是DSO(Distributed Shared Object),通过DSO我们可以把那些被频繁访问的,重要的数据(在Terracotta的文档中称之为ScratchData)缓存到TC Server上,然后供集群里的不同JVM共享,这样一来就减轻了数据库的负载。

Terracotta就可以通过增强的代码截获对这些共享数据的读写请求,并且与Terracotta服务器协作,实现共享数据在集群中的一致性(集群范围内共享锁)。对于Java代码中使用的也是利用相同的机制实现全局协同;Terracotta服务器则首先记录所有节点对共享数据和锁的访问信息,为读取数据的节点提供最新数据,把修改的数据通知给正在使用中这些数据的节点等等。服务器除了协调节点间数据的获取和变化通知以外,还利用其本地内存和硬盘实现共享数据的缓存和持久化。

Terracotta驱动器和服务器:
    有时我们也称Terracotta驱动器为一级缓存L1,服务器为二级缓存L2
Terracotta
这一体系架构跟其它集群解决方案相比,有如下几点好处:
1
、避免Java序列化,只把被修改的字段的数据传递给服务器和使用节点,大大减少CPU和内存消耗;
2
、避免数据的广播,只把修改的数据通知给正在使用该数据的节点,大大降低了网络流量;
3
、利用服务器实现网络扩展内存,使得有限内存的客户端节点可以访问远大于其内存容量的数据结构,而不必担心发生内存逸出的异常;
4
、通过服务器实现共享数据持久化,通过服务器集群实现容错性等等
5
、无须学习新的API,大大降低开发成本

Terracotta插件(http://forge.terracotta.org/releases/projects.html)

  1.      Tomcat session复制、
  2.      Spring Security整合、
  3.      与Hibernate的整合、
  4.      异步数据库持久化
Terracotta 架构:

Terracotta采用的是一种被称之为中心辐射的架构。在这种架构里运行着分布式应用程序的JVM们在启动时都会与一台中心Terracotta服务器相连。Terracotta服务器负责存储DSO对象数据,协调JVM之间的并发线程。Terracotta库位于应用程序JVM中,在类加载过程中,它们用来对类的字节码进行增强,处理同步块内的lock和unlock请求,处理应用JVM之间的wait(),notify()请求,处理运行时和Terracotta服务器的联系等等。

ROOT、集群对象图

集群对象从一个共享对象图中的根开始,这个root可以通过Terracotta配置文件中的一个或多个域进行配置的,当一个root被首先实例化时,这个root对象和这个root所能到达的所有的对象就变成了集群对象:

他们的各个域的数据会被传递到服务器上由服务器来存储,在任何JVM中一旦一个root对象被创建,那么该root对象创建时所对应的那个域就会忽略本地堆对象的分配,取而代之的是分配一个服务器集群对象。这种情况往往发生在第二个应用程序实例创建root对象的时刻,由于root对象已经由第一个应用程序实例化创建了,那么其他应用程序中的,尽管这些root域按照代码的要求是要通过构造函数来生成对象的,但这些指令都被忽略了,取而代之的是,Terracotta客户端库会从服务器获取root对象,然后在本地堆中实例化它,然后把这个引用赋给相应的域,这些工作都是透明得进行的,被terracotta的库隐藏了。terracotta的工作机制给我们的应用程序带来的最主要也是最有价值的地方也就在于此。一旦某一个对象变成集群对象了,那么他就会被分配一个整个集群范围内唯一的object id,并且在剩下的生命周期内一直保持集群特性。一旦某一个集群对象突然变成了任何root对象都不可达的状态,并且在整个集群JVM中都没有它的任何实例,那么这个集群对象会被terracotta的服务器GC进行回收。

 

细粒度的更改复制

包含DSO对象变化的transaction只包含那些已经发生变化的域的数据。这些transaction会被发送到Terracotta服务器和其他集群JVM上从而保持集群一致性。服务器不是广播式的将transaction发送到所有其它的JVM上,这些transaction只会被发送到特定的JVM上,这些JVM包含transaction代表的对象,并且这些对象在这些JVM的堆上进行了实例化。也就是说,terracotta服务器只发送其它JVM必须使用到的transaction的一部分。比如:一个线程改变了对象a中的域p和对象b中的域q,那么只有a.p和b.q的域数据会被放到transaction中并被发送到服务器。更改某个DSO的多个相关的域在terracotta中一定是原子的,一定是要用synchronized关键字进行同步的,根据前面的定义,那么更改DSO的这些域也就是transaction,被发送到服务器上。(只更改某个DSO的单个域本身就是原子的,不需要用synchronized进行显式同步,也就是说某个DSO单个域的修改本身就是一个transaction)。Terracotta服务器会决定哪些JVM含有a和b的实例。如果一个JVM的本地堆只含有对象a的实例而并没有对象b的实例,那么这个JVM只会收到a.p的数据,而不会收到b.q的数据

对象的标识和序列化

由于对象的变化的历史记录只是局限在对象的域层次并且transaction只包含的是DSO的片段而不是整个对象图,因此terracotta不会使用Java序列化来复制传播对象的变化。举个例子,我们更改一个product对象的price域,那么我们需要发送到集群上就是发生变化的对象的ID,对象发生变化的域的ID,和包含price域数据的字节。Product对象的其余部分就被忽略了。如果我们采用object序列化技术,那么product对象的每个域都需要被序列化,而各个域又会引用到其它对象,这样最后的结果是仅仅是对product对象的一个double域的修改就会导致整个对象图都会被序列化,Terracotta目前采用的做法相比java序列化而言更加高效,因为它只发送了发生改变的对象而不是整个对象图。但是,除了效率,利用对象域作为改变的基本单位还有另外的好处:保持对象的唯一性,如果采用java序列化来在集群间转移对象的变化,那么JVM集群的客户端应用程序需要对发生改变的对象进行反序列化并且不得不替换已有的对象实例。这就是为什么许多其他的集群和分布式技术会要求提供PUT/GET API,因为一个集群对象从集群中被获取出来一定需要一个GET调用,当对象发生变化时,它一定需要一个PUT调用把发生改变的对象放回集群上去,Terracotta没有这样的限制。一个集群对象也像普通对象一样在JVM堆中生存着。当对象是被JVM本地进行修改的,那么这些修改直接作用在JVM的堆上。如果这些修改是通过远程的在另外一个JVM上的这个DSO对象的引用进行的,那么本地的JVM就会收到这个transaction并且直接将transaction作用在已在本地堆中存在的对象上。这意味着针对某个DSO,在任何给定的时刻一个JVM在堆中只可能拥有一个对它的实例引用。

有了terracotta你不必考虑每个JVM实际上存放的是一个对象的copy,也不必考虑当本地进行完修改时再把对象的copy放回集群中去。由于没有对象拷贝的概念,一个集群对象就是一个在集群堆中的普通对象,行为也和普通对象没有什么区别,任何对集群对象的修改对任何拥有该集群对象引用的对象也是有效的。由于保留了对象的唯一性,这使得集群的,多JVM的应用在行为表现上和普通的,单JVM的应用没有什么区别。在集群中保持对象唯一性带来的简洁和强大使得分布式特性从应用程序的设计和实施中剥离出来。分布式行为被推给了terracotta服务器,已经融入了基础架构。就像JavaGC使得内存管理的代码从应用层代码中完全消失了,terracotta使得分布式计算行为也从应用代码中消失。

虚拟堆/网络内存 

除了在多个JVM之间分享和同步对象,Terracotta也能够针对非常大的对象图有效得使用本地堆。随着共享对象图不断增大,可能它已经不能够放在单个JVM的堆中了,Terracotta会保持一个对分布式对象图的配置窗口,这样当分布式对象对堆的使用超过一定阈值后就会按照一定的策略被flush out出去。当这些被flush out的对象片段又被使用时,再从terracotta服务器中取出来放到JVM的堆中。你可以把terracotta服务器看成一个无限大的虚拟堆或者网络内存,由于terracotta可以看成一个巨大的可以无限扩展的网络内存,你可以装进整个对象,使之成为一个分布式的对象图,而不必关心它的大小,对象只需要装载一次,这大大减小了应用程序实例的启动的时间。


附上分布式代码锁:

    public class TerracottaLockTool implements LockTool{

       private ClusteringToolkit toolkit;

       public TerracottaLockTool(String tcServer){

           TerracottaClient client = new TerracottaClient(tcServer);//构造客户端连接TcServer

           toolkit = client.getToolkit();//同过客户端TerracottaClient获取toolkit

       }

       @Override

       public Lock getWriteLock(String lockKey) {

           ReadWriteLock lock = toolkit.getReadWriteLock(lockKey);//通过toolkit获取写锁

           Lock lock2 = lock.writeLock();

           return lock2;

       }

       @Override

       public Lock getReadLock(String lockKey) {

           ReadWriteLock lock = toolkit.getReadWriteLock(lockKey);//通过toolkit获取读锁

           Lock lock2 = lock.readLock();

           return lock2;

       }

    }





http://chatgpt.dhexx.cn/article/8IVQKyme.shtml

相关文章

分布式缓存之Ehcache与terracotta - Terracotta服务器概念篇

1、介绍 Terracotta服务器为Terracotta产品提供分布式数据平台。Terracotta服务器集群被称为Terracotta服务器阵列(TSA)。Terracotta服务器阵列可以从单个服务器,到一个用于高可用性(HA)的基本的双服务器串联,再到一个提供可配置的规模、高性能和深度故障…

IOCP与ASIO关系

笔记 IOCP:Input/Output Completion Port,Windows独有的内核对象,内核级完成IO的传输 ,数据到来的时候自动把数据搬运到用户态的内存区,不需要拷贝文件描述符FileDescription(fd)到内核态查询状…

IOCP工作原理

文章来源:http://blog.csdn.net/zhongguoren666/article/details/7386592 本文主要探讨一下windows平台上的完成端口开发及其与之相关的几个重要的技术概念,这些概念都是与基于IOCP的开发密切相关的,对开发人员来讲,又不得不给予足…

Windows IOCP

Windows IOCP IOCP全称I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的Windows API,它可以高效地将I/O事件通知给应用程序,类似于Linux中的Epoll。 简介 IOCP模型属于一种通讯模型,适用于Windows平台下高负载服务器…

IOCP小结

文章目录 一 什么是完成端口(completion port)对象二 使用IOCP的方法创建完成端口对象I/O服务线程和完成端口完成端口和重叠I/O 三 恰当地关闭IOCP四 IOCP大概的处理流程五 一个简单示例具体编程流程 当应用程序必须一次管理多个套接字时,完成…

IOCP高性能服务器的实现

应用场景说明:完成端口在面向现实应用的许多网络通信中应用很广泛,例如大型多人在线游戏,大型即时通信系统,网吧管理系统以及企业管理系统等具有大量并发用户请求的场合。 实现目标说明:通过完成端口模型构建一款服务…

IOCP 详解

IOCP 详解 网络上关于epoll的介绍资料多如牛毛,大多数已经讲解的非常细致。相比而言epoll只有三个接口调用,IOCP却有一堆的接口调用,更关键的是Windows的闭源性质,我们不知道调用之后Windows究竟做了哪些操作。众所周知IOCP是基于…

IOCP简介

1.1 环境要求本文读者需要熟悉C、TCP/IP、Socket编程、MFC,和多线程。源码使用Winsock 2.0和IOCP技术,要求:Windows NT/2000或以上:要求Windows NT3.5或以后版本Windows 95/98/ME:不支持Visual C.NET,或完整…

什么是IOCP

百度词条 输入输出完成端口(Input/Output Completion Port,IOCP), 是支持多个同时发生的异步I/O操作的应用程序编程接口 一个IOCP对象,在操作系统中可关联着多个Socket和(或)文件控制端。 IOCP对象内部有一…

IOCP

载自:http://blog.csdn.net/markman101/article/details/6235516 本文主要探讨一下windows平台上的完成端口开发及其与之相关的几个重要的技术概念,这些概念都是与基于IOCP的开发密切相关的,对开发人员来讲,又不得不给予足够重视的…

IOCP模型与网络编程

IOCP模型与网络编程 一。前言: 在老师分配任务(“尝试利用IOCP模型写出服务端和客户端的代码”)给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装…

Windows下的IOCP模型(一):介绍与简单使用

一、IOCP简介 IOCP(I/O Completion Port,I/O完成端口)是Windows操作系统中伸缩性最好的一种I/O模型。I/O 完成端口是应用程序使用线程池处理异步 I/O 请求的一种机制。处理多个并发异步I/O请求时,使用 I/O 完成端口比在 I/O 请求时…

完成端口(IOCP)编程探讨

FW: http://www.zhuaxia.com/item/473350387 完成端口(IOCP)编程探讨 2007-08-26 16:06:00 来自:C博客-首页原创精华区 新建目录...根目录新手试用频道 本文主要探讨一下windows平台上的完成端口开发及其与之相关的几个重要的技术概念,这些概念都是与…

异步通信之IOCP详解

一、 概述 学习完网络基础,在写C/S应用程序时,大多童靴写服务器基本都没有用到io模型,基本都是采用“accept同步拥塞通讯和多线程方式”与客户端通讯。但当有成千上万客户端请求连接并与服务器通讯时,多线程的创建与CPU上下文的切…

IOCP详解

IOCP详解 IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求。这样就有很多…

IOCP技术详解

这几周我接触了Windows网络通讯中的IOCP模型,自己在网上找了相关的知识进行学习,自己又下了好多服务器端的代码,但都运行不了,也是自己菜,能力还需加强。幸好我师父资助了我一个能运行的服务端IOCP代码,自己参照网上的…

Python正则表达式模式

在 Python 程序中,模式字符串使用如下特殊的语法来表示一个正则表达式: 字母和数字表示它们自身,一个正则表达式模式中的字母和数字匹配同样的字符串;当大多数字母和数字前加一个反斜杠时,它们会拥有不同的含义&#…

Python正则表达式实例详解

一、正则表达式语法 正则表达式是用匹配或者描述字符串的工具。 用处: a.判断字符串是否满足某个条件—判断输入的字符串是否是邮箱/手机号码。是否是ip地址 b.提取满足条件的字符串 c.字符串替换 Python中通过re模块中相应的方法来支持正则表达式的匹配、查找和替…

Python正则表达式语法快速入门

文章目录 1 正则符号初阶代码举例1:不同符号的组合代码举例2:符号加,代表连续的一个或多个代码举例3:匹配字符串开始代码举例4:匹配字符串结束代码举例5:匹配单词边界 2 正则符号进阶代码举例1:…

python正则表达式入门

🙊今天我们来学习python的正则表达式的部分,先说下为什么要学习这一部分呢,当然是因为正则表达式处理文本类型的数据实在是太方便了。为以后进入nlp领域打打基础! 先给大家推荐一个网站: 用于正则表达式验证. 大致就长这个样子。…