springboot集成redis
上一篇是关于redis介绍的文章,这里不重复赘述了。快速通道
之前有讲过如何快速创建springboot
项目,这里也不重复赘述了。快速通道
找到springboot的配置文件
,添加配置,这里使用的是application.properties
,application.yml
类似
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait= 3000ms
#连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout= 3000ms
此处使用的是stringredistemplate
,也是比较常用的,还有redistemplate
StringRedisTemplate
继承了RedisTemplate
。RedisTemplate
是一个泛型类,而StringRedisTemplate
则不是。StringRedisTemplate
只能对key=String,value=String
的键值对进行操作,RedisTemplate
可以对任何类型
的key-value
键值对操作。序列化
的方式不同,但最终都是得到了一个字节数组,殊途同归,StringRedisTemplate
使用的是StringRedisSerializer
类;RedisTemplate
使用的是JdkSerializationRedisSerializer
类。反序列化,则是一个得到String
,一个得到Object
这个utils
是从网上找的,也比较全面->RedisUtils
因为代码比较多,所以我放在了第三方渠道里面,点击文章最下方阅读原文,获取最新代码
这里只做一个简单的取值赋值演示
,详细的使用,相信各位大大,看了本文涉及到的几篇文章,再看RedisUtils代码,自己能找到
适用的数据结构
和配套的连接方式
package com.yxj.spring.controller;
import com.yxj.spring.utils.RedisUtils;
import com.yxj.spring.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @version v1.0
* @Copyright(c): 2020-2020
* @FileName: RedisTestController.java
* @Description:
* @autho Admin
* @date 2020/1/17 13:55
*/
@RestController
@RequestMapping("/test")
public class StringRedisTestController {
@Autowired
private RedisUtils redisUtils;
@PostMapping("/redis")
public String updateRedis(User user){
redisUtils.set(user.getId(),user.getUserName());
return "success";
}
@GetMapping("/redis/{key}")
public String insertRedisTest(@PathVariable String key){
return redisUtils.get(key);
}
}
redis事物
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证
EXEC
命令前被放入队列缓存。EXEC
命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。一个事务从开始到执行会经历以下三个阶段
以下是一个事务的例子, 它先以 MULTI
开始一个事务, 然后将多个命令加入到事务中, 最后由 EXEC
命令触发事务, 一并执行事务中的所有命令
单个 Redis
命令的执行是原子性的,但 Redis
没有在事务上增加任何维持原子性的机制,所以 Redis
事务的执行并不是原子性
的。
事务可以理解为一个打包的批量执行脚本,某个脚本指令执行失败,不会导致前面做的操作回退和影响后面的指令运行
可以观看下图操作,set b
很明显是失败的,但是set a
和 set c
操作还是成功了
DISCARD
取消事务,放弃执行事务块内的所有命令。EXEC
执行所有事务块内的命令。MULTI
标记一个事务块的开始。UNWATCH
取消 WATCH 命令对所有 key 的监视。WATCH key [key ...]
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。redis缓存穿透和
PS:以下有个人理解,但是本人没有做过这种处理,只是看文章总结出来的内容,不保障效果,如果有错误,还请各位大佬指正!
通常我们使用缓存存储某条记录,流程是先根据key
查询redis
,如果redis
不存在,查询数据库,再同步至redis
,如果每次都给定一个不存在的key
那么redis
无存在的意义,没有一点作用,这个叫做缓存穿透
网上给出了两种
解决方案
对所有可能查询的参数以hash
形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力;
我的理解
ID
,进行处理,处理后放入redis
redis
查询不到,准备从数据库查询前,先查询该条记录ID可不可能存在redis
操作redis
和数据库都没有通过key查询到数据,将返回的空对象也存储起来key->null
,之后再次访问,直接就返回了null
,需要设置过期时间,推荐1-2
分钟内,具体视业务而定
我的理解
这个其实相对比较容易理解,就是保障一段时间,这个不存在结果的key
,不会一直访问数据库,当然,这种数据如果多了,想想都可怕,全是key->null
如果本来之前没有的key
,突然存在了,再次查询走缓存,返回的null
是不是与数据库就不一致了呢?这里可能需要再多做业务处理
缓存击穿,是指一个key
非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务,比如 Redis Sentinel
和 Redis Cluster
都实现了高可用。
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key
只允许一个线程查询数据和写缓存,其他线程等待。
可以通过缓存reload
机制,预先去更新缓存,即将发生大并发访问前手动触发加载缓存不同的key
,设置不同的过期时间,让缓存失效的时间点尽量均匀。
在缓存更新或者过期的情况下,先获取锁,在进行更新或者从数据库中获取数据后,再释放锁,需要一定的时间等待,就可以从缓存中继续获取数据。
要不就设置永不过期吧,哈哈哈哈哈,省时省力