20、ShardedJedis客户端分片

学习目标:

1、使用JRedis的客户端分片

2、掌握Spring Boot整合Redis的客户端

学习过程:

      如果需要缓存的内容很多,单台服务器的内存不够,那么我们可以使用两台Redis服务器,使用客户端的分片技术,可以自动根据Key分布到Redis服务器中。

    ShardedJedis是通过一致性哈希来实现分布式缓存的,由客户端通过把不同的key通过一致性哈希,计算出其对应的RedisServer,把该key分配到不同的redis server上,从而达到横向扩展的目的。优点是客户端进行计算,效率较高,服务端只需要简单的启动多台redis服务器就可以了。缺点也很明显,redis服务器之间事实上没有任何关系的,之间并没有做备份,所以是不能保证高可用性的,任意一台redis服务器挂了,该redis上面的所有的key都不可以访问了。

一、实战

1、先准备两台Redis服务,分别安装Redis,安装方式和前面的课程一样就可以了,然后分别启动就可以了,可以参考签名的redis的安装的文章。

2、使用ShardedJedis实现

(1)先定义链接池,记录redis的连接信息

ShardedJedisPool pool;

@Before
public void pre() {
	List<JedisShardInfo> jedisShardInfos = new ArrayList<JedisShardInfo>();
	JedisPoolConfig config = new JedisPoolConfig();
	config.setMaxTotal(50);
	String[] serversLo = { "192.168.137.101:6379", "192.168.137.102:6379" };
	for (String server : serversLo) {
		String[] hostport = server.split(":");
		JedisShardInfo info = new JedisShardInfo(hostport[0], Integer.parseInt(hostport[1]), 5000);
		info.setPassword("123456");
		jedisShardInfos.add(info);

	}

	pool = new ShardedJedisPool(config, jedisShardInfos);
}

(2)操作,基本操作差不多,就是通过ShardedJedisPool 获得对应的ShardedJedis 就可以操作了。

@Test
public void testBfAdd() {
	//基本操作
	try(ShardedJedis shardedJedis=pool.getResource()){
		String result=shardedJedis.set("sname", "liubao");
		System.out.println(result);
	}
}

@Test
public void testGetShardInfo() {
	// 想知道自己的key计算去了哪里,可以通过getShardInfo方法获得
	try(ShardedJedis shardedJedis = pool.getResource()){
		JedisShardInfo info = shardedJedis.getShardInfo("sname");
		System.out.println(info.getHost() + ":" + info.getPort());
	}

}

@Test
public void testGetClient() {
	// 调用扩展命令,可以直接使用getShard().getClient()
	try(ShardedJedis shardedJedis = pool.getResource()){
		Connection client = shardedJedis.getShard("abcd").getClient();
		client.sendCommand(Command.ADD, "computer", "baobaobb");
		client.close();
	}
}

3、使用Spring Boot整合Redis,先导入相关的包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

(1)在application.properties中配置连接信息

myredis.shard.name=redisshard
myredis.shard.servers=192.168.137.101:6379,192.168.137.102:6379
myredis.shard.auth=123456
myredis.shard.timeout=5000
myredis.shard.maxTotal=32

(2)实现分片连接配置

@Configuration

@ConfigurationProperties(prefix = "myredis.shard")    

public class RedisShardConfig {
    private String servers;
    private int timeout;
    private int maxTotal;
    private String name;
    private String auth;

    @Bean
    public ShardedJedisPool shardedJedisPool() {
        List<JedisShardInfo> jedisShardInfos=new ArrayList<JedisShardInfo>();
        JedisPoolConfig config=new JedisPoolConfig();
        config.setMaxTotal(maxTotal);
        String[] serversLo=servers.split(",");
        for(String server:serversLo) {
            String[] hostport=server.split(":");
            JedisShardInfo info=new JedisShardInfo(hostport[0],Integer.parseInt(hostport[1]),timeout);
            info.setPassword(auth);
            jedisShardInfos.add(info);

        }
        return new ShardedJedisPool(config,jedisShardInfos);
    }

    public String getServers() {
        return servers;
    }
    public void setServers(String servers) {
        this.servers = servers;
    }
    public int getTimeout() {
        return timeout;
    }
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
    public int getMaxTotal() {
        return maxTotal;
    }
    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

(3)实现工具类

@Component
public class RedisUtil {
    @Autowired
    private ShardedJedisPool pool;
    public void set(String key, String value) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = pool.getResource();
            if (shardedJedis != null) {
                shardedJedis.set(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (shardedJedis != null) {
                shardedJedis.close();
            }
        }
    }

    public String get(String key) {
        ShardedJedis shardedJedis = null;
        try {
            shardedJedis = pool.getResource();
            if (shardedJedis != null) {
                return shardedJedis.get(key);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (shardedJedis != null) {
                shardedJedis.close();
            }
        }
        return null;
    }
}

(4)、测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringfirstApplicationTests {
    @Autowired
    private RedisUtil redisUtil;

    @Test
    public void testRedis() {
        System.out.println(redisUtil);
        redisUtil.set("java", "haha");
        redisUtil.set("abc", "akey");
    }
}

     最后,你可以登陆到不同的redis服务器中,可以看到每个服务器之间由不通的key保存着,这种客户端的分片非常简单,可以充分利用服务器的资源。但是高可用性时没有保证的。如果某一台服务器挂了,那么这台服务器上面的所有缓存都会没有了。如果你的缓存信息非常重要,如果要保证高可用性,在redis 3.0后可以使用主从+sentinel或者cluster等方式实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值