Redisクライアント単純パッケージ


詳細
Redisクライアントは簡単にパッケージ化してspringを統合する.Spring-data-redisはredisに過度なパッケージ化の疑いがあり,shardingモードも提供されていないため,本稿ではjedisを簡単にパッケージ化した.
 


    
    
    
        
        
        
        
        
        
        
    
    
    
        
        
        
        
        
        
    
    
    
        
        
        
        
        
        
    

    


 
 
 
package com.itlong.whatsmars.redis.client.singleton;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class SingletonRedisClient implements FactoryBean,InitializingBean {
    private JedisPool jedisPool;

    private int maxTotal = 128;

    //       
    private int maxIdle = 2;

    //       
    private int minIdle = 1;
    //       ,       ,   3 
    private long maxWait = 3000;//    
    private String host;
    private int port;
    private int database = 0;//     ,   0
    private int timeout = 3000;//connectionTimeout,soTimeout,   3 

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String password;

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setDatabase(int database) {
        this.database = database;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        jedisPool = new JedisPool(config,host,port,timeout, password, database,null);
    }

    @Override
    public JedisPool getObject() throws Exception {
        return jedisPool;
    }

    @Override
    public Class> getObjectType() {
        return JedisPool.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

 
package com.itlong.whatsmars.redis.client.readwrite;

import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class ReadWriteRedisClient implements InitializingBean {
    //master:port,slave:port,slave:port...
    //master first
    private String hosts;
    private JedisPool master;
    private List slaves = new ArrayList();

    private int maxTotal = 128;

    //       
    private int maxIdle = 2;

    //       
    private int minIdle = 1;
    //       ,       ,   3 
    private long maxWait = 3000;//    
    private int database = 0;//     ,   0
    private int timeout = 3000;//connectionTimeout,soTimeout,   3 

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String password;

    private Random random = new Random();

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setDatabase(int database) {
        this.database = database;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setHosts(String hosts) {
        this.hosts = hosts;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        String[] hostAndPorts = hosts.split(",");
        String masterHP = hostAndPorts[0];
        String[] ms = masterHP.split(":");
        master = new JedisPool(config,ms[0],Integer.valueOf(ms[1]),timeout, password, database,null);
        if(hostAndPorts.length > 1) {
            for(int i = 1; i < hostAndPorts.length; i++) {
                String[] ss = hostAndPorts[i].split(":");
                JedisPool slave = new JedisPool(config,ss[0],Integer.valueOf(ss[1]),timeout, password, database,null);
                slaves.add(slave);
            }
        }
        slaves.add(master);
    }

    public String get(String key) {
        Jedis jedis = fetchResource(true);
        try {
            return jedis.get(key);
        } finally {
            jedis.close();
        }
    }

    public List mget(String... keys) {
        Jedis jedis = fetchResource(true);
        try {
            return jedis.mget(keys);
        } finally {
            jedis.close();
        }
    }

    public String setex(String key,int seconds,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.setex(key,seconds,value);
        } finally {
            jedis.close();
        }
    }

    public Long setnx(String key,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.setnx(key,value);
        } finally {
            jedis.close();
        }
    }

    public String set(String key,String value) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.set(key,value);
        } finally {
            jedis.close();
        }
    }

    public Long del(String key) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.del(key);
        } finally {
            jedis.close();
        }
    }

    public Long expire(String key,int seconds) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.expire(key,seconds);
        } finally {
            jedis.close();
        }
    }

    public Boolean exists(String key) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.exists(key);
        } finally {
            jedis.close();
        }
    }

    public Long exists(String... keys) {
        Jedis jedis = fetchResource(false);
        try {
            return jedis.exists(keys);
        } finally {
            jedis.close();
        }
    }

    private Jedis fetchResource(boolean read) {
        if(slaves.isEmpty() || !read) {
            return master.getResource();
        }
        int size = slaves.size();
        int i = random.nextInt(size);
        return slaves.get(i).getResource();
    }


    public static void main(String[] args) throws Exception {
        String prefix = "_test_";
        ReadWriteRedisClient client = new ReadWriteRedisClient();
        client.setHosts("127.0.0.1:6379,127.0.0.1:6379");

        client.afterPropertiesSet();

        client.set(prefix + "10001","test");
        System.out.println(client.get(prefix + "10001"));
    }
}

 
package com.itlong.whatsmars.redis.client.cluster;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by javahongxi on 2017/6/22.
 */
