jedis
jdeis是redis官方推出的连接redis的客户端,貌似自带了redis驱动
导入依赖
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency>
建立连接并使用
redis操作极其简单,建立一个连接对象,连接对象便可以通过各种方法直接操作
- redis不像mysql一样可以有多个用户,多个连接。一个redis服务就一个用户,即一个连接。所以配置下url和密码即可
- 通过java操作redis插入的中文是可以正确显示和插入中文的,而在
redis-cli中不配置插入的中文是乱码或者是\x??形式的编码 - redis方法用法跟命令几乎一模一样的用法 ```java Jedis jedis = new Jedis(“localhost”,[Integer port]); //连接本地的 Redis 服务 port不传就cao’y jedis.auth(“password”); //如果设置了密码则配置密码 System.out.println(“服务状态: “+jedis.ping()); //正常返回为:PONG
//字符串 jedis.set(“name”,”饶泽东”); jedis.get(“name”);
//删除键值对 jedis.del(“name”);
//哈希
hmset(String , Map
//list
lpush(“键”,String …); //…即是可变参数列表
List
//set
sadd(“键”,String …)
Set
//zset zadd(“键”, double, “值”)
jedis.close();
<a name="oakho"></a>### 事务```javaTransaction multi=jedis.multi(); //开启事务try{multi.set("name","rzd"); //一系列入队命令...multi.exec(); 执行事务} catch(Exception e){multi.discard();} finally{jedis.close();}
spring-data-redis
springboot1.x时spring-data-redis的底层实现 是jedis,2.x换为了lettuceRedisTemplate
RedisTemplate是Spring框架对Jedis API的进行了高度封装,支持连接池自动管理,我们可以在Spring应用中通过简单的连接池配置信息就能访问Redis服务并进行相关缓存操作
- 默认提供了两个使用Redis的类
StringRedisTemplate和RedisTemplateRedisTemplate可以支持Redis没有的缓存对象的操作- 而
StringRedisTemplate用来存储字符串
- 默认提供了两个使用Redis的类
jedis每次使用都会创建一个连接,不节省资源。同时jedis是单线程操作的,多线程使用有隐患
Lettuce:一个基于Netty的高性能Redis客户端。
lettuce依赖于commons-pools@ConditionalOnClass表明redisTemplate是可以自定义的
- 默认绑定的配置文件名为RedisProperties
- RedisProperties是个实体配置类,开头有
@ConfigurationProperties(prefix="spring.redis")表明会寻找配置文件里spring.redis.?的配置进行注入
springboot中使用redis
Lettuce的Timed out问题
- 在 Spring Boot 2.x 默认使用 Lettuce 之后,会偶发性出现
Redis command timed out问题,从而导致客户端(Java 代码)无法连接到 Redis Server 的问题。 - 这种问题无法正面解决,只能放弃使用
Lettuce,springboot2.x情况下需要手动排除 spring-data-redis 对 Lettuce 的依赖,并引入 Jedis 依赖配置
```yaml spring.redis.host=127.0.0.1 spring.redis.port=6379 #使用默认端口时无需配置 spring.redis.database=0 #指定使用的分区片,使用默认片时无需配置 spring.redus.password=
整合了lettuce的详细配置
spring: redis: host: localhost
# 连接超时时间(记得添加单位,Duration)timeout: 10000ms# Redis默认情况下有16个分片,这里配置具体使用的分片# database: 0lettuce:pool:# 连接池最大连接数(使用负值表示没有限制) 默认 8max-active: 8# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1max-wait: -1ms# 连接池中的最大空闲连接 默认 8max-idle: 8# 连接池中的最小空闲连接 默认 0min-idle: 0
cache:
# 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配type: redis #配置缓存的实现
<a name="BKdKo"></a>## 引入依赖```java<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 对象池,使用redis时必须引入,lettuce使用commons-pool2创建redis连接池 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions> <!-- 从依赖关系中排除 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>
使用Template与配置bean
- 其实
StringRedisTemplate也是继承自RedisTemplate,所以RedisTemplate也可以 操作字符串 - 更多见链接
重写RedisTemplate
- 在RedisAutoConfigiration中
RedisTemplate<T,T>2个泛型均为Object类型,Object最后还是尝试序列化为String写入。而我们需要实现redis自动序列化和反序列化,这样更加方便- 第一个T代表键值,我们重写时应该为String,否则直接传字符串对象会出现键值除了字符串值还有对象信息
- 第二个T设置为
Serializable/Object,通过jackson等工具序列化可以避免乱码,默认的jdk序列化的结果还是特殊编码字符串
实体类必须实现序列化接口,同时引入一个序列化工具,推荐jackson。
public class User implements Serializable{...}
@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)@EnableCachingpublic class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();//配置键的序列化方式,传一个RedisSerializer的实现类对象即可,下面也可以2个都传jackson,stringredisserializer不清楚是哪种序列方式template.setKeySerializer(new StringRedisSerializer());//配置值的序列方式template.setValueSerializer(new GenericJackson2JsonRedisSerializer());//配置连接方式 这里跟上面一样,传个连接接口实现类对象,这里我们传lettuce连接池对象template.setConnectionFactory(redisConnectionFactory);return template;}}
redisTemplate使用
不存在的key获取为null

