Zookeeper + Guava loading cache 实现分布式缓存
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 实现分布式缓存的更多相关文章
- 基于redis分布式缓存实现
Redis的复制功能是完全建立在之前我们讨论过的基 于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你 的 ...
- 分布式缓存重建并发冲突和zookeeper分布式锁解决方案
如果缓存服务在本地的ehcache中都读取不到数据. 这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中 分布 ...
- 本地缓存google.guava及分布式缓存redis 随笔
近期项目用到了缓存,我选用的是主流的google.guava作本地缓存,redis作分布式 缓存,先说说我对本地缓存和分布式缓存的理解吧,可能不太成熟的地方,大家指出,一起 学习.本地缓存的特点是速度 ...
- 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
- 分布式缓存HttpRuntime.cache应用到单点登陆中_优化登陆
以前的设计方案,是我们在数据库中放一个表,用作存储验证登陆成功的用户,并且生成用户TOKEN(令牌) 分布式缓存+集群的解决方案图: 相应的代码: DE层中配置文件: receiveTimeout=& ...
- Distributed Cache(分布式缓存)-SqlServer
分布式缓存是由多个应用服务器共享的缓存,通常作为外部服务存储在单个应用服务器上,常用的有SqlServer,Redis,NCache. 分布式缓存可以提高ASP.NET Core应用程序的性能和可伸缩 ...
- Flink分布式缓存Distributed Cache
1 分布式缓存 Flink提供了一个分布式缓存,类似于hadoop,可以使用户在并行函数中很方便的读取本地文件,并把它放在taskmanager节点中,防止task重复拉取. 此缓存的工作机制如下:程 ...
- 用guava快速打造两级缓存能力
首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度! 现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了! 而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 ...
- Guava的两种本地缓存策略
Guava的两种缓存策略 缓存在很多场景下都需要使用,如果电商网站的商品类别的查询,订单查询,用户基本信息的查询等等,针对这种读多写少的业务,都可以考虑使用到缓存.在一般的缓存系统中,除了分布式缓存, ...
随机推荐
- python-------打印与字符串格式化
print python中每次执行print时都会在新的一行上开始.形如:print(’xiao') print('ming') 结果为:>>>xiao >>>mi ...
- python --爬虫基础 --爬猫眼top 100 使用 requests 库的基本操作
import requests import re import json import time def get_page(url): # 获取页数 headers = { 'User-Agent' ...
- 高斯分布(Gaussian Distribution)的概率密度函数(probability density function)
高斯分布(Gaussian Distribution)的概率密度函数(probability density function) 对应于numpy中: numpy.random.normal(loc= ...
- jmeter之beanshell断言---数据处理
在做接口测试时,对响应数据的校验是非常重要的部分:在使用Jmeter进行接口测试时,有多种respone校验方式,比如响应断言.BeanShell断言等等,BeanShell断言可以自定义断言,自由灵 ...
- #PHP# 华为云 API 方式发送短信
使用给华为云 消息 服务 API 方式发送短信 代码来自华为云,已通过测试 <?php /** * 华为云发送短信示例代码 * 本段代码需要使用自己的配置信息才能正常运行,出配置信息外,不需要改 ...
- 蓝桥杯-正则问题(dfs,解决()的计算)
历届试题 正则问题 时间限制:1.0s 内存限制:256.0MB 问题描述 考虑一种简单的正则表达式: 只由 x ( ) | 组成的正则表达式. 小明想求出这个正则表达式能接受的最长 ...
- shell (三) 文件压缩
查看压缩文件 #tar tvf tar.tar.gz -rw-r--r-- root/root 290 2019-03-22 14:38 README.md -rw-r--r-- root/root ...
- 内核诊断(二)-- patch 和diff
patch文件结构 生成patch文件 --diff命令 patch 使用 -- patch命令 3.1 打path 3.1撤销patch 使用举例 4.1 基本命令使用 4.2 内核打补丁 1. p ...
- [Xamarin] 開啟另外一個Activity 並且帶資料 (转帖)
每隻App是透過許多畫面所組成的,當然可能主畫面之外,都會有許多其他的頁面 再Android 設計中畫面會有配合的Activity 當然在這之前,最好事先了解一下,Android 關於生命週期的規劃 ...
- sysv-rc-conf介绍
sysv-rc-conf简介 sysv-rc-conf是一个强大的服务管理程序,Ubuntu运行级别Linux 系统任何时候都运行在一个指定的运行级上,不同的运行级的程序和服务都不同,所要完成的工作和 ...