public class RedisClusterClient implements FactoryBean,InitializingBean {
    private JedisCluster jedisCluster;

    private int maxTotal = 128;

    //       
    private int maxIdle = 6;

    //       
    private int minIdle = 1;
    //       ,       ,   3 
    private long maxWait = 3000;//    

    private int timeout = 3000;//connectionTimeout,soTimeout,   3 

    private boolean testOnBorrow = true;
    private boolean testOnReturn = true;

    private String addresses;//ip:port,ip:port

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public void setAddresses(String addresses) {
        this.addresses = addresses;
    }

    protected JedisPoolConfig buildConfig() {
        JedisPoolConfig config = new JedisPoolConfig();

        config.setMinIdle(minIdle);
        config.setMaxIdle(maxIdle);
        config.setMaxTotal(maxTotal);
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        config.setBlockWhenExhausted(true);
        config.setMaxWaitMillis(maxWait);
        config.setFairness(false);

        return config;
    }

    private Set buildHostAndPorts() {
        String[] hostPorts = addresses.split(",");
        Set hostAndPorts = new HashSet();
        for(String item : hostPorts) {
            String[] hostPort = item.split(":");
            HostAndPort hostAndPort = new HostAndPort(hostPort[0],Integer.valueOf(hostPort[1]));
            hostAndPorts.add(hostAndPort);
        }
        return hostAndPorts;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        JedisPoolConfig config = buildConfig();
        Set hostAndPorts = buildHostAndPorts();
        jedisCluster = new JedisCluster(hostAndPorts,timeout,config);
    }

    @Override
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    @Override
    public Class> getObjectType() {
        return JedisCluster.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

 
 
/**
 * Created by javahongxi on 2017/6/23.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-redis.xml")
public class Demo {

    @Autowired
    @Qualifier("singletonRedisClient")
    private JedisPool singletonRedisClient;

    @Autowired
    private ReadWriteRedisClient readWriteRedisClient;

    @Autowired
    @Qualifier("redisClusterClient")
    private JedisCluster jedisCluster;

    @Test
    public void testSingleton() {
        Jedis jedis = singletonRedisClient.getResource();
        String cacheContent = null;
        try {
            cacheContent = jedis.get("hello_world");
        }finally {
            singletonRedisClient.close();
        }
        //   redis    ,      ,          
        if(cacheContent == null) {
            // DB operation
        }
        // ..
    }

    @Test
    public void testReadWrite() {
        String cacheContent = null;
        try {
            cacheContent = readWriteRedisClient.get("hello_world");
        } catch (Exception e) {
            //    ,         
        }
        if(cacheContent == null) {
            //  cache    ,  redis  
        }
    }

    @Test
    public void testCluster() {
        String cacheContent = null;
        try {
            cacheContent = jedisCluster.get("hello_world");
        } catch (Exception e) {
            //    ,         
        }
        if(cacheContent == null) {
            //  cache    ,  redis  
        }
    }
}

 
 
@M-Sモードによる読み書き分離
通常、Slaveはデータバックアップとしてのみ使用され、read操作は提供されません.slaveがstaleデータを提供することを避けるためにいくつかの問題が発生します.しかし、多くのシナリオでは、slaveデータに一定の遅延があっても、互換性があるか正常に処理することができます.この場合、slaveはreadサービスを提供し、M-Sクラスタでread操作を分流することができます.この場合、私たちのRedisクラスタはより高いQPSをサポートすることができます.この例では、「読み書き分離」のテンプレートのみが提供されており、すべてのredisメソッドが書き換えられ、カプセル化されていません.開発者は後で補足してください.さらに、slaveノードが異常であればfailoverをサポートする必要があります.この部分の特性は後で拡張されます. 
   https://github.com/javahongxi/whatsmars/tree/master/whatsmars-redis