基于CHM在JVM层面,再做一层缓存。提升查询性能,基于定时任务做全量更新

master
e 5 months ago
parent dee7e53254
commit bd663e0433

@ -0,0 +1,74 @@
package com.mashibing.cache;
import com.mashibing.entity.Air;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author zjw
* @description
*/
@Repository
public class AirCache implements InitializingBean {
// 一个只有一个工作线程,并且可以执行的定时任务的线程池。
private static final ScheduledExecutorService AIR_POOL = Executors.newSingleThreadScheduledExecutor();
// JVM缓存 写读
private static final ConcurrentHashMap<Long,Air> AIR_CACHE = new ConcurrentHashMap<Long, Air>(128);
// 做全量更新时,上好写锁,不允许读取数据。 读取数据时,需要走读锁
private static final ReentrantReadWriteLock READ_WRITE_LOCK = new ReentrantReadWriteLock();
private static final ReentrantReadWriteLock.WriteLock WRITE_LOCK = READ_WRITE_LOCK.writeLock();
private static final ReentrantReadWriteLock.ReadLock READ_LOCK = READ_WRITE_LOCK.readLock();
@Override
public void afterPropertiesSet() throws Exception {
// scheduleAtFixedRate 每次间隔3s但是任务的执行时间也会算到这3s内。
// scheduleWithFixedDelay 每次间隔3s等待上个任务完成后间隔3s再执行下次任务。
AIR_POOL.scheduleWithFixedDelay(() -> {
// 这里做全量更新
// 1、查询数据库中的全部数据 TODO 后面全量查询数据库
Map<Long,Air> allData = new HashMap<>();
// 2、同步到JVM缓存中。
writeAll(allData);
},0,3, TimeUnit.SECONDS);
}
// 全量更新 (数据体量比较小,咱们采用全量更新。 如果数据体量比较大采用增量更新增量更新需要考虑多个JVM之间的数据同步MQ的广播机制去玩
private void writeAll(Map<Long, Air> allData) {
// 获取写锁
WRITE_LOCK.lock();
try{
// 清除缓存全部数据
AIR_CACHE.clear();
// 全量更新
AIR_CACHE.putAll(allData);
}finally {
WRITE_LOCK.unlock();
}
}
// 对外提供查询功能
public Air getAirById(Long id){
if(id == null) return null;
boolean b = READ_LOCK.tryLock();
if(!b){
return null;
}
try{
Air air = AIR_CACHE.get(id);
return air;
}catch (Exception e){
return null;
}finally{
READ_LOCK.unlock();
}
}
}

@ -1,5 +1,6 @@
package com.mashibing.service.impl;
import com.mashibing.cache.AirCache;
import com.mashibing.entity.Air;
import com.mashibing.mapper.AirMapper;
import com.mashibing.service.AirService;
@ -23,20 +24,25 @@ public class AirServiceImpl implements AirService {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private AirCache airCache;
private final String AIR_PREFIX = "air:";
@Override
public Air getById(Long id) {
// 查询Redis缓存之前先去查询一下JVM中的缓存 ConcurrentHashMap 作为JVM缓存
// 查询数据库之前查询Redis中的数据
Air air = (Air) redisTemplate.opsForValue().get(AIR_PREFIX + id);
Air air = airCache.getAirById(id);
if(air == null) {
// 查询数据库
air = airMapper.findById(id);
redisTemplate.opsForValue().set(AIR_PREFIX + id,air);
}
// 查询数据库之前查询Redis中的数据
air = (Air) redisTemplate.opsForValue().get(AIR_PREFIX + id);
if (air == null) {
// 查询数据库
air = airMapper.findById(id);
redisTemplate.opsForValue().set(AIR_PREFIX + id, air);
}
}
return air;
}
}

Loading…
Cancel
Save