java通过jedis操作redis(从JedisPool到JedisCluster)

redis作为一个缓存数据库,在绝大多数java项目开发中是必须使用的,在web项目中,直接配合spring-redis,各种配置都直接在spring配置文件中做了,一般都是使用redis连接池。在非web项目中,通常也是使用的redis连接池。

根据redis的机器数量和集群方式,又分为以下三种方式:普通单机版的redis,多机器的分片集群,多机器的cluster集群方式(redis3版本以上)。

对于单机版的redis使用简单示例如下:

package com.xxx.redis.redisdemo;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolUtil {
	private static JedisPool jedisPool;
	
	public static JedisPool getJedisPool(){
		if(jedisPool == null){
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxIdle(200);
			config.setMaxIdle(50);
			config.setMaxWaitMillis(1000 * 100);
			config.setTestOnBorrow(false);
			jedisPool = new JedisPool(config, "192.168.42.128",6379);
		}
		return jedisPool;
	}	
	
	public static String get(String key){
		String value = null;
		JedisPool pool = null;
		Jedis jedis = null;
		try{
			pool = getJedisPool();
			jedis = pool.getResource();
			value = jedis.get(key);
		}catch(Exception e){
			e.printStackTrace();
		}
		return value;
	}
	
	public static void set(String key,String value){
		JedisPool pool = null;
		Jedis jedis = null;
		try{
			pool = getJedisPool();
			jedis = pool.getResource();
			value = jedis.set(key,value);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		set("name", "xx-jedis");
		String name = get("name");
		System.out.println(name);
	}
}

 这是一个最简单的demo,实际项目中,会配置redis host,port等信息,也会根据redis支持的方法和jedis的api,完善更多的方法,如delete,expire,sadd,lpush等等。

当项目增大,需要缓存的数据量增大,我们会考虑做分布式集群,集群的数量可以根据业务需求扩展。数据存储会均匀分布在各个分片上。这里给出一个示例:

package com.xxx.redis.redisdemo;
import java.util.ArrayList;
import java.util.List;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
public class ShardedPoolUtil {
	private static ShardedJedisPool jedisPool;
	public static ShardedJedisPool getJedisPool(){
		if(jedisPool == null){
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxTotal(200);
			config.setMaxIdle(50);
			config.setMaxWaitMillis(1000*100);
			config.setTestOnBorrow(false);
			List<JedisShardInfo> shareInfos = new ArrayList<JedisShardInfo>();
			shareInfos.add(new JedisShardInfo("192.168.42.128", 6379));
			shareInfos.add(new JedisShardInfo("192.168.42.128", 6380));
			jedisPool = new ShardedJedisPool(config, shareInfos);
		}
		return jedisPool;
	}
	
	public static void set(String key,String value){
		ShardedJedisPool pool = null;
		ShardedJedis jedis = null;
		try{
			pool = getJedisPool();
			jedis = pool.getResource();
			jedis.set(key, value);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static String get(String key){
		String value = null;
		ShardedJedisPool pool = null;
		ShardedJedis jedis = null;
		try{
			pool = getJedisPool();
			jedis = pool.getResource();
			value = jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}
	
	public static void main(String[] args) {
		String age = "30";
		String address = "beijing";
		set("age", age);
		set("address", address);
		System.out.println(get("age"));
		System.out.println(get("address"));
	}
}

相对单机版的redis,sharding分布式集群方式:配置ShardedJedisPool多了设置多个redis服务器信息。 数据分布在哪个机器上,是有算法的,这里支持MD5和MURMUR两种散列函数的方式,默认采用的是MURMUR哈希方法。

这第二种方法,虽然是分布式的,数据分布在不同的机器上,但是并没有采用集群的方式,因为支持redis集群的是3.0版本及以上,目前redis集群方式,数据是以槽的方式分布的,因为需要保证一个master对应至少一个slave节点,所以节点数会比sharding分布式节点多。

redis-cluster这种情况下,java调用的方式会发生一些变化,但是还是相似的思路。

package com.xxx.redis.redisdemo;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
public class ClusterPoolUtil {
	
	private static JedisCluster jedisCluster;
	private static String hostAndPorts = "192.168.42.128:6379||192.168.42.128:6380||"
			+ "192.168.42.128:6381||192.168.42.128:6382||"
			+ "192.168.42.128:6383||192.168.42.128:6384";
		
	public static JedisCluster getJedisCluster(){
				
		if(jedisCluster==null){
			int timeOut = 10000;
			Set<HostAndPort> nodes = new HashSet<HostAndPort>();
			JedisPoolConfig poolConfig = new JedisPoolConfig();
			poolConfig.setMaxTotal(200);
			poolConfig.setMaxIdle(50);
			poolConfig.setMaxWaitMillis(1000 * 100);
			poolConfig.setTestOnBorrow(false);
			
			String[] hosts = hostAndPorts.split("\\|\\|");
			for(String hostport:hosts){
				String[] ipport = hostport.split(":");
				String ip = ipport[0];
				int port = Integer.parseInt(ipport[1]);
				nodes.add(new HostAndPort(ip, port));
			}
			jedisCluster = new JedisCluster(nodes,timeOut, poolConfig);
		}
		return jedisCluster;
	}
	
	public static void set(String key,String value){
		JedisCluster jedisCluster = getJedisCluster();
		jedisCluster.set(key, value);
	}
	
	public static String get(String key){
		String value = null;
		JedisCluster jedisCluster = getJedisCluster();
		value = jedisCluster.get(key);
		return value;
	}
	
	public static void main(String[] args) {
		set("name-1", "value-1");
		set("name-2", "value-2");
		set("name-3", "value-3");
		System.out.println(get("name-1"));
		System.out.println(get("name-2"));
		System.out.println(get("name-3"));
	}
}

 redis-cluster集群安装好了之后,做好slot分配,就可以开始使用redis存储和查找了。redis-cluster是redis3开始支持的,他与sharding分片方式不同的是,数据是按照slot槽(16384个slot)分布的,slot的划分不是固定的,可以人为指定。这里使用了六个节点,分为三组,所以slot划分为3组槽(5461,5461,5460),分别如下:

{
0=192.168.42.128:6382, 5460=192.168.42.128:6382, 
5461=192.168.42.128:6380, 10922=192.168.42.128:6380, 
10923=192.168.42.128:6384, 16383=192.168.42.128:6384
}

第一组是0-5460,第二组是5461-10922,第三组是10993-16383,从分组中可以看出,6380,6382,6384端口的节点都是master节点,这可以在redis-cluster集群中查看:

 存储的key分布在哪个槽上,可以通过如下方法获取:

public static int getSlot(String key){
    return JedisClusterCRC16.getSlot(key);
}

按照这种方法计算name-1,name-2,name-3的slot槽分别是:10801,6738,2675。按照之前的slot分布,可以得到name-1,name-2均落在6380上,name-3则落在6382上,我们可以在redis-cluster集群上通过命令来查找key,验证了这个结果:

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
JedisCluster Could not get a resource from the pool错误通常是由于连接池中的资源不足或连接超时引起的。以下是一些可能的解决方案: 1. 增加连接池的最大连接数和最大空闲连接数,以确保连接池中有足够的资源可用。 2. 增加连接池的超时时间,以便在连接池中没有可用连接时等待更长的时间。 3. 检查redis集群的配置是否正确,确保所有节点都已正确配置。 4. 检查redis集群的状态,确保所有节点都处于正常状态。 5. 检查网络连接是否正常,确保可以从应用程序服务器访问redis集群。 以下是一些可能的解决方案的代码示例: ```java // 增加连接池的最大连接数和最大空闲连接数 JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(100); poolConfig.setMaxIdle(50); // 增加连接池的超时时间 JedisCluster jedisCluster = new JedisCluster(nodes, 5000, 5000, 10, password, poolConfig); // 检查redis集群的配置是否正确 Set<HostAndPort> nodes = new HashSet<HostAndPort>(); nodes.add(new HostAndPort("127.0.0.1", 7000)); nodes.add(new HostAndPort("127.0.0.1", 7001)); nodes.add(new HostAndPort("127.0.0.1", 7002)); JedisCluster jedisCluster = new JedisCluster(nodes, poolConfig); // 检查redis集群的状态 Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes(); for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) { Jedis jedis = null; try { jedis = entry.getValue().getResource(); String pong = jedis.ping(); System.out.println(entry.getKey() + " - " + pong); } catch (Exception e) { System.out.println(entry.getKey() + " - " + e); } finally { if (jedis != null) { jedis.close(); } } } // 检查网络连接是否正常 ping redis-server-ip ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值