1. 概述

项目中,创建的活动内容存入redis,然后需要用到活动内容的地方,从redis去取,然后参与计算。

活动数据的一个特点是更新不频繁、数据量不大。因为项目部署一般是多机器、多实例,除了redis,有没有其他实现呢?

Guava的 loading cache是本地缓存,数据量不是很大时 可以适用(如果有大量的key-value数据缓存本地,本机也吃不消啊),

然后多机器多实例怎么同步呢?想到了zookeeper....

2. 代码

2.1 模拟多实例

package TestZK;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry; /**
* @Author: rocky
* @Date: Created in 2018/5/20.
*/
public class InstanceOne {
private static final String ADDRESS = "xxx:2181";
private static final String PATH = "/strategy";
private static CuratorFramework client;
static {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.builder()
.connectString(ADDRESS)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
// .namespace(BASE)
.build();
client.start();
} public static void main(String[] args) throws Exception {
startCache();
Thread.sleep(Integer.MAX_VALUE);
} private static void startCache() throws Exception {
PathChildrenCache childrenCache = new PathChildrenCache(client, PATH, true);
childrenCache.start();
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
System.out.println("catch that: the path of changed node "+ event.getData().getPath()
+ ", the data of changed node is " + new String(event.getData().getData()));
//load data to loading cache(guava)
doSomething();
}
});
}
//load data to loading cache
private static void doSomething() {
// LoadingCache<String, Map<Integer, DriverIntegral>> driverIntegralCache = CacheBuilder.newBuilder().maximumSize(500)
// .expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader<String, Map<Integer, DriverIntegral>>() {
// @Override
// public Map<Integer, DriverIntegral> load(String key) throws Exception {
// Map<Integer, DriverIntegral> integerDriverIntegralMap = ..;
// logger.info("guava load ::driverIntegralMap"+integerDriverIntegralMap!=null?integerDriverIntegralMap.toString():"");
// return integerDriverIntegralMap;
// }
// });
//
// Map<Integer, DriverIntegral> driverIntegralMap = driverIntegralCache.get(INTEGRAL);
}
} package TestZK; import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry; /**
* @Author: rocky
* @Date: Created in 2018/5/20.
*/
public class InstanceTwo {
private static final String ADDRESS = "xxx:2181";
private static final String PATH = "/strategy";
private static CuratorFramework client;
static {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.builder()
.connectString(ADDRESS)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
// .namespace(BASE)
.build();
client.start();
} public static void main(String[] args) throws Exception {
startCache();
Thread.sleep(Integer.MAX_VALUE);
} private static void startCache() throws Exception {
PathChildrenCache childrenCache = new PathChildrenCache(client, PATH, true);
childrenCache.start();
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
System.out.println("catch that: the path of changed node "+ event.getData().getPath()
+ ", the data of changed node is " + new String(event.getData().getData()));
}
});
}
} package TestZK; import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry; /**
* @Author: rocky
* @Date: Created in 2018/5/20.
*/
public class InstanceThree {
private static final String ADDRESS = "xxx:2181";
private static final String PATH = "/strategy";
private static CuratorFramework client;
static {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.builder()
.connectString(ADDRESS)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
// .namespace(BASE)
.build();
client.start();
} public static void main(String[] args) throws Exception {
startCache();
Thread.sleep(Integer.MAX_VALUE);
} private static void startCache() throws Exception {
PathChildrenCache childrenCache = new PathChildrenCache(client, PATH, true);
childrenCache.start();
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
System.out.println("catch that: the path of changed node is "+ event.getData().getPath()
+ ", the data of changed node is " + new String(event.getData().getData()));
}
});
}
}

监听zk孩子节点,有变化时(创建、更新、删除),重新从DB加载活动数据,缓存到loading cache,用到活动数据的地方,从cache中取。

2.2 模拟客户端

package TestZK;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry; /**
* @Author: rocky
* @Date: Created in 2018/5/20.
*/
public class NodeChangeTest {
private static final String ADDRESS = "xxx:2181";
private static final String PATH = "/strategy";
private static CuratorFramework client;
static {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.builder()
.connectString(ADDRESS)
.sessionTimeoutMs(5000)
.connectionTimeoutMs(5000)
.retryPolicy(retryPolicy)
// .namespace(BASE)
.build();
client.start();
} public static void main(String[] args) throws Exception {
String path_node_1 = PATH + "/node_1";
//create
client.create().creatingParentsIfNeeded().forPath(path_node_1);
Thread.sleep(2000);
//change
client.setData().forPath(path_node_1, "yahahaha".getBytes());
Thread.sleep(2000);
//delete
client.delete().forPath(path_node_1);
Thread.sleep(Integer.MAX_VALUE);
}
}

