正常情况下的流程是:请求来了,先检查 Redis 有没有数据,有返回;没有便查询 MySQL 然后 放入 Redis。
此时,如果 MySQL 的数据发生了变化,所以需要同步到 Redis 中。
解决方法:MySQL 中的数据更新的时候 ,在更新之前先删一次 Redis 中的数据,在更新之后再删一次 Redis 中的数据。
工具类
- public class RedisUtil {
-
-
- private final static ScheduledExecutorService DELAY_EXECUTOR = new ScheduledThreadPoolExecutor(4);
-
-
-
- /**
- * 缓存延迟双删
- *
- * @param factory 目标任务
- * @param keys 插入':' 拼接成需要删除的缓存key
- * @param
any object - * @return 目标任务返回结果
- */
- public static
T doubleDeletion(Supplier factory, Object... keys) { - return RedisUtil.doubleDeletion(
- factory,
- () -> RedisUtil.getRedisTemplate().delete(
- RedisUtil.key(keys)
- )
- );
- }
-
- /**
- * 缓存延迟双删
- *
- * @param task 目标任务
- * @param keys 插入':' 拼接成需要删除的缓存key
- */
- public static void doubleDeletion(Runnable task, Object... keys) {
- RedisUtil.doubleDeletion(
- task,
- () -> RedisUtil.getRedisTemplate().delete(
- RedisUtil.key(keys)
- )
- );
- }
-
- /**
- * 缓存延迟双删
- *
- * @param factory 目标任务
- * @param key 需要删除的缓存key
- * @param
any object - * @return 目标任务返回结果
- */
- public static
T doubleDeletion(Supplier factory, String key) { - return RedisUtil.doubleDeletion(
- factory,
- () -> RedisUtil.getRedisTemplate().delete(key)
- );
- }
-
- /**
- * 缓存延迟双删
- *
- * @param task 目标任务
- * @param key 需要删除的缓存key
- */
- public static void doubleDeletion(Runnable task, String key) {
- RedisUtil.doubleDeletion(
- task,
- () -> RedisUtil.getRedisTemplate().delete(key)
- );
- }
-
- /**
- * 缓存延迟双删
- *
- * @param factory 执行的目标任务
- * @param deleteCacheTask 清除缓存的任务
- * @param
any object - * @return 执行目标任务的返回结果
- */
- public static
T doubleDeletion(Supplier factory, Runnable deleteCacheTask) { - deleteCacheTask.run();
- T data = factory.get();
- //延迟800毫秒秒再删一次
- DelayExecutor.DELAY_EXECUTOR.schedule(deleteCacheTask, 800, TimeUnit.MILLISECONDS);
- return data;
- }
-
- /**
- * 缓存延迟双删
- *
- * @param task 目标任务
- * @param deleteCacheTask 清除缓存任务
- */
- public static void doubleDeletion(Runnable task, Runnable deleteCacheTask) {
- RedisUtil.doubleDeletion(
- () -> {
- task.run();
- return null;
- },
- deleteCacheTask
- );
- }
-
- }
用法 1
-
- RedisUtil.doubleDeletion(
- // 定义数据库更新操作
- () -> updateProcudt(product),
- // 定义 删除 redis 操作
- () -> RedisUtil.delete("product:" + id)
- );