缘起
最近在弄一个答题小程序,当用户选择的时候需要把用户选择的选项提交到服务器上,然后整个字段是个json格式的,更新的方法也就是解析json后添加选项进入json中。
于是其中就涉及到频繁的数据库修改,因为用户答题速度根据题目不同嘛,所以我就寻思这样频繁的修改,数据量上来速度就会受到较大的影响。
于是我打算在服务端做一个缓存机制,保存从数据库中读取到的记录用户选项的字段,这样修改就会快一些,然后利用spring的@Scheduled进行定时提交到数据库
springboot后端写法
缓存机制
利用一个ConcurrentHashMap,记录userId和对象,当获取这个字段时,判断是否存在有效的对象,如果存在,直接从map中返回,并且更新缓存的过期时间
public Map<String, UserGroupProgress> getUserGroupProgress(Integer userId) {
if ( !userGroupProgressMap.containsKey(userId) ){
log.info("get userProgress from database");
// 对象不存在,从数据库中读取
User user = userService.lambdaQuery().select(User::getGroupProgress).eq(User::getId, userId).one();
if ( user == null ){
return null;
}
UserGroupProgressCache cache = new UserGroupProgressCache();
cache.setMap(user.getGroupProgress());
cache.setCacheTime(System.currentTimeMillis());
userGroupProgressMap.put(userId, cache);
return cache.getMap();
}
log.info("get userProgress from map");
UserGroupProgressCache cache = userGroupProgressMap.get(userId);
// 更新缓存时间
cache.setCacheTime(System.currentTimeMillis());
return cache.getMap();
}
然后再application启动类中加上 @EnableScheduling 注解
@EnableScheduling
@SpringBootApplication
public class CloudQuestionApplication {
public static void main(String[] args) {
SpringApplication.run(CloudQuestionApplication.class, args);
}
}
定时提交
使用 @Scheduled 注解进行定时提交,并且检查缓存是否过期
// 这里是测试,所以才定的30s
@Scheduled(fixedDelay = 30000)
public void executeProgressSubmit() {
// 遍历整个map,提交一轮,如果过期,直接抛弃,缓存20分钟
// 这里主要用于测试,没啥实际作用
int commitCount = 0, removeCount = 0;
Long time = System.currentTimeMillis();
for (Map.Entry<Integer, UserGroupProgressCache> entry : userGroupProgressMap.entrySet()) {
commitCount ++;
if ( entry.getValue() == null ){
continue;
}
userService.lambdaUpdate()
.set(User::getGroupProgress, JSON.toJSONString(entry.getValue().getMap()))
.eq(User::getId, entry.getKey())
.update();
if ( time - entry.getValue().getCacheTime() > 1000 * 60 * 20 ){
// 抛弃对象
removeCount ++;
userGroupProgressMap.remove(entry.getKey());
}
}
}
前端写法
略
前端还考虑集贸,直接提交即可