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>
### 事务
```java
Transaction 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
换为了lettuce
RedisTemplate
RedisTemplate是Spring框架对Jedis API的进行了高度封装,支持连接池自动管理,我们可以在Spring应用中通过简单的连接池配置信息就能访问Redis服务并进行相关缓存操作
- 默认提供了两个使用Redis的类
StringRedisTemplate
和RedisTemplate
RedisTemplate
可以支持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: 0
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制) 默认 8
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-wait: -1ms
# 连接池中的最大空闲连接 默认 8
max-idle: 8
# 连接池中的最小空闲连接 默认 0
min-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)
@EnableCaching
public class RedisConfig {
@Bean
public 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
@Autowired
private StringRedisTemplate stringRedisTemplate; //字符串存储
@Autowired
private 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
@Bean
public 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官方的布隆实现,能对字符串也进行存读
@Bean
public 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;
@Id
private Long id;
private String userName;
private String password;
private String email;
}
创建
Repository
接口@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}