如何入侵网站后台,个人网站建设方案书实例,智能手机软件开发培训,北京注册公司查询1、提前设置热点数据永不过期
2、分布式中用redis分布式锁#xff08;锁可以在多个 JVM 实例之间协调#xff09;、单体中用synchronized#xff08;锁只在同一个 JVM 内有效#xff09; 编写服务类
import com.redisson.api.RLock;
import com.redisson.api.RedissonCli…1、提前设置热点数据永不过期
2、分布式中用redis分布式锁锁可以在多个 JVM 实例之间协调、单体中用synchronized锁只在同一个 JVM 内有效 编写服务类
import com.redisson.api.RLock;
import com.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;Service
public class CacheService {Autowiredprivate StringRedisTemplate redisTemplate;Autowiredprivate RedissonClient redissonClient;private static final String HOT_DATA_KEY hotData;private static final String LOCK_KEY hotDataLock;public String getHotData() {// 尝试从 Redis 中获取热点数据String hotData redisTemplate.opsForValue().get(HOT_DATA_KEY);if (hotData null) {// 获取分布式锁RLock lock redissonClient.getLock(LOCK_KEY);try {// 尝试加锁最多等待100ms锁的过期时间为30秒if (lock.tryLock(100, 30, TimeUnit.SECONDS)) {try {// 再次检查缓存是否过期双重检查hotData redisTemplate.opsForValue().get(HOT_DATA_KEY);if (hotData null) {// 缓存确实过期从数据库加载数据hotData loadHotDataFromDatabase();// 将数据存入 Redis设置过期时间为10分钟redisTemplate.opsForValue().set(HOT_DATA_KEY, hotData, 10, TimeUnit.MINUTES);}} finally {// 释放锁lock.unlock();}}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}return hotData;}private String loadHotDataFromDatabase() {// 模拟从数据库加载数据return Hot Data from Database;}
}
模拟多个请求
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;Component
public class CacheTestRunner implements CommandLineRunner {Autowiredprivate CacheService cacheService;Overridepublic void run(String... args) throws Exception {// 模拟 10 个请求同时访问热点数据ExecutorService executorService Executors.newFixedThreadPool(10);for (int i 0; i 10; i) {executorService.submit(() - {String hotData cacheService.getHotData();System.out.println(Thread Thread.currentThread().getId() got hot data: hotData);});}executorService.shutdown();}
} Thread 12 got hot data: Hot Data from Database
Thread 13 got hot data: Hot Data from Database
Thread 14 got hot data: Hot Data from Database
...
所有线程最终都会获取到相同的数据但只有第一个线程会去加载数据避免了缓存击穿问题。 单体应用
在单体应用中所有请求都运行在同一个 JVM 实例中因此可以使用 synchronized 来同步线程。
java复制
Service
public class CacheService {Autowiredprivate StringRedisTemplate redisTemplate;private static final String HOT_DATA_KEY hotData;private static final Object lock new Object(); // 用于同步的锁对象public String getHotData() {// 尝试从 Redis 中获取热点数据String hotData redisTemplate.opsForValue().get(HOT_DATA_KEY);if (hotData null) {synchronized (lock) { // 使用 synchronized 同步// 再次检查缓存是否过期双重检查hotData redisTemplate.opsForValue().get(HOT_DATA_KEY);if (hotData null) {// 缓存确实过期从数据库加载数据hotData loadHotDataFromDatabase();// 将数据存入 Redis设置过期时间为10分钟redisTemplate.opsForValue().set(HOT_DATA_KEY, hotData, 10, TimeUnit.MINUTES);}}}return hotData;}private String loadHotDataFromDatabase() {// 模拟从数据库加载数据return Hot Data from Database;}
}