学习目标:
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等方式实现