使用spring-data-redis实现incr自增
2017-09-03 13:13
1001 查看
redis系列文章目录
使用spring-data-redis实现incr自增Redis 利用Hash存储节约内存
Redis学习笔记(九)redis实现时时直播列表缓存,支持分页[热点数据存储]
Redis学习笔记(八)redis之lua脚本学习
Redis学习笔记(七)jedis超时重试机制注意事项
Redis学习笔记(六)redis实现分布式锁
Redis学习笔记(五)jedis(JedisCluster)操作Redis集群 redis-cluster
redis学习笔记(四)缓存与数据库一致性问题
redis学习笔记(三)数据淘汰策略
redis学习笔记(二)JedisCluster + redis 3.2.5集群
redis学习笔记(一)redis3.2.5集群安装与测试
应该有不少人在使用spring-data-redis时遇到各种各样的问题。反正我是遇到了。
由于是隔了一段时间才写的本篇博客,也懒得去重现哪些错误场景了,下面凭着记忆写了几个我遇到的问题:
redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range
使用的RedisTemplate,做读写操作时候,都是要经过序列化和反序列化。这时你使用
redisTemplate.opsForValue().increment()就可能报错
redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range了。
valueOper.get(key) 获取不到自增的值。
于是我去看了一下redis的官方文档,找到一个解决方法使用spring-data-redis实现incr自增
/** * * @param key * @param liveTime * @return */ public Long incr(String key, long liveTime) { RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); Long increment = entityIdCounter.getAndIncrement(); if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间 entityIdCounter.expire(liveTime, TimeUnit.SECONDS); } return increment; }
这样,上面的
increment就是自增后的新知值,然后中间通过
entityIdCounter.expire(liveTime, TimeUnit.SECONDS);设置过期时间。当然这里比较讨厌,spring没有在创建
RedisAtomicLong对象的时候一起设置过期时间。可以看看其源码,
new RedisAtomicLong最终调用的是这个方法:
private RedisAtomicLong(String redisCounter, RedisConnectionFactory factory, Long initialValue) { Assert.hasText(redisCounter, "a valid counter name is required"); Assert.notNull(factory, "a valid factory is required"); RedisTemplate<String, Long> redisTemplate = new RedisTemplate<String, Long>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericToStringSerializer<Long>(Long.class)); redisTemplate.setExposeConnection(true); redisTemplate.setConnectionFactory(factory); redisTemplate.afterPropertiesSet(); this.key = redisCounter; this.generalOps = redisTemplate; this.operations = generalOps.opsForValue(); if (initialValue == null) { if (this.operations.get(redisCounter) == null) { set(0); } } else { set(initialValue); } }
可以看到,初始值是0。
然后根进
set方法
public void set(long newValue) { operations.set(key, newValue); }
可以看到,他是采用的
operations.set(key, newValue);但是明明还有一个重载的方法
void set(K key, V value, long timeout, TimeUnit unit);可以设置过期时间,为啥spring不提供呢。
为了解决这个问题,我们可以自己模拟
RedisAtomicLong方法,去实现一个带有过期时间的自增方法。比较简单,读者自行撸代码吧,这里就不写出了。
相关文章推荐
- 使用Spring Data +Redis实现缓存
- 分布式缓存技术redis学习系列(五)——spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- spring data redis 集群(sentinel实现)和simple spring memcached分布式初使用
- 分布式缓存技术redis学习系列(五)——spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- 分布式缓存技术redis学习系列(五)——spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- 使用Spring Data Redis实现缓存遇到的一些问题
- 使用Spring Data Redis 实现订阅/发布
- 分布式缓存技术redis学习系列(五)——spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- 【Redis】spring-data-redis与JedisPool的区别、使用ShardedJedisPool与spring集成的实现及一致性哈希分析
- 深入理解Spring Redis的使用 (六)、用Spring Aop 实现注解Dao层的自动Spring Redis缓存
- 【Redis基础】SSH 中Spring-data-redis使用体验
- 在spring data jpa中使用redis的通用list及entity存储方法
- 利用redis(spring-data-redis)锁的功能来实现定时器的分布式
- 五分钟学会使用spring-data-cassandra快速实现数据的访问
- spring-data-redis使用RedisTemplate模板存储时键值与预设不一致的解决方法
- springdata redis实现的简单demo
- redis实现 spring-redis-data,存取对象
- redis实现spring-redis-data的入门实例
- spring-data-redis 使用过程中需要注意的一点