前言:本文为原创 若有错误欢迎评论!
一.Redis的数据结构
1.String:
- set/get(基本操作)
set key value
get key
- mset(一次存入多个)
mset key1 value1 key2 value2
- mget(一次取出多个)
mget key1 key2 key3
- incr(每次value必须是数字 等同i++)(是原子性的 线程安全的 可以搭配lua脚本保证完全一起执行)
incr key
- incrby(每次增加指定的值)
incrby key incrNum
- decr(每次value必须是数字 相当i–)(是原子性的 线程安全的 可以搭配lua脚本保证完全一起执行)
decr key
- decrby(每次减少指定的值)
decr key decrNum
- setnx(如果不存在这个key就存入 返回值为 1:成功,0:失败)
setnx key value
- msetnx(存入多个 如果不存在就存入)
mset key1 value1 key2 value2
- setex(给key可以设置过期时间 单位是秒)
setex age second value
- getset(存入新值并返回旧值)
getset key value
- getrange(获取字符串value的指定长度 相当于字符串函数substr)
getrange key startpos lenth
- append(给指定的key拼接字符串 返回长度)
append key value
2.Hash:
- Hash的数据结构:Map<String,Map<String,String>> (即一个key对应多个filed 一个filed对应一个key)
- hset/hget(基本操作)
hset key filed1 value
hset key filed2 value
hget key filed
- hgetall(打印key对应的所有value)
hgetall key
- hmset(一次放入多个)
hmset key1 filed1 value1 key2 filled 2 value2
- hmget(一次取多个filed多赢的值)
hmget key1 filed1 key2 filed2
- hlen(一个key对应了多少对filed)
hlen key
- hdel(删除一个filed)
hdel key filed
3.List
- lpush(从第一个值开始压栈 是栈结构 先进后出)
lpush key value1 value2
- lrang(取指定下标的值 0 -1 表示取全部)
lrange key 0 -1
lrange key startpos num
- lpop(抛出栈顶(即最后一个存入的)并返回该值)
lpop key
- rpush(将值压入栈底)
rpush key value
- rpop(抛出栈底的值)
rpop key
- llen(list的长度)
llen key
- lindex(只获取key第num个元素)
lindex key num
- lrem(删除第num个元素)
lrem key num
4.Set
- 底层是HashMap 一个key对应的多个value没有重复的
- sadd(添加)
sadd key value1 value2 value3
- smembers(取全部的值)
smembers key
- spop(随机抛出一个元素 并返回该值)
spop key
- sdiff(获得前面set不存在于后面set的元素)
sdiff set1 set2
- sunion(获得两个set的并集)
sunion set1 set2
- sinter(获得两个set的交集)
sinter set1 set2
5.SortSet
- 对set的基础进行score,再根据score进行排序
- zadd(添加)
zadd key socer1 obj1 socer2 obj2
- zrange(递增排序,即由小到大排序后,取 [start 下标 , stop 下标]所有元素 )
zrange key 0 -1 # 说明,-1 代表取全部元素
zrange key start stop [withscores] # 说明,withscores 代表是否显示分数
- zrevrang (递减排序,即由大到小排序后,取 [start 下标 , stop 下标]所有元素 )
zrevrang key start stop [WITHSCORES]
- zrangebyscore(通过score获得在一个范围内的obj)
zrangebyscore key min max
- zrank(获得指定 obj 的排名 从小到大的顺序 最小值返回的排名是0)
zrank key obj
- zrevrank(获得指定 obj 的排名 从大到小的顺序 最小值返回的排名是0)
zrevrank key obj
- zcard(查看有多少个元素)
zcard key
- zsocer(获得 obj 的分数)
zsocre key obj
- zrem(删除对应obj 的值)
zrem key obj
二.Redis其他命令
1.消息发布订阅
- PUBLISH(将消息发送到指定的channel 并返回客户端数量)
PUBLISH channelName message
- SUBSCRIBE(订阅指定的channel的消息)
SUBSCRIBE channelName
- UNSUBSCRIBE(取消订阅 如果不指定channel 则取消全部订阅)
UNSUBSCRIBE channelName
2.Redis事务
- MULTI(开启事务 之后每执行一个命令都放进队列并返回QUENE)
MULTI
- EXEC(执行所有命令 并返回队列中任务的执行结果)
EXEC
- DISCARD(清空队列中所有任务)
DISCARD
- WATCH(在MULIT开启事务之前使用 如果多端口修改了被WATCH的值 则事务提交失败)
WATCH key
三.SpringBoot整和redis
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.在根目录新建RedisConfig.java 并注解【@Configuration】
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String,String>();
redisTemplate.setConnectionFactory(factory);
/**
* 定义好三种序列化方式:Jackson序列化、Jdk序列化、String序列化
*/
/**Jackson序列化 json占用的内存最小 */
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
/**Jdk序列化 JdkSerializationRedisSerializer是最高效的*/
// JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
/**String序列化*/
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
/**
* 设置不同数据类型的序列化方式
* /
/**将key value 进行stringRedisSerializer序列化*/
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
/**将HashKey HashValue 进行序列化*/
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
3.RedisTemplate常用方法
- redisTemplate.opsForValue()
//返回操作string类型的Operations
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
- redisTemplate.expire()
//setnx 设置超时时间
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
redisTemplate.delete(key); //删除一个key
-
redisTemplate.hasKey(key); //检查是否存在一个key
-
redisTemplate.opsForHash()
//返回操作hah类型的Operations
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key, hashKey, value);
- redisTemplate.opsForSet()
//返回操作set类型的Operations
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key, value)
- redisTemplate.opsForZSet()
//返回操作zset类型的Operations
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key, value, scoure)
//有序集合获取排名
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
Set<ZSetOperations.TypedTuple> ret = zset.rangeWithScores(key,start,end);
- 注意:
所有对元素的增删改查都不是直接用RedisTemplate的方法 用都是的RedisTemplate返回的"Operations"的方法 且五种类型的方法各不相同
四.Redis作为springBoot二级缓存
1.依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.在applicaton.yml中配置好redis的连接
spring.redis.database=0
#Redis服务器地址
spring.redis.host=xxx.xxx.xxx.xxx
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=xxx
3.给启动类加注解启动二级缓存:
@EnableCaching
4.在根目录新建RedisConfig.java:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String,String>();
redisTemplate.setConnectionFactory(factory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
/**Jackson序列化 json占用的内存最小 */
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
/**Jdk序列化 JdkSerializationRedisSerializer是最高效的*/
// JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
/**String序列化*/
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//设置序列化类型
/**将key value 进行stringRedisSerializer序列化*/
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
/**将HashKey HashValue 进行序列化*/
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
//注入redis中key的生成方式 到时可以在方法的注解上直接调用
@Bean
public KeyGenerator simpleKeyGenerator() {
return (o, method, objects) -> {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(o.getClass().getSimpleName());
stringBuilder.append(".");
stringBuilder.append(method.getName());
stringBuilder.append("[");
for (Object obj : objects) {
stringBuilder.append(obj.toString());
}
stringBuilder.append("]");
return stringBuilder.toString();
};
}
//配置CacheManager
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
this.getRedisCacheConfigurationWithTtl(600), // 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationMap() // 指定 key 策略
);
}
//自定缓存策略
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
/**
*可以通过@Cacheable、@CachPut、@CachEvict注解中的value找到对应方法 然后设置过期时间
*/
redisCacheConfigurationMap.put("在使用Cach注解的方法的value", this.getRedisCacheConfigurationWithTtl(100));//单位是秒
redisCacheConfigurationMap.put("在使用Cach注解的方法的value", this.getRedisCacheConfigurationWithTtl(18000));
return redisCacheConfigurationMap;
}
//给自定缓存策略设置序列化方式以及过期时间
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
//设置序列化方式
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds)); //设置过期时间
return redisCacheConfiguration;
}
}
5.给要开启二级缓存的类注解
@CachConfig(cachNames=" ")
注意:该注解时为了在redis存储时设置名字前缀 如果每个方法的的Cach相关注解有value的话可以不用在类上加该注解
6.给要开启的方法注解(该方法必须有返回值)
@Cacheable(value=" ",keyGenerator=“simpleKeyGenerator”)
每次更新缓存前查询是否缓存中已经存在 不存在才执行该方法 并且将返回值刷新为本次执行的返回值
@CachPut(value=" ",keyGenerator=“simpleKeyGenerator”)
每次都执行 不管缓存中是否存在
@CachEvict(value=" ",keyGenerator=“simpleKeyGenerator”)
删除缓存名为simpleKeyGenerator拼接后得到的key对应的value
注意:
- 不使用(value=" “,keyGenerator=“simpleKeyGenerator”)这个组合配置key
如果只用(key=”#p下标"+"#p下标".字段名)所得的key是“cacheNames的值::对应下标参数的值)很容易重复 还有下标从0开始 - 注解中value的值用于在自定缓存策略时找到对应的方法 在设置好value之后 可以去修改getRedisCacheConfigurationMap()那里 加入该方法
- key的生成方式simpleKeyGenerator 是前面配置中注入的生成方式
- 如果不想返回的空值更新到会缓存里 注解里加一条”unless="#result==null“
五.分布式session
1.原因:
-
因为每个浏览器和服务器建立连接之后都会有一个session 然后可以给session里面添加值来作一些验证,但是每个session默认存储在访问的服务器的内存中 如果分布式多机器部署的话一个连接会产生多个session 所以把所以session都保存在redis中
-
引入依赖并配置之后 springboot会自己把创建的session保存在redis 每次通过request获取session也会从redis中获取 而不是本机内存
-
并且每次访问服务器都会自动把过期时间重置为初始值
注意:
如果是前后端分离跨域就不适用,可以通过:- 手动放入(key: 唯一标识的token、value: User信息),每次获取也要手动从redist获取
- 或者使用shiro+redis 生成分布式session ( 配置其SessionManger )
登陆成功之后才生成session 用 Session session = SecurityUtils.getSubject().getSession() 获得session 但没有登陆就没subject 将空指针异常
2.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-session-data-redis</artifactId>
</dependency>
3.使用:
给启动类加注解
@EnableHttpSession(maxInactiveIntervalInSeconds= 过期时间(单位:秒))
注意:
- session-data-redis的分布式session:只要连上服务器就会把session缓存到数据库
- shiro+redis的session的分布式session:登陆成功才有