用Vert.x使用共享数据
共享数据包含允许,在应用的不同部分,或者在同一个Vert.x实例的不同应用中,或者集群中的不同Vert.x实例中安全共享数据的功能。共享数据包括本地共享映射表,分布的,群集范围的映射表,异步群集范围的锁和异步群集范围的计数器。
重要:分布式数据结构的行为依赖于你使用集群管理器。在面对网络分区时,备分(复制)和行为由集群管理器及其配置进行定义。参考集群文档以及下面的框架文档。
本地共享映射表
本地共享映射表允许在同一个Vert.x实例不同的事件循环中安全共享数据(例如不同的verticle)。本地共享映射仅容许特定的数据类型用作键和值。这些类型必须是不可变的,或者是象Buffer能被复制的特定其他类型,在后一种情况下,在向本地映射中添加时键和值将会被复制。这种方法能确保,在你的Vert.x应用的不同线程间没有对可变状态的共享访问。所以,不用担心通过同步访问保护状态。
这时一个使用共享本地映射的例子:
SharedData sd = vertx.sharedData();
LocalMap<String, String> map1 =sd.getLocalMap("mymap1");
map1.put("foo", "bar"); //Strings are immutable so no need to copy
LocalMap<String, Buffer> map2 =sd.getLocalMap("mymap2");
map2.put("eek",Buffer.buffer().appendInt(123)); // This buffer will be copied before adding tomap
// Then... in another part of your application:
map1 = sd.getLocalMap("mymap1");
String val = map1.get("foo");
map2 = sd.getLocalMap("mymap2");
Buffer buff = map2.get("eek");
群集范围同步映射
群集范围同步映射允许群集里任意节点设置和接收数据。这使得在集群服务器管理的Vert.x应用保存会话状态时真得有用。可以调用getClusterWideMap方法获取AsyncMap实例。获取映射是异步的,这会导致在你指定的处理器得到AsyncMap。这是一个例子:
SharedData sd = vertx.sharedData();
sd.<String,String>getClusterWideMap("mymap", res -> {
if(res.succeeded()) {
AsyncMap<String, String> map = res.result();
} else{
//Something went wrong!
}
});
向映射中设置数据
调用put方法向映射中添加数据。实际的put方法是异步的,一旦完成添加将会通知处理器。
map.put("foo", "bar",resPut -> {
if(resPut.succeeded()) {
//Successfully put the value
} else{
//Something went wrong!
}
});
从映射中获取数据
用get方法从映射中获取数据。
实际的get异步执行,在调用get一些时间后,将会调用处理器并传入获得的数据。
map.get("foo", resGet -> {
if(resGet.succeeded()) {
//Successfully got the value
Object val = resGet.result();
} else{
//Something went wrong!
}
});
其他操作
可以从异步的映射中移除实体,清除映射并获取大小。参见API文档获取更多信息。
群集范围的锁
群集范围的锁允许在整个群集里包含排他锁,这为在任何时间,应用仅需要在群集中的一个节点做些事或访问资源是有用的。群集范围的锁有一个异步API,与其他阻塞调用线程直到获取锁的大部分API不同。
使用getLock获取锁。这不会阻塞,但是一旦获取锁,传入Lock实例的处理器将被调用,预示着现在你获得了锁。在你获得了锁,没有调用者,集群的任何地方能获取这个锁。在用完锁后,调用release方法释放锁。接着另外调用者获得锁。
sd.getLock("mylock", res -> {
if(res.succeeded()) {
//Got the lock!
Locklock = res.result();
// 5seconds later we release the lock so someone else can get it
vertx.setTimer(5000, tid -> lock.release());
} else{
//Something went wrong
}
});
在获取锁时可以设置超时。如果超时时间内获取锁失败,将会调用超时处理器处理失败。
sd.getLockWithTimeout("mylock",10000, res -> {
if(res.succeeded()) {
//Got the lock!
Locklock = res.result();
} else{
//Failed to get lock
}
});
群集范围计数器
跨应用的不同节点维护一个原子的计数据通常很有用。用Counter做这件事,用getCounter方法获取Counter实例:
sd.getCounter("mycounter", res ->{
if(res.succeeded()) {
Counter counter = res.result();
} else{
//Something went wrong!
}
});
一旦有了Counter实例,就可以获取当前计数,用多种方法原子增加或减少,或给其加上一个值。参看API文档获取更多信息。
2019-11-19 20:58:21
共有0条评论!