客户端实际上可能是某个后台,在后台创建、修改、或删除某活动,然后对应操作zookeeper节点,其他监听到节点变化的地方,做相应操作(如查询DB并缓存数据)

控制台

3. 说明

Zookeeper原生的API只能实现一次监听,这里用到的Curator的封装jar包,免去了手动重复注册。另外Curator的NodeCache和TreeCache分别监听本节点及分支所有节点,

该实例演示的PathChildrenCache只能监控一级子节点(即儿子节点、孙子节点也不能监控),根据需要选择相应NodeCache.

很low的实现,请多指教^_^

Zookeeper Curator API 使用 www.cnblogs.com/rocky-fang/p/9037509.html

Zookeeper JAVA API的使用 http://www.cnblogs.com/rocky-fang/p/9030438.html

Zookeeper + Guava loading cache 实现分布式缓存的更多相关文章

  1. 基于redis分布式缓存实现

    Redis的复制功能是完全建立在之前我们讨论过的基 于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你 的 ...

  2. 分布式缓存重建并发冲突和zookeeper分布式锁解决方案

    如果缓存服务在本地的ehcache中都读取不到数据. 这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中 分布 ...

  3. 本地缓存google.guava及分布式缓存redis 随笔

    近期项目用到了缓存,我选用的是主流的google.guava作本地缓存,redis作分布式 缓存,先说说我对本地缓存和分布式缓存的理解吧,可能不太成熟的地方,大家指出,一起 学习.本地缓存的特点是速度 ...

  4. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

  5. 分布式缓存HttpRuntime.cache应用到单点登陆中_优化登陆

    以前的设计方案,是我们在数据库中放一个表,用作存储验证登陆成功的用户,并且生成用户TOKEN(令牌) 分布式缓存+集群的解决方案图: 相应的代码: DE层中配置文件: receiveTimeout=& ...

  6. Distributed Cache(分布式缓存)-SqlServer

    分布式缓存是由多个应用服务器共享的缓存,通常作为外部服务存储在单个应用服务器上,常用的有SqlServer,Redis,NCache. 分布式缓存可以提高ASP.NET Core应用程序的性能和可伸缩 ...

  7. Flink分布式缓存Distributed Cache

    1 分布式缓存 Flink提供了一个分布式缓存,类似于hadoop,可以使用户在并行函数中很方便的读取本地文件,并把它放在taskmanager节点中,防止task重复拉取. 此缓存的工作机制如下:程 ...

  8. 用guava快速打造两级缓存能力

    首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度! 现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了! 而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 ...

  9. Guava的两种本地缓存策略

    Guava的两种缓存策略 缓存在很多场景下都需要使用,如果电商网站的商品类别的查询,订单查询,用户基本信息的查询等等,针对这种读多写少的业务,都可以考虑使用到缓存.在一般的缓存系统中,除了分布式缓存, ...

随机推荐

  1. STM32-RS232通信软硬件实现

    OS:Windows 64 Development kit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6/VET6 AD:Altium Designer 18.0.12 1.RS ...

  2. QuantLib 金融计算——数学工具之插值

    目录 QuantLib 金融计算--数学工具之插值 概述 一维插值方法 二维插值方法 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之插值 载入模块 ...

  3. Cisco ISR4400 Netflow 配置模板

    flow exporter NAME destination 145.0.1.200 transport udp 9991 export-protocol netflow-v5 flow monito ...

  4. 牛客OI周赛8-提高组A-用水填坑

    牛客OI周赛8-提高组A-用水填坑 题目 链接: https://ac.nowcoder.com/acm/contest/403/A 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制: ...

  5. JDK下载安装以及环境变量的配置

    JDK是Java Development Kit 的缩写,是 Java 语言的软件开发工具包,主要用于移动设备.嵌入式设备上的java应用程序. 一.JDK的下载 这里以Oracle官网下载为例 1. ...

  6. php array_flip() 删除数组重复元素

    在PHP中,用于删除数组中重复元素有一个可用的函数,那就是 array_unique(), 但是它并不是一个最高效的方法,使用array_flip() 函数将比array_uniqure()在速度上高 ...

  7. linux 下 vi 编辑器 使用

    命令模式(command mode).插入模式(Insert mode)和底行模式(last line mode) 1.进入插入模式 按「i」切换进入插入模式「insert mode」,按“i”进入插 ...

  8. JavaScript设计模式-8.链式调用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 深度学习(十三) R-CNN Fast RCNN

    object detection我的理解,就是在给定的图片中精确找到物体所在位置,并标注出物体的类别.object detection要解决的问题就是物体在哪里,是什么这整个流程的问题.然而,这个问题 ...

  10. iview中使用Tag时进行数据的变化和实现将输入内容转化为标签输出数组

    上代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title ...