目录
1.redis作为缓存
(1)数据存储在内存中,数据查询速度快。可以分摊数据库压力。
(2)什么样的数据适合放入缓存。
查询频率比较高,修改频率比较低。
安全系数低的数据
(3)使用redis作为缓存
package com.wzl.qy151redisspringboot.service;
import com.wzl.qy151redisspringboot.dao.DeptMapper;
import com.wzl.qy151redisspringboot.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.TimeUnit;
@Service
public class DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private RedisTemplate redisTemplate;
//业务代码
public Dept findById(Integer id){
ValueOperations forValue = redisTemplate.opsForValue();
//查询缓存
Object o = forValue.get("dept::" + id);
//缓存命中
if(o!=null){
return (Dept) o;
}
Dept dept = deptMapper.selectById(id);
if(dept!=null){
//存入缓存中
forValue.set("dept::"+id,dept,2, TimeUnit.HOURS);
}
return dept;
}
public int deleteById(Integer id){
redisTemplate.delete("dept::"+id);
int row = deptMapper.deleteById(id);
return row;
}
public Dept insert(Dept dept){
int insert = deptMapper.insert(dept);
return dept;
}
public Dept update(Dept dept){
ValueOperations forValue = redisTemplate.opsForValue();
forValue.set("dept::"+dept.getId(),dept,2, TimeUnit.HOURS);
int insert = deptMapper.updateById(dept);
return dept;
}
}
查看的缓存:前部分代码相同@before通知,后部分代码也相同后置通知。我们可以AOP完成缓存代码和业务代码分离.
spring框架应该能想到。----使用注解完成。注解该解析
(1)把缓存的配置类加入
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
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);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
(2)使用开启注解缓存注解
(3)使用注解
//业务代码
//使用查询注解:cacheNames表示缓存的名称 key:唯一标志---dept::key
//先从缓存中查看key为(cacheNames::key)是否存在,如果存在则不会执行方法体,如果不存在则执行方法体并把方法的返回值存入缓存中
@Cacheable(cacheNames = {"dept"},key="#id")
public Dept findById(Integer id){
Dept dept = deptMapper.selectById(id);
return dept;
}
//先删除缓存在执行方法体。
@CacheEvict(cacheNames = {"dept"},key = "#id")
public int deleteById(Integer id){
int row = deptMapper.deleteById(id);
return row;
}
//这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中,实现缓存与数据库的同步更新。
@CachePut(cacheNames = "dept",key="#dept.id")
public Dept update(Dept dept){
int insert = deptMapper.updateById(dept);
return dept;
}
2.分布式锁
使用测压工具测试高并发下带来线程安全问题
我们看到同一个库存被使用了n次。数据库中库存为负数,线程安全问题导致
(1)解决方案:使用synchronized或者lock锁
package com.wzl.distrinctlock.service.impl;
import com.wzl.distrinctlock.dao.ProductStockDao;
import com.wzl.distrinctlock.service.ProductStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductStockServiceImpl2 implements ProductStockService {
@Autowired
private ProductStockDao productStockDao;
@Override
public String decreaseStock(Integer productId) {
synchronized (this) {
//查看该商品的库存数量
Integer stock = productStockDao.findStockByProductId(productId);
if (stock > 0) {
//修改库存每次-1
productStockDao.updateStockByProductId(productId);
System.out.println("扣减成功!剩余库存数:" + (stock - 1));
return "success";
} else {
System.out.println("扣减失败!库存不足!");
return "fail";
}
}
}
}
使用synchronized 或者lock锁 如果我们搭建了项目集群,那么该锁无效。
使用redis开集群项目
发现又出现: 重复数字以及库存为负数。
本文含有隐藏内容,请 开通VIP 后查看