hanhanfilm中扩展jfinal Redis插件,实现读写分离


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


}

评论区

sphsyv

2016-09-12 08:45

这种不是集群啊,JedisShardInfo与JedisCluster是不同的东西。看官方https://github.com/xetorthio/jedis,Redis cluster specification (still under development) is implemented

badouyuren

2016-09-12 13:49

@sphsyv 谢谢指正。

bing086

2017-03-11 20:15

二阳

2017-05-15 13:37

热门分享

扫码入社