1 package com.cjs.example.lock.service.impl;
2
3 import com.alibaba.fastjson.JSON;
4 import com.cjs.example.lock.constant.RedisKeyPrefixConstant;
5 import com.cjs.example.lock.model.CourseModel;
6 import com.cjs.example.lock.model.CourseRecordModel;
7 import com.cjs.example.lock.repository.CourseRecordRepository;
8 import com.cjs.example.lock.repository.CourseRepository;
9 import com.cjs.example.lock.service.CourseService;
10 import lombok.extern.slf4j.Slf4j;
11 import org.apache.commons.lang3.StringUtils;
12 import org.redisson.api.RLock;
13 import org.redisson.api.RedissonClient;
14 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.data.redis.core.HashOperations;
16 import org.springframework.data.redis.core.StringRedisTemplate;
17 import org.springframework.stereotype.Service;
18
19 import java.util.concurrent.TimeUnit;
20
21 /**
22 * @author ChengJianSheng
23 * @date 2019-07-26
24 */
25 @Slf4j
26 @Service
27 public class CourseServiceImpl implements CourseService {
28
29 @Autowired
30 private CourseRepository courseRepository;
31 @Autowired
32 private CourseRecordRepository courseRecordRepository;
33 @Autowired
34 private StringRedisTemplate stringRedisTemplate;
35 @Autowired
36 private RedissonClient redissonClient;
37
38 @Override
39 public CourseModel getById(Integer courseId) {
40
41 CourseModel courseModel = null;
42
43 HashOperations hashOperations = stringRedisTemplate.opsForHash();
44
45 String value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId));
46
47 if (StringUtils.isBlank(value)) {
48 String lockKey = RedisKeyPrefixConstant.LOCK_COURSE + courseId;
49 RLock lock = redissonClient.getLock(lockKey);
50 try {
51 boolean res = lock.tryLock(10, TimeUnit.SECONDS);
52 if (res) {
53 value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId));
54 if (StringUtils.isBlank(value)) {
55 log.info("从数据库中读取");
56 courseModel = courseRepository.findById(courseId).orElse(null);
57 hashOperations.put(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId), JSON.toJSONString(courseModel));
58 }
59 }
60 } catch (InterruptedException e) {
61 e.printStackTrace();
62 } finally {
63 lock.unlock();
64 }
65 } else {
66 log.info("从缓存中读取");
67 courseModel = JSON.parseObject(value, CourseModel.class);
68 }
69
70 return courseModel;
71 }
72
73 @Override
74 public void upload(Integer userId, Integer courseId, Integer studyProcess) {
75
76 HashOperations hashOperations = stringRedisTemplate.opsForHash();
77
78 String cacheKey = RedisKeyPrefixConstant.COURSE_PROGRESS + ":" + userId;
79 String cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId));
80 if (StringUtils.isNotBlank(cacheValue) && studyProcess <= Integer.valueOf(cacheValue)) {
81 return;
82 }
83
84 String lockKey = "upload:" + userId + ":" + courseId;
85
86 RLock lock = redissonClient.getLock(lockKey);
87
88 try {
89 lock.lock(10, TimeUnit.SECONDS);
90
91 cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId));
92 if (StringUtils.isBlank(cacheValue) || studyProcess > Integer.valueOf(cacheValue)) {
93 CourseRecordModel model = new CourseRecordModel();
94 model.setUserId(userId);
95 model.setCourseId(courseId);
96 model.setStudyProcess(studyProcess);
97 courseRecordRepository.save(model);
98 hashOperations.put(cacheKey, String.valueOf(courseId), String.valueOf(studyProcess));
99 }
100
101 } catch (Exception ex) {
102 log.error("获取所超时!", ex);
103 } finally {
104 lock.unlock();
105 }
106
107 }
108 }