基本语法
public void putObject() {
Jedis jedis = new Jedis("localhost", 6379);
System.out.println(jedis.ping());
System.out.println("=======================");
/*string*/
jedis.set("str","hello redis");
String jString=jedis.get("str");
System.out.println(jString);
/*map*/
Map map = new HashMap();
map.put("a", "a");
map.put("b", "b");
jedis.hmset("map", map);
Map map1=jedis.hgetAll("map");
System.out.println(jedis.hmget("map", "a", "b"));
System.out.println(map1.keySet());
/*list*/
String[] li = {"a", "b", "c"};
jedis.lpush("li", li);
List list = jedis.lrange("li", 0, -1);
System.out.println(list);
}
springboot 配置
spring.cache.type=redis
spring.cache.redis.time-to-live=60000
# Redis数据库索引(默认为0)
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=123456
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=300
# 是否启用SSL连接.
#spring.redis.ssl=false
service
@Service @EnableCaching public class CategoryService { @Autowired private CategoryMapper categoryMapper; @Cacheable(cacheNames = "cate", key = "#p0") public Category getById(Integer id) { return categoryMapper.getById(id); } @CachePut(cacheNames = "cate", key = "#p0.id") public Category updateCategoryById(Category category) { categoryMapper.updateCategoryById(category); return category; } }
@Mapper public interface CategoryMapper { @Select("select * from category where id = #{id}") Category getById(Integer id); @Update("update category set cateName=#{cateName}, date=#{date} where id=#{id} ") int updateCategoryById(Category category); }
redis配置类
@Configuration public class MyRedisCacheConfiguration extends CachingConfigurerSupport { @Bean public CacheManager getRedisCacheManager(RedisConnectionFactory factory) { RedisCacheWriter writer = RedisCacheWriter.nonLockingRedisCacheWriter(factory); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig( Thread.currentThread().getContextClassLoader() ); config.entryTtl(Duration.ofHours(1)); //值的序列化 // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer(); RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair .fromSerializer(jsonSerializer); config.serializeValuesWith(pair); RedisCacheManager manager = new RedisCacheManager(writer, config); return manager; } }
项目中使用了热部署,在自动装配bean获取CacheManager时
装载redisconfig,会使用到devtools容器,该容器具有缓存作用
读取redis数据进行反序列化,会出现类型转换错误
解决思路:
1.直接删除热部署
2.创建redisconfig时,指定装载器,不使用devtools
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(
Thread.currentThread().getContextClassLoader()
);
mybatis整合redis缓存
自定义cache类
1 public class MybatisRedisCache implements Cache { 2 private static Logger LOGGER = LoggerFactory.getLogger(MybatisRedisCache.class); 3 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 4 private String id; 5 private Jedis redisClient = createReids(); 6 7 public MybatisRedisCache(final String id) { 8 if (id == null) { 9 try { 10 throw new IllegalAccessException("Cache instances require an ID"); 11 } catch (IllegalAccessException e) { 12 e.printStackTrace(); 13 } 14 } 15 LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id); 16 this.id = id; 17 } 18 19 private static Jedis createReids() { 20 JedisPool jedisPool = new JedisPool("127.0.0.1", 6379); 21 return jedisPool.getResource(); 22 } 23 24 @Override 25 public String getId() { 26 return this.id; 27 } 28 29 @Override 30 public void putObject(Object key, Object value) { 31 LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value); 32 redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value)); 33 } 34 35 @Override 36 public Object getObject(Object key) { 37 Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString()))); 38 LOGGER.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value); 39 return value; 40 } 41 42 @Override 43 public Object removeObject(Object key) { 44 return redisClient.expire(SerializeUtil.serialize(key.toString()), 0); 45 } 46 47 @Override 48 public void clear() { 49 redisClient.flushDB(); 50 } 51 52 @Override 53 public int getSize() { 54 return Integer.valueOf(redisClient.dbSize().toString()); 55 } 56 57 @Override 58 public ReadWriteLock getReadWriteLock() { 59 return readWriteLock; 60 } 61 }
序列化和反序列化
1 public class SerializeUtil { 2 3 public static byte[] serialize(Object object) { 4 ObjectOutputStream oos = null; 5 ByteArrayOutputStream baos = null; 6 try { 7 // 序列化 8 baos = new ByteArrayOutputStream(); 9 oos = new ObjectOutputStream(baos); 10 oos.writeObject(object); 11 byte[] bytes = baos.toByteArray(); 12 return bytes; 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 return null; 17 } 18 19 public static Object unserialize(byte[] bytes) { 20 ByteArrayInputStream bais = null; 21 try { 22 // 反序列化 23 bais = new ByteArrayInputStream(bytes); 24 ObjectInputStream ois = new ObjectInputStream(bais); 25 return ois.readObject(); 26 } catch (Exception e) { 27 // e.getCause().equals(NullPointerException.class); 28 // e.printStackTrace(); 29 } 30 return null; 31 } 32 }
mapper.xml文件中配置
<cache eviction="LRU" type="com.example.demo.util.MybatisRedisCache"/>
常用的淘汰算法:
FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。
Redis提供的淘汰策略:
noeviction:达到内存限额后返回错误,客户尝试可以导致更多内存使用的命令(大部分写命令,但DEL和一些例外)
allkeys-lru:为了给新增加的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC)。
volatile-lru:为了给新增加的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC),但只限于过期设置键。
allkeys-random: 为了给新增加的数据腾出空间,驱逐任意键
volatile-random: 为了给新增加的数据腾出空间,驱逐任意键,但只限于有过期设置的驱逐键。
volatile-ttl: 为了给新增加的数据腾出空间,驱逐键只有秘钥过期设置,并且首先尝试缩短存活时间的驱逐键