一、实现原理

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

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

三、代码

. 配置文件
redis1.ip = 127.0.0.1
redis1.port= redis2.ip = 127.0.0.1
redis2.port= #最大连接数
redis.max.total=
#最大空闲数
redis.max.idle=
#最小空闲数
redis.min.idle=
#效验使用可用连接
redis.test.borrow=true
#效验归还可用连接
redis.test.return=false
 package com.mmall.common;

 import com.mmall.util.PropertiesUtil;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.util.Hashing;
import redis.clients.util.Sharded;
import java.util.ArrayList;
import java.util.List; /**
* redis分片连接池
*/
public class RedisShardedPool {
private static ShardedJedisPool pool ; //jedis连接池
private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total","20")); //最大连接数
private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle","10")); //最大空闲状态
private static Integer minIdle =Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle","2")); //最小空闲状态 private static Boolean testOnBorrow =Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow","true")); //验证从连接池拿出的jedis实例,一定可用
private static Boolean testOnReturn =Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return","true")); //验证还回连接池的jedis实例,一定可用 private static String redis1Ip =PropertiesUtil.getProperty("redis1.ip"); //最小空闲状态
private static Integer redis1Port =Integer.parseInt(PropertiesUtil.getProperty("redis1.port")); //最小空闲状态
private static String redis2Ip =PropertiesUtil.getProperty("redis2.ip"); //最小空闲状态
private static Integer redis2Port =Integer.parseInt(PropertiesUtil.getProperty("redis2.port")); //最小空闲状态 private static void initPool(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle); config.setTestOnBorrow(testOnBorrow);
config.setTestOnReturn(testOnReturn); config.setBlockWhenExhausted(true); //连接耗尽时是否阻塞,false抛出异常;true阻塞到超时。默认true JedisShardInfo info1 = new JedisShardInfo(redis1Ip,redis1Port,1000*2);
JedisShardInfo info2 = new JedisShardInfo(redis2Ip,redis2Port,1000*2);
List<JedisShardInfo> jedisShardInfoList = new ArrayList<JedisShardInfo>(2);
jedisShardInfoList.add(info1);
jedisShardInfoList.add(info2); pool = new ShardedJedisPool(config,jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
} static{
initPool();
} public static ShardedJedis getJedis(){
return pool.getResource();
} /**
* redis不正常不可用,将其废弃,最新版本直接将此连接销毁jedis.close();
* @param jedis
*/
public static void returnBrokenResource(ShardedJedis jedis){
pool.returnBrokenResource(jedis);
} public static void returnResource(ShardedJedis jedis){
pool.returnResource(jedis);
} public static void main(String[] args) {
ShardedJedis shardedJedis = pool.getResource();
for (int i = 0; i<10; i++){
shardedJedis.set("key"+i,"value"+i);
}
returnResource(shardedJedis); //使用后的连接放回连接池中
// pool.destroy(); // 销毁连接池的所有连接
System.out.println("program is end"); }
}

运行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);

