Redis 与 MySQL 一致性 实现方案
正常情况下的流程是:请求来了,先检查 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 <T> any object
* @return 目标任务返回结果
*/
public static <T> T doubleDeletion(Supplier<T> 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 <T> any object
* @return 目标任务返回结果
*/
public static <T> T doubleDeletion(Supplier<T> 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 <T> any object
* @return 执行目标任务的返回结果
*/
public static <T> T doubleDeletion(Supplier<T> 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)
);