提出现象
- 做数据库更新A
- redis缓存刷新A
- 做据库更新B
- redis缓存更新B
如果正常执行1,2,3,4步骤,一切正常。但是在高并发的情况下, 执行步骤是 1,3,4,2,导致数据库和缓存不一致。
提出解决方法,做延时双删。
// 操作数据库的方法
@PostMapping("/employee/update") @ClearAndReloadCache(name = "employee") public void update(){ Employee employee = new Employee(); employee.setEmployeeId(BigInteger.valueOf(100)); employee.setHireDate(new Date()); employeeService.update(employee); }
// 注解类
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ClearAndReloadCache { String name() default ""; }
import javafx.concurrent.Task; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @Component @Aspect @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) public class ClearAndReloadCacheAop { @Autowired private StringRedisTemplate stringRedisTemplate; private ExecutorService executorService; { executorService = Executors.newCachedThreadPool(); } @Pointcut("@annotation(com.jin.redis.ClearAndReloadCache)") public void pointCut1() { } @Around(value = "pointCut1()") public Object around(ProceedingJoinPoint proceedingJoinPoint) { Object proceed = null; MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); System.out.println(methodSignature.getName()); ClearAndReloadCache annotation = methodSignature.getMethod().getAnnotation(ClearAndReloadCache.class); if (annotation == null) { try { proceed = proceedingJoinPoint.proceed(); } catch (Throwable e) { throw new RuntimeException(e); } } else { String keyName = annotation.name(); //模糊定义key Set<String> keys = stringRedisTemplate.keys("*" + keyName + "*"); assert keys != null; // 第一次删除 stringRedisTemplate.delete(keys); // 执行数据库的操作 try { proceed = proceedingJoinPoint.proceed(); } catch (Throwable e) { throw new RuntimeException(e); } Task<Void> task = new Task<Void>() { @Override protected Void call() throws Exception { // 休眠 1s 是为了让数据库操作完成 TimeUnit.SECONDS.sleep(1); // 第二次删除 Set<String> keys = stringRedisTemplate.keys("*" + keyName + "*"); assert keys != null; stringRedisTemplate.delete(keys); return null; } }; executorService.submit(task); } return proceed; } }
标签:缓存,双删,keys,redis,org,employee,import,annotation From: https://www.cnblogs.com/wuyicode/p/17838688.html