redis集群(多机)分布的更多相关文章

  1. Redis集群分布

    Redis系列 作者Mr.Chen,转载请注明博客出处:http://www.cnblogs.com/cjh-notes/ Redis集群存储 先看下架构图,下面说明其存储原理:首先redis每个节点 ...

  2. 在虚拟机上安装redis集群,redis使用版本为4.0.5,本机通过命令客户端可以连接访问,外部主机一直访问不了

    在虚拟机上安装了redis 4 ,启动后本机客户端可以连接访问,但是外部主机一直访问不了,在使用java代码连接redis集群时报:no reachable node in cluster,原因:在r ...

  3. redis集群节点宕机

    redis集群是有很多个redis一起工作,那么就需要这个集群不是那么容易挂掉,所以呢,理论上就应该给集群中的每个节点至少一个备用的redis服务.这个备用的redis称为从节点(slave). 1. ...

  4. Redis集群环境之linux搭建多机版---已完结,跟着一步一步来你就可以集群成功

    上一篇踩着各种坑写了Redis集群环境之linux搭建单机版,这一篇准备就多机版集群进行搭建,主要目的一来是在上一篇的基础上进行精华提粹总结,二来是把单机版与多机版的区别进行记录. 首先软硬件环境: ...

  5. centos6.5下redis集群配置(多机多节点)

    可参考官网文档:redis集群配置 需要注意的是,集群中的每个节点都会涉及到两个端口,一个是用于处理客户端操作的(如下介绍到的6379/6380),另一个是10000+{监听端口},用于集群各个节点间 ...

  6. Redis 集群的合纵与连横

    之前一篇写了关于 Redis 的性能,这篇就写写我认为比性能更重要的扩展性方面的主题. 如果再给我一次回到好几年前的机会,对于使用 Redis 我一开始就要好好考虑将来的扩展问题.就像我们做数据库分库 ...

  7. (转)基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案

    转载自:http://warm-breeze.iteye.com/blog/2020413 本文主要介绍一种通过Jedis&Sentinel实现Redis集群高可用方案,该方案需要使用Jedi ...

  8. Redis集群

    一.Redis集群原理 集群技术是构建高性能网站架构的重要手段,试想在网站承受高并发访问压力的同时,还需要从海量数据中查询出满足条件的数据,并快速响应,我们必然想到的是将数据进行切片,把数据根据某种规 ...

  9. Redis集群方案应该怎么做

    方案1:Redis官方集群方案 Redis Cluster Redis Cluster是一种服务器sharding分片技术.Redis Cluster集群如何搭建请参考我的另一篇博文:http://w ...

随机推荐

  1. DP(第二版)

    第一版请见:直通 话不多说,直接上题 1.P1040 加分二叉树 直通 思路: 已知中序遍历,相当于一段区间了,所以我们枚举一个k,如果以k为根节点,能够将分数更新,那么这段区间的根节点就置为k,最后 ...

  2. 1656:Combination

    一本通1656:Combination 1656:Combination 时间限制: 1000 ms         内存限制: 524288 KB提交数: 89     通过数: 49 [题目描述] ...

  3. 常用exporter下载

    1.node_exporter https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter- ...

  4. HTML页面预览表格文件内容

    背景简介 在将一个表格文件上传到服务器上之前,JS读取表格文件并将文件内容输出到页面中 vue项目 第三方 exceljs 安装 npm install exceljs 插件使用 github 中文文 ...

  5. 字符串匹配 - hash

    之前有写过一篇hash表,不过那是非常久远的时候了,应该是大一刚学一个学期的时候的成果,后来也就不那样写了,后来从xiaoxin那里学习了hash的写法,比较容易用也比较方便多hash,就这样. 分别 ...

  6. Nginx内置变量及正则语法

    对于很多Nginx初学者来说,配置文件是必须要看懂的.但是当公司的Nginx配置文件放在你面前的时候你总会被一些带着"$"符号和一大推看不懂的的正则给正懵逼.没错带着"$ ...

  7. 在使用vagrant访问PHP文件是报错“file not found”,好像是最新的NGINX不能识别document_root,只能改为自己的项目目录/vagrant_data

    出现该错误有很多可能,有可能是root配置不对,有可能是fastcgi_param SCRIPT_FILENAME参数不对等. 而本人遇到的也是参数不对,但是是一个比较少人提及的问题,nginx版本不 ...

  8. python 调用github的api,呈现python的受欢迎的程度

    1 使用api调用数据: 在浏览器的地址栏中输入: https://api.github.com/search/repositories?q=language:python&sort=star ...

  9. Methods for Identifying Out-of-Trend Results in Ongoing Stability Data

     python机器学习-乳腺癌细胞挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  10. AlarmManager(闹钟服务)

    1.Timer类与AlarmManager类区别: 对Timer就是定时器,一般写定时任务的时候 肯定离不开他,但是在Android里,他却有个短板,不太适合那些需要长时间在后台运行的 定时任务,因为 ...