redis集群(多机)分布

一、实现原理

  一致性哈希算法(Consistent Hashing): http://www.zsythink.net/archives/1182

二、配置两个redis服务,端口号要不一致

三、代码

1. 配置文件
    redis1.ip = 127.0.0.1
    redis1.port=6379

    redis2.ip = 127.0.0.1
    redis2.port=6380

    #最大连接数
    redis.max.total=20
    #最大空闲数
    redis.max.idle=10
    #最小空闲数
    redis.min.idle=2
    #效验使用可用连接
    redis.test.borrow=true
    #效验归还可用连接
    redis.test.return=false
 1 package com.mmall.common;
 2 
 3 import com.mmall.util.PropertiesUtil;
 4 import redis.clients.jedis.JedisPoolConfig;
 5 import redis.clients.jedis.JedisShardInfo;
 6 import redis.clients.jedis.ShardedJedis;
 7 import redis.clients.jedis.ShardedJedisPool;
 8 import redis.clients.util.Hashing;
 9 import redis.clients.util.Sharded;
10 import java.util.ArrayList;
11 import java.util.List;
12 
13 /**
14  * redis分片连接池
15  */
16 public class RedisShardedPool {
17     private static ShardedJedisPool pool ; //jedis连接池
18     private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total","20")); //最大连接数
19     private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle","10")); //最大空闲状态
20     private static Integer minIdle =Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle","2")); //最小空闲状态
21 
22     private static Boolean testOnBorrow =Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow","true")); //验证从连接池拿出的jedis实例,一定可用
23     private static Boolean testOnReturn =Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return","true")); //验证还回连接池的jedis实例,一定可用
24 
25     private static String redis1Ip =PropertiesUtil.getProperty("redis1.ip"); //最小空闲状态
26     private static Integer redis1Port =Integer.parseInt(PropertiesUtil.getProperty("redis1.port")); //最小空闲状态
27     private static String redis2Ip =PropertiesUtil.getProperty("redis2.ip"); //最小空闲状态
28     private static Integer redis2Port =Integer.parseInt(PropertiesUtil.getProperty("redis2.port")); //最小空闲状态
29 
30     private static void initPool(){
31         JedisPoolConfig config = new JedisPoolConfig();
32         config.setMaxTotal(maxTotal);
33         config.setMaxIdle(maxIdle);
34         config.setMinIdle(minIdle);
35 
36         config.setTestOnBorrow(testOnBorrow);
37         config.setTestOnReturn(testOnReturn);
38 
39         config.setBlockWhenExhausted(true); //连接耗尽时是否阻塞,false抛出异常;true阻塞到超时。默认true
40 
41         JedisShardInfo info1 = new JedisShardInfo(redis1Ip,redis1Port,1000*2);
42         JedisShardInfo info2 = new JedisShardInfo(redis2Ip,redis2Port,1000*2);
43         List<JedisShardInfo> jedisShardInfoList = new ArrayList<JedisShardInfo>(2);
44         jedisShardInfoList.add(info1);
45         jedisShardInfoList.add(info2);
46 
47         pool = new ShardedJedisPool(config,jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
48     }
49 
50     static{
51         initPool();
52     }
53 
54     public static ShardedJedis getJedis(){
55         return pool.getResource();
56     }
57 
58     /**
59      * redis不正常不可用,将其废弃,最新版本直接将此连接销毁jedis.close();
60      * @param jedis
61      */
62     public static void returnBrokenResource(ShardedJedis jedis){
63         pool.returnBrokenResource(jedis);
64     }
65 
66     public static void returnResource(ShardedJedis jedis){
67         pool.returnResource(jedis);
68     }
69 
70     public static void main(String[] args) {
71         ShardedJedis shardedJedis = pool.getResource();
72         for (int i = 0; i<10; i++){
73             shardedJedis.set("key"+i,"value"+i);
74         }
75         returnResource(shardedJedis); //使用后的连接放回连接池中
76 //        pool.destroy(); // 销毁连接池的所有连接
77         System.out.println("program is end");
78 
79     }
80 }

运行main方法,查询redis生成的数据:

封装常用redisAPI

import com.mmall.common.RedisShardedPool;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ShardedJedis;

/**
 * 封装分片redis
 */
@Slf4j
public class RedisShardedPoolUtil {

    /**
     * 设置对应key的有效期
     * @param key
     * @param exTime 有效期,单位秒
     * @return
     */
    public static Long expire(String key, int exTime){
        ShardedJedis shardedJedis = null;
        Long result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.expire(key,exTime);
        }catch (Exception e){
            log.error("set key:{} exTime:{} value:{} error",key,exTime,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }

    /**
     * string 添加,存在有效期exTime
     * @param key 键
     * @param value 值
     * @param exTime 有效期,单位秒
     * @return
     */
    public static String setEx(String key, String value, int exTime){
        ShardedJedis shardedJedis = null;
        String result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.setex(key,exTime,value);
        }catch (Exception e){
            log.error("set key:{} exTime:{} value:{} error",key,exTime,value,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }

    /**
     * string 添加
     * @param key
     * @param value
     * @return
     */
    public static String set(String key, String value){
        ShardedJedis shardedJedis = null;
        String result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.set(key,value);
        }catch (Exception e){
            log.error("set key:{} value:{} error",key,value,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }

    /**
     * string 获取
     * @param key
     * @return
     */
    public static String get(String key){
        ShardedJedis shardedJedis = null;
        String result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.get(key);
        }catch (Exception e){
            log.error("get key:{} error",key,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }
    public static String  getSet(String key, String value){
        ShardedJedis shardedJedis = null;
        String result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.getSet(key,value);
        }catch (Exception e){
            log.error("set key:{} value:{} error",key,value,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }

    /**
     * stirng 删除
     * @param key
     * @return
     */
    public static Long del(String key){
        ShardedJedis shardedJedis = null;
        Long result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.del(key);
        }catch (Exception e){
            log.error("get key:{} error",key,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }

    public static Long  setnx(String key, String value){
        ShardedJedis shardedJedis = null;
        Long result = null;
        try{
            shardedJedis = RedisShardedPool.getJedis();
            result = shardedJedis.setnx(key,value);
        }catch (Exception e){
            log.error("set key:{} value:{} error",key,value,e);
            RedisShardedPool.returnBrokenResource(shardedJedis);
            return result;
        }
        RedisShardedPool.returnResource(shardedJedis);
        return result;
    }
}

四、ShardedJedis相关类介绍

  (1)、ShardedJedisPool

    ShardedJedis是基于一致性哈希算法实现的分布式Redis集群客户端;ShardedJedis的设计分为以下几块:
    对象池设计:Pool,ShardedJedisPool,ShardedJedisFactory
    面向用户的操作封装:BinaryShardedJedis,BinaryShardedJedis
    一致性哈希实现:Sharded

    Sharded一致性哈希实现
    shared一致性哈希采用以下方案:
    Redis服务器节点划分:将每台服务器节点采用hash算法划分为160个虚拟节点(可以配置划分权重)
    将划分虚拟节点采用TreeMap存储
    对每个Redis服务器的物理连接采用LinkedHashMap存储
     对Key or KeyTag 采用同样的hash算法,然后从TreeMap获取大于等于键hash值得节点,取最邻近节点存储;当key的hash值大于虚拟节点hash值得最大值时,存入第一个虚拟节点。

  (2)、JedisShardInfo

      配置每台redis服务器的连接

     JedisShardInfo info1 = new JedisShardInfo(redis1Ip,redis1Port,1000*2);
posted @ 2019-10-17 11:08  王大军  阅读(876)  评论(0编辑  收藏  举报