抛砖引玉,分享一下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); } }