Spring Data Redis
Jedis是使用最多的Redis的Java客户端,这种使用方式属于裸用,直接通过Jedis操作Redis特性
主要有:
- 基本使用
- 连接池的使用
- 高可用连接
- 客户端分片
基本使用
单线程下使用
@Component public class RedisClientUtil { @Value("${spring.redis.host:localhost}") private String host; @Value("${spring.redis.port:6379}") private Integer port; private final byte[] tmp_lock = new byte[1]; private Jedis jedis; private RedisClientUtil(){} public Jedis getRedisClient(){ if (jedis == null){ synchronized (tmp_lock){ if (jedis == null){ jedis = new Jedis(this.host,this.port); } } } return jedis; } }
测试代码:
@Autowired private RedisClientUtil redisClientUtil; @Test public void testJedis() { Jedis jedis = redisClientUtil.getRedisClient(); try { jedis.set("user1", "admin"); System.out.println(redisClientUtil.getRedisClient().get("user")); } catch (Exception e) { e.printStackTrace(); }finally { // 注意关闭 jedis.close(); } }
连接池的使用
在多线程的环境下,引用连接池的概念帮我们管理各个连接
@Component public class RedisClientUtil { @Value("${spring.redis.host:localhost}") private String host; @Value("${spring.redis.port:6379}") private Integer port; private final byte[] tmp_lock = new byte[1]; private JedisPool jedisPool; private RedisClientUtil(){} private JedisPool getRedisClient(){ if (jedisPool == null){ synchronized (tmp_lock){ if (jedisPool == null){ jedisPool = new JedisPool(jedisPoolConfig(),this.host,this.port); } } } return jedisPool; } /** * 获取Jedis * @return */ public Jedis getJedis(){ return getRedisClient().getResource(); } private JedisPoolConfig jedisPoolConfig(){ JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(20); jedisPoolConfig.setMaxIdle(10); jedisPoolConfig.setMaxWaitMillis(1000); return jedisPoolConfig; } }
测试例子:
@Test public void testJedis() { Jedis jedis = redisClientUtil.getJedis(); try { jedis.set("user1", "admin"); System.out.println(jedis.get("user")); } catch (Exception e) { e.printStackTrace(); }finally { // 注意关闭 jedis.close(); } }
高可用连接(master/salve)
Jedis提供哨兵机制的使用
public static void main(String[] args) { HashSet<String> hashSet = new HashSet<>(); hashSet.add("localhost:6379"); hashSet.add("localhost:6378"); hashSet.add("localhost:6377"); JedisSentinelPool pool = new JedisSentinelPool("redis_master_name", hashSet); Jedis jedis = pool.getResource(); try { jedis.set("user","user"); String val = jedis.get("user"); assert val.equals("user"); } catch (Exception e) { e.printStackTrace(); }finally { jedis.close(); } }
客户端分片:
public static void main(String[] args) { List<JedisShardInfo> shards = new ArrayList<>(); shards.add(new JedisShardInfo("localhost:6379")); shards.add(new JedisShardInfo("localhost:6378")); shards.add(new JedisShardInfo("localhost:6377")); ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(),shards); ShardedJedis jedis = pool.getResource(); try { jedis.set("user","user"); String val = jedis.get("user"); assert val.equals("user"); } catch (Exception e) { e.printStackTrace(); }finally { jedis.close(); } }
Jedis 在实际工作中的正确使用场景
最常见的就是对Service这层的数据加缓存
做法1:
在Service方法中,在得到数据之前,先判断缓存里面有没有通过显示调用JedisUtil类,如果没有就从DB层去获取,再放入Redis中,在更新的时候显示调用JedisUtil去更新缓存,这回出现大量冗余代码
做法2:
自定义一个注解,放在每个方法上,有更新、添加的缓存注解,利用@Aspect拦截机制,调用JedisUtils在拦截器里面处理上下文
Spring Data Redis
# reids 服务器地址 spring.redis.host=localhost # 端口 spring.redis.port=6379 # 连接等待超时时间,毫秒 spring.redis.timeout=6000 # 连接池,最大活跃数 spring.redis.jedis.pool.max-active=8 # 连接池,最大空闲数 spring.redis.jedis.pool.max-idle=8 # 连接池,最大等待时间 spring.redis.jedis.pool.max-wait=-1 # 连接池,最小空闲活动链接数 spring.redis.jedis.pool.min-idle=0
简单实用例子
@Autowired private static RedisTemplate redisTemplate; @Test public void testSDR(){ redisTemplate.opsForSet().add("user","admin"); }
哨兵高可用配置
# 哨兵的 master 名称 spring.redis.sentinel.master=redis_master # 哨兵地址 spring.redis.sentinel.nodes=localhost:6379,localhost:6378,localhost:6377
集群分布式切片配置
# 在集群中执行命令时要遵循的最大重定向数 spring.redis.cluster.max-redirects=3 # 集群节点列表 spring.redis.cluster.nodes=localhost:6379,localhost:6378,localhost:6377
调用案例
在实际使用中无论是 RedisTemplate 还是 ValueOperatoration、HashOperation都是可以的
// set 的使用 @Autowired private RedisTemplate<String,String> redisTemplate; @Test public void testSDR(){ Set<String> sets = this.redisTemplate.opsForSet().members("user1"); System.out.println(sets); if (!sets.isEmpty()){ sets.forEach(val->this.redisTemplate.opsForSet().remove("user1",val)); } this.redisTemplate.opsForSet().add("user1","admin","user","employee"); } // Key-val 的使用 @Resource(name = "redisTemplate") public ValueOperations<String,String> vops; @Test public void testVops(){ String string = vops.get("user"); System.out.println(string); vops.set("user","admin"); } // hash的使用 @Resource(name = "redisTemplate") private HashOperations<String,String,Object> hashOps; @Test public void testHashOps(){ // 写入hash Map<String,Object> map = new HashMap<>(); map.put("value","code"); map.put("key","keyValue"); hashOps.putAll("myhash",map); // 读取hash Object value = hashOps.get("myhash","value"); Object key = hashOps.get("myhash","key"); System.out.println(value); System.out.println(key); // 删除hash hashOps.delete("myhash","value","key"); }
操作总结
redisTemplate.opsForValue(); // 操作字符串 redisTemplate.opsForHash(); // 操作 hash redisTemplate.opsForList(); // 操作 list redisTemplate.opsForSet(); // 操作 set redisTemplate.opsForZSet(); // 操作 有序set
Spring Cache
@Cacheable 注解
应用到读取数据的方法上,如查询方法:先从缓存中读取,如果没有,则调用方法获取数据,然后将数据加入到缓存中
public @interface Cacheable { @AliasFor("cacheNames") String[] value() default {}; // cache的名称,根据名称设置不同cache处理类,Redis里面可以根据cache名字设置不同的失效时间 @AliasFor("value") String[] cacheNames() default {}; // 缓存key的名称,支持spel String key() default ""; // key生成策略,不指定则使用全局默认 String keyGenerator() default ""; // 选择不同的CacheManager String cacheManager() default ""; // 配置不同的 cache resolver String cacheResolver() default ""; // 满足什么样的条件才能被缓存,支持spel,可以获取到方法名和方法参数 String condition() default ""; // 排除那些返回结果不加入到缓存里面去,支持spel,常见的是 result == null 等 String unless() default ""; // 是否同步读取、更新缓存 boolean sync() default false; }
@CachePut
调用方法时会自动把响应的数据放入缓存,与@Cacheable不同的是所注解的方法每次都会执行,一般配置到Update和Insert方法上
@CacheEvict
public @interface CacheEvict { // 与@Cacheable 相同的部分 略.... // 是否删除所有的实体对象 boolean allEntries() default false; // 是否方法执行之前执行,默认在方法调用成功后删除 boolean beforeInvocation() default false; }
@Caching
所有Cache注解的组合配置方法
public @interface Caching { Cacheable[] cacheable() default {}; CachePut[] put() default {}; CacheEvict[] evict() default {}; }
@CacheConfig
全局Cache配置
@EnableCaching
开启SpringCache默认配置

浙公网安备 33010602011771号