@Autowiredprivate StringRedisTemplate stringRedisTemplate; //字符串存储@Autowiredprivate RedisTemplate<String, Object> redisCacheTemplate; //对象操作//----------------操作基本类与集合类-----------stringRedisTemplate.opsForValue().set("k1", "v1"); //字符串操作String k1 = stringRedisTemplate.opsForValue().get("k1");redisCacheTemplate.opsForValue().set(键名, T); //Map操作T t=(T) redisCacheTemplate.opsForValue().get(键名);redisTemplate.opsForList().leftPushAll("list", "rzd");redisTemplate.opsForList().leftPushAll("list", "lhy");List<Object> S= listOps.range("listcollection4",0,-1);对于list等多元素集合,直接传入序列化集合对象不会对每个元素依次插入,而是插入一个包含所有元素的字符串。暂时不清楚怎么把一个多元素集合插入为正确的格式//-----------------设置时效-----------------------opsForValue().getOperations().getExpire(键); 获取剩余时间,-2为不存在或者已过期(已过期即一般不存在被清空),-1为存在但是未设置过期时间//-----------------删除key------------redisTemplate.delete("key)
RedisConnection conn=redisTemplate.getConnectionFactory.getConnection();//连接较为少用,一般用于操作redis数据库,如conn.flushDb();conn.flushAll();
注解使用缓存
- 借助
spring cache实现对缓存操作。核心注解为@Cacheable、@CachePut和@CacheEvict这几个注解根据入参与返回值以实现缓存与方法内部数据的一致性,使用方法的同时也会自动操作缓存 -
配置类
在redisTemplate的配置类中追加如下配置bean
@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {// 配置序列化RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();}
使用
有三个操作注解,value参数为命名空间,key为键名。注解就相当于一个操作方法。下面注解都支持spEl表达式。具体使用参考springboot教程电子书
@CacheEvict删除@Cacheable查询 如果缓存存在这个key,则不执行方法直接走缓存。否则走方法,并在方法返回时将结果也存入缓存。@CachePut增加/更新 不管是否存在这个key,都会执行方法,有时使用该注解仅仅是表明该方法支持缓存 cacheput和cacheable的注解参数是相同的
- 官方强烈不推荐将 @Cacheable 和 @CachePut 注解到同一个方法。
- 注解方式会生成一个命名空间,里面存不同的东西。只有一个元素时就显示为
命名空间::键

这里表示键名为user@CachePut(value = "user", key = "#user.id")public void saveOrUpdate(User user) { }@Cacheable(value = "user", key = "#id") //对应多个键时使用数组:{"a","b"},还可以设置条件,条件为true时才会进行缓存public User get(Long id) { new User(); }@CacheEvict(value = "user", key = "#id")public void get(Long id) {}
redis实现session共享
- 集群环境下session共享本质还是一个缓存环境对应多个服务,只不过多了几个备用的redis机子
首先需要导入依赖,这个依赖的作用是添加分布式session共享的支持,暂时还不是很清楚
依赖
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency
配置类
@Configuration@EnableRedisHttpSession//可以配置session的失效时间@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60)public class RedisSessionConfig{//...}
使用注解
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60) /整合布隆过滤器
首先导入google提供的
guava,里面有个布隆链接 可以使用redis官方的布隆实现,能对字符串也进行存读
@Beanpublic BloomFilter initBloomFilter() {BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(), 1500, 0.01);return filter;}
*Redis Repositories
Spring Data Redis 从 1.7 开始提供 Redis Repositories功能 ,可以无缝的转换并存储实体类。使用哈希类型存储实体类
- 即一个实体类对应一个redis中的键值对,该键值对可以存储很多该类对象
spring Data Redis的Repository的基本实现为:CrudRepository
- 个人猜测spring cache存储于redis中的结果和这个Repositories是一样的,都是
?:数字的形式 感觉不是很实用,每种类都要实现一个接口,不如直接使用自动序列化存入redis里面
启用Repositories
使用
@EnableRedisRepositories(basePackages = "...")@RedisHash表示将 User 类的对象都对应 Redis 中的键名为user的 Set,每个Set里可以存储多个该实体类对象。此时每个对象的key为user:<Id>,如user:1- 获取该redis键值对中某个对象的属性
hget user:1 username
- 获取该redis键值对中某个对象的属性
@Id:标注于实体类的唯一标识字段上@RedisHash("user")public class User implements Serializable {private static final long serialVersionUID = 1L;@Idprivate Long id;private String userName;private String password;private String email;}
创建
Repository接口@Repositorypublic interface UserRepository extends CrudRepository<User, Long> {}
