抛砖引玉,分享一下hanhanfilm中扩展jfinal Redis插件,实现读写分离的代码。兼容jfinal redis 插件。如有错误,请大家多多指正。
配置信息和jfinal默认配置文件在一起,具体如下:
#redis主服务器ip # redis.master.ip=127.0.0.1 #redis主服务器端口号# redis.master.port=6379 #redis主服务器密码# redis.master.password=**** #redis奴隶服务器个数;当个数为0时,代表奴隶为主redis服务器 # redis.slave.count=2 #redis奴隶服务器ip集合 # redis.slave.ip=127.0.0.1,127.0.0.1 #redis奴隶服务器端口号集合# redis.slave.port=16379,26379 #redis奴隶服务器密码# redis.slave.password=****,**** ###jedis连接池配置### #jedis最大保存idel状态对象数 # jedis.pool.maxIdle=200 #jedis调用borrowObject方法时,是否进行有效检查# jedis.pool.testOnBorrow=false
插件代码如下:
package com.jfinal.ext.plugin.redis;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.IKeyNamingPolicy;
import com.jfinal.plugin.redis.serializer.FstSerializer;
import com.jfinal.plugin.redis.serializer.ISerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedisPool;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* https://www.hanhanfilm.com
* Created by badouyuren
*/
public class RedisShardingPlugin implements IPlugin {
private JedisPool masterPool;//非切片连接池
private RedisBean master;
private ShardedJedisPool slavePool;//切片连接池
private RedisBean[] slaves;
private ISerializer serializer = null;
private IKeyNamingPolicy keyNamingPolicy = null;
public boolean start() {
if (serializer == null)
serializer = FstSerializer.me;
if (keyNamingPolicy == null)
keyNamingPolicy = IKeyNamingPolicy.defaultKeyNamingPolicy;
Properties p = PropKit.use("app_config.txt").getProperties();
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(Integer.parseInt(p.getProperty("jedis.pool.maxIdle")));
config.setTestOnBorrow(!p.getProperty("jedis.pool.testOnBorrow").equals("false"));
master = new RedisBean();
master.setIp(p.getProperty("redis.master.ip"));
master.setPort(Integer.parseInt(p.getProperty("redis.master.port")));
master.setPwd(p.getProperty("redis.master.password"));
initialMasterPool(config);
int slaveCount = Integer.parseInt(p.getProperty("redis.slave.count"));
if (slaveCount >= 1) {
slaves = new RedisBean[slaveCount];
String[] slaveIps = p.getProperty("redis.slave.ip").split(",");
String[] slavePorts = p.getProperty("redis.slave.port").split(",");
String[] slavePwds = p.getProperty("redis.slave.password").split(",");
for (int i = 0; i < slaveCount; i++) {
slaves[i] = new RedisBean(slaveIps[i], Integer.parseInt(slavePorts[i]), slavePwds[i]);
}
} else {
slaves = new RedisBean[1];
slaves[0] = master;
}
initialSlavePool(config);
Cache cache1 = new Cache("master_cache", masterPool, serializer, keyNamingPolicy);
RedisCluster.addWriteCache(cache1);
ShardedCache cache2 = new ShardedCache("slave_cache", slavePool, serializer, keyNamingPolicy);
RedisCluster.addReadCache(cache2);
return true;
}
public boolean stop() {
return true;
}
private void initialMasterPool(JedisPoolConfig config) {
masterPool = new JedisPool(config, master.getIp(), master.getPort(), 2000, master.getPwd());
}
private void initialSlavePool(JedisPoolConfig config) {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
for (RedisBean slave : slaves) {
JedisShardInfo temp = new JedisShardInfo(slave.getIp(), slave.getPort());
temp.setPassword(slave.getPwd());
shards.add(temp);
}
slavePool = new ShardedJedisPool(config, shards);
}
}
RedisBean 如下:
package com.jfinal.ext.plugin.redis;
/**
* https://www.hanhanfilm.com
* Created by badouyuren
*/
public class RedisBean {
private String ip;
private int port;
private String pwd;
public RedisBean() {
}
public RedisBean(String ip, int port, String pwd) {
this.ip = ip;
this.port = port;
this.pwd = pwd;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
package com.jfinal.ext.plugin.redis;
import com.jfinal.plugin.redis.IKeyNamingPolicy;
import com.jfinal.plugin.redis.serializer.ISerializer;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
/**
* https://www.hanhanfilm.com
* Created by badouyuren
*/
public class ShardedCache {
protected String name;
protected ISerializer serializer;
protected IKeyNamingPolicy keyNamingPolicy;
protected ShardedJedisPool shardedJedisPool;
protected final ThreadLocal<ShardedJedis> threadLocalShardedJedis = new ThreadLocal<>();
protected ShardedCache() {
}
public ShardedCache(String name, ShardedJedisPool shardedJedisPool, ISerializer serializer, IKeyNamingPolicy keyNamingPolicy) {
this.name = name;
this.shardedJedisPool = shardedJedisPool;
this.serializer = serializer;
this.keyNamingPolicy = keyNamingPolicy;
}
//具体的操作细节太多了,不写了
public String getName() {
return name;
}
public ISerializer getSerializer() {
return serializer;
}
public IKeyNamingPolicy getKeyNamingPolicy() {
return keyNamingPolicy;
}
public ShardedJedis getShardedJedis() {
ShardedJedis jedis = threadLocalShardedJedis.get();
return jedis != null ? jedis : shardedJedisPool.getResource();
}
public void close(ShardedJedis jedis) {
if (threadLocalShardedJedis.get() == null && jedis != null)
jedis.close();
}
public ShardedJedis getThreadLocalShardedJedis() {
return threadLocalShardedJedis.get();
}
public void setThreadLocalShardedJedis(ShardedJedis jedis) {
threadLocalShardedJedis.set(jedis);
}
public void removeThreadLocalShardedJedis() {
threadLocalShardedJedis.remove();
}
}
package com.jfinal.ext.plugin.redis;
import com.jfinal.plugin.redis.Cache;
import java.util.concurrent.ConcurrentHashMap;
/**
* https://www.hanhanfilm.com
* Created by badouyuren
*/
public class RedisSharding {
private static final ConcurrentHashMap<String, Cache> writeCacheMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, ShardedCache> readCacheMap = new ConcurrentHashMap<>();
public static void addWriteCache(Cache cache) {
if (cache == null)
throw new IllegalArgumentException("cache can not be null");
if (writeCacheMap.containsKey(cache.getName()))
throw new IllegalArgumentException("The cache name already exists");
writeCacheMap.put(cache.getName(), cache);
}
public static void addReadCache(ShardedCache cache) {
if (cache == null)
throw new IllegalArgumentException("cache can not be null");
if (readCacheMap.containsKey(cache.getName()))
throw new IllegalArgumentException("The cache name already exists");
readCacheMap.put(cache.getName(), cache);
}
public static Cache write(String cacheName) {
return writeCacheMap.get(cacheName);
}
public static ShardedCache read(String cacheName) {
return readCacheMap.get(cacheName);
}
}