1.认识两个工具类
2.开发中使用场景以及注意事项
2.1业务逻辑编写中的使用
2.1.1使用Demo
- 同事A要写一个用户查询接口,入参是用户的id,出参是一个用户信息
- 同事A编写完成,Controller->Service->DAO(Mapper)
①Controller层
@RestController
public class TestRedisController {
@Autowired
private SysUserService sysUserService;
@RequestMapping("getSysUser")
public SysUser getSysUser(long id){
return sysUserService.getSysUserById(id);
}
}
②Service层
@Service
public class SysUserService {
@Autowired
private SysUserMapper sysUserMapper;
public SysUser getSysUserById(long id){
return sysUserMapper.getUserById(id);
}
}
③Dao层
@Repository
public interface SysUserMapper {
SysUser getUserById(long id);
}
同事A编写完成后,老大要求对此接口引入缓存来加快二次查询的效率,同事A求助同事B,同事B用了2秒种完成了老大的需求,改动如下:
@Repository
public interface SysUserMapper {
@Cacheable(value="user",key = "#id")
SysUser getUserById(long id);
}
4.同事A成功的完成的任务,但是他不明白@Cacheable注解的含义,于是同事B告诉他:
- @Cacheable注解标注到方法上
- 首次执行被@Cacheable标注的注解,该方法的返回值(这里SysUser对象)会被缓存进入Redis
- 注解中的value指明是最终key值的前缀,注解中的key值指明拼接在前缀后面的值,#id就是参数id值,注解中key值的指明规则可以查看 https://blog.csdn.net/newbie_907486852/article/details/81478046
- 对于c的解释可能有点模糊,直接举例:我查询一个 id=1的用户信息,那么redis中会为我记录如下的信息: key为
user:1
,value 为 id=1的用户信息。
5.开发中可能还会删除redis缓存,因此可以查看 其他的缓存注解 ,相关博客同上
2.1.2关于key过期时间的配置
- 场景:对于查询对象的key-value对,可能要求的过期时间是不一样的
配置方式
yurun:
cache-manager:
configs:
- key: menu
second: 300
- key: user
second: 1800
- key:xxxx
second: xxx
上述配置中我们查看第二个
key=user second=1800
的
①含义解释:通过注解的方式设置缓存的,前缀为 user的 所有key -value对的 过期时间是1800s
②结合2.1.1来说,就是我的sysUser只保存1800s
2.2分布式锁的使用
分布式锁的封装方法在RedissonDistributedLock
类中,注入使用即可,这里的方法是对redission客户端提供的分布式锁方法的二次封装
2.2.1方法概览
方法罗列
/**
* 获取锁,如果获取不成功则一直等待直到lock被获取
* @param key 锁的key
* @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
* 如果leaseTime为-1,则保持锁定直到显式解锁
* @param unit {@code leaseTime} 参数的时间单位
* @param isFair 是否公平锁
* @return 锁对象
*/
Object lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
Object lock(String key, long leaseTime, TimeUnit unit) throws Exception;
Object lock(String key, boolean isFair) throws Exception;
Object lock(String key) throws Exception;
/**
* 尝试获取锁,如果锁不可用则等待最多waitTime时间后放弃
* @param key 锁的key
* @param waitTime 获取锁的最大尝试时间(单位毫秒)
* @param leaseTime 加锁的时间,超过这个时间后锁便自动解锁;
* 如果leaseTime为-1,则保持锁定直到显式解锁
* @param unit {@code waitTime} 和 {@code leaseTime} 参数的时间单位
* @return 锁对象,如果获取锁失败则为null
*/
Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;
Object tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception;
Object tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception;
Object tryLock(String key, long waitTime, TimeUnit unit) throws Exception;
/**
* 释放锁
* @param lock 锁对象
*/
void unlock(Object lock) throws Exception;
方法解释
①unlock:释放锁
②lock:获取锁
③trylock:尝试获取锁
④这里对②、③的区别是不是很迷惑?简单解释一下:
场景描述:这里我写两个线程,每个线程打印完自己的内容后,睡眠3s。
@Test
public void testLock() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello2");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}).start();
countDownLatch.await();
}
以上的结果一定是:hello和hello2几乎同时打印出来,但是我想让一个线程打印完后,等待3s再打印另一个。
@Autowired
RedissonDistributedLock redissonDistributedLock;
final String LOCK_KEY="mylock";
@Test
public void testLock() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
RLock lock = redissonDistributedLock.lock(LOCK_KEY);
System.out.println("hello");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
redissonDistributedLock.unlock(lock);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
RLock lock2 = redissonDistributedLock.lock(LOCK_KEY);
System.out.println("hello2");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
redissonDistributedLock.unlock(lock2);
}
}).start();
countDownLatch.await();
}
上面的代码执行结果,一定是其中一个先打印,3s后另一个才打印
2.3数据库CRUD操作的工具使用
2.3.1使用Demo
注入
RedisRepository
工具类使用即可- 简单的使用代码
@Autowired
private RedisRepository redisRepository;
@Test
public void testestRedisUtil(){
redisRepository.set("name","yurun");
redisRepository.get("name");
redisRepository.putHashValue("person","age",1);
redisRepository.getHashValues("person","age");
redisRepository.leftPush("mylist","helloworld");
redisRepository.leftPop("mylist");
redisRepository.getList("mylist",0,-1);
redisRepository.set("productNum",200);
redisRepository.incr("productNum");
}