redis
redis缓存
缓存穿透
布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是 redisson实现的布隆过滤器。 它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一 开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据 的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一 个key的存在。查找的过程也是一样的。
当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置 这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增 加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能 接受,不至于高并发下压倒数据库。
缓存雪崩
双写一致
强一致性:读写锁
异步通知:
数据持久化
数据过期策略
redis的过期策略是惰性删除和定期删除配合使用
数据淘汰策略
分布式锁
主从复制
主从复制原理
哨兵模式
redis是单线程快的原因
redis业务场景自我整理
spring
考察范围
spring框架中的单列bean是线程安全的码
spring AOP详解
结果输出:
spring事务失效的原因
只有代理的类才会被切入,我们在controller层调用service的方法的时候,是可以被切入的,但是如果我们在service层 A方法中,调用B方法,切点切的是B方法,那么这时候是不会切入的,解决办法就是如上所示,在A方法中使用((Service)AopContext.currentProxy()).B() 来调用B方法,这样一来,就能切入了!
描述时可以加上应用场景,什么时候出现过事务失效
package com.hmdp.service.impl;
import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisIdWorker;
import com.hmdp.utils.UserHolder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Collections;
/**
* <p>
* 服务实现类
* </p>
*
* @author 虎哥
* @since 2021-12-22
*/
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
@Autowired
private ISeckillVoucherService seckillVoucherService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
RedissonClient redissonClient;
private static final DefaultRedisScript<Long> SECKILL_SCRIPT;
static {
SECKILL_SCRIPT = new DefaultRedisScript<>();
SECKILL_SCRIPT.setLocation(new ClassPathResource("seckill.lua"));
SECKILL_SCRIPT.setResultType(Long.class);
}
@Override
public Result seckillVoucher(Long voucherId) {
// //查询秒杀时间
// SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId);
// if (seckillVoucher==null){
// return Result.fail("秒杀商品不存在");
// }
// if (seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())){
// return Result.fail("秒杀未开始");
// }
// if (seckillVoucher.getEndTime().isBefore(LocalDateTime.now())){
// return Result.fail("秒杀已结束");
// }
// if (seckillVoucher.getStock()<1){
// return Result.fail("库存不足");
// }
// Long userId = UserHolder.getUser().getId();
// //加锁:单机下使用synchronized
synchronized (userId.toString().intern()) {
RedisLock redisLock=new RedisLock("order:"+userId,stringRedisTemplate);
redisClient.getL
// RLock lock = redissonClient.getLock("order:" + userId);
// boolean b = lock.tryLock();
// if (!b){
// return Result.fail("每个用户只能购买一次");
// }
// //交给spring后实现事务
// try {
// IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();
// return proxy.createOrder(voucherId);
// } finally {
// lock.unlock();
// }
Long userId = UserHolder.getUser().getId();
Long redult = stringRedisTemplate.execute(SECKILL_SCRIPT,
Collections.emptyList(),
voucherId.toString(), userId.toString());
int r = redult.intValue();
if (r != 0) {
return Result.fail(r == 1 ? "库存不足" : "不能重复下单");
}
RedisIdWorker redisIdWorker = new RedisIdWorker(stringRedisTemplate);
long orderId = redisIdWorker.nextId("order");
return Result.ok(0);
}
@Transactional
public Result createOrder(Long voucherId) {
RedisIdWorker redisIdWorker = new RedisIdWorker(stringRedisTemplate);
long orderId = redisIdWorker.nextId("order");
Long userId = UserHolder.getUser().getId();
//实现一人一单
Integer count = query().eq("user_id", userId)
.eq("voucher_id", voucherId).select().count();
if (count > 0) {
return Result.fail("用户已经购买过一次了");
}
//扣减库存
boolean b = seckillVoucherService.update()
.setSql("stock=stock-1")
.eq("voucher_id", voucherId)
.gt("stock", 0)
.update();
if (!b) {
return Result.fail("秒杀失败");
}
//添加订单信息
VoucherOrder voucherOrder = new VoucherOrder();
voucherOrder.setUserId(userId);
voucherOrder.setVoucherId(voucherId);
voucherOrder.setId(orderId);
save(voucherOrder);
return Result.ok(orderId);
}
}
spring中Bean的生命周期
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class User implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {
public User() {
System.out.println("User的构造方法执行了.........");
}
private String name ;
@Value("张三")
public void setName(String name) {
System.out.println("setName方法执行了.........");
}
@Override
public void setBeanName(String name) {
System.out.println("setBeanName方法执行了.........");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory方法执行了.........");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext方法执行了........");
}
@PostConstruct
public void init() {
System.out.println("init方法执行了.................");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet方法执行了........");
}
@PreDestroy
public void destory() {
System.out.println("destory方法执行了...............");
}
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("user")) {
System.out.println("postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("user")) {
System.out.println("postProcessAfterInitialization->user对象初始化方法后开始增强....");
//cglib代理对象
Enhancer enhancer = new Enhancer();
//设置需要增强的类
enhancer.setSuperclass(bean.getClass());
//执行回调方法,增强方法
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//执行目标方法
return method.invoke(method,objects);
}
});
//创建代理对象
return enhancer.create();
}
return bean;
}
}
输出结果:
User的构造方法执行了.........
setName方法执行了.........
setBeanName方法执行了.........
setBeanFactory方法执行了.........
setApplicationContext方法执行了........
postProcessBeforeInitialization方法执行了->user对象初始化方法前开始增强....
init方法执行了.................
afterPropertiesSet方法执行了........
postProcessAfterInitialization->user对象初始化方法后开始增强....
User的构造方法执行了.........
public java.lang.String java.lang.Object.toString()
spring循环依赖
spring MVC请求
springboot自动配置
spring常见的注解