Redis目前已经是行业内很成熟,很香的一款nosql。猿Why最早时候使用,要追溯到在上一家单位的时候了。当时只是做一个服务调用者,从未了解过Redis的知识。
但是最近项目中多次遇到一个奇怪的问题:“应用程序调用Redis服务(Redission作为客户端),set成功之后,get获取数据为null”。为了一探究竟,方便排查问题,决定认真学习一番Redis。学习分为三个步骤:基础命令学习、客户端工具学习、Redis服务学习(集群),以此文章为开篇。
为了将问题最简化:
在本地启用一个单节点Redis服务(过程是在太简单,不做赘述)
一个客户端连接操作:
另一个客户端可以作为Monitor对服务端进行监控(简化到日志都不想去看)
Spring集成Redission
redis.properties
spring.redis.address=127.0.0.1
spring.redis.port=6379
spring.redis.timeout=3000
spring.redis.password=
spring.redis.database=0
@PropertySource(name = "META-INF/redis.properties", value = "classpath:META-INF/redis.properties", ignoreResourceNotFound = false, encoding = "GBK")
@Configuration
public class RedissonConfig {
@Bean(destroyMethod = "shutdown")
public RedissonClient singleRedis(@Value("${spring.redis.address}") String address,
@Value("${spring.redis.port}") String port,
@Value("${spring.redis.timeout}") int timeout,
@Value("${spring.redis.password}") String password,
@Value("${spring.redis.database}") int database
) {
Config config = new Config();
SingleServerConfig singleServerConfig = config.useSingleServer();
singleServerConfig.setAddress("redis://" + address + ":" + port);
singleServerConfig.setTimeout(timeout);
singleServerConfig.setDatabase(database);
if (!StringUtils.isEmpty(password)) {
singleServerConfig.setPassword(password);
}
return Redisson.create(config);
}
}
Demo Test
public class RedissionClientTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(RedissonConfig.class);
context.register(RedissionClientTest.class);
context.refresh();
RedissonClient redissonClient = context.getBean(RedissonClient.class);
RMap<String, String> rMap = redissonClient.getMap("demo");
System.out.printf("Map容量:%d\n", rMap.size());
System.out.printf("test:%s\n", rMap.get("test"));
redissonClient.shutdown();
context.close();
}
}
然而,结果是这样的:
好嘛!细心一点可以发现,redis-cli 通过命令方式去操作的时候,是可以获取到值的,here we go,看看服务端监控:发现了什么?field多了一层双引号
问题出在哪里?
直接上结果:Redission依赖JsonJackson,导致RMap反序列化异常
Unable to evaluate the expression Method threw 'org.redisson.client.RedisException' exception.
那么规避办法呢?
RedissonConfig中补充一行代码
config.setCodec(new org.redisson.client.codec.StringCodec());
至于其中原理,后边的章节一探究竟。
另外:出现这种类似问题还有可能因为:
主从复制模式下,在master set之后,尚未同步到slave,就从slave读取,自然不会get到(后边一边学习,一边记录吧)