1. 首页
  2. IT资讯

如何使用 Redis 实现高性能点赞,取消点赞?

“u003Cpu003E点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。点赞、取消点赞是高频次的操作,若每次都读写数据库,大量的操作会影响数据库性能,所以需要做缓存。u003Cu002Fpu003Eu003Cpu003E本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。u003Cu002Fpu003Eu003Cpu003E至于多久从 Redis 取一次数据存到数据库中,根据项目的实际情况定吧,我是暂时设了两个小时。u003Cu002Fpu003Eu003Cpu003E项目需求需要查看都谁点赞了,所以要存储每个点赞的点赞人、被点赞人,不能简单的做计数。u003Cu002Fpu003Eu003Cpu003E文章分四部分介绍:u003Cu002Fpu003Eu003Cul class=”list-paddingleft-2″u003Eu003Cliu003ERedis 缓存设计及实现u003Cu002Fliu003Eu003Cliu003E数据库设计u003Cu002Fliu003Eu003Cliu003E数据库操作u003Cu002Fliu003Eu003Cliu003E开启定时任务持久化存储到数据库u003Cu002Fliu003Eu003Cu002Fulu003Eu003Cpu003E一、Redis 缓存设计及实现u003Cu002Fpu003Eu003Cpu003E1.1 Redis 安装及运行u003Cu002Fpu003Eu003Cpu003ERedis 安装请自行查阅相关教程。u003Cu002Fpu003Eu003Cpu003E说下Docker 安装运行 Redisu003Cu002Fpu003Eu003Cpreu003Edocker run -d -p 6379:6379 redis:4.0.8u003Cu002Fpreu003Eu003Cpu003E如果已经安装了 Redis,打开命令行,输入启动 Redis 的命令u003Cu002Fpu003Eu003Cpreu003Eredis-serveru003Cu002Fpreu003Eu003Cpu003E1.2 Redis 与 SpringBoot 项目的整合u003Cu002Fpu003Eu003Cpu003E1、 在 pom.xml 中引入依赖u003Cu002Fpu003Eu003Cpreu003E<dependency><groupId>org.springframework.boot<u002FgroupId><artifactId>spring-boot-starter-data-redis<u002FartifactId><u002Fdependency>u003Cu002Fpreu003Eu003Cpu003E2、 在启动类上添加注释 @EnableCachingu003Cu002Fpu003Eu003Cpreu003E@SpringBootApplication@EnableDiscoveryClient@EnableSwagger2@EnableFeignClients(basePackages = "com.solo.coderiver.project.client")@EnableCachingpublicclassUserApplication{u003Cbru003Epublicstaticvoid main(String[] args) {SpringApplication.run(UserApplication.class, args);}}u003Cu002Fpreu003Eu003Cpu003E3、 编写 Redis 配置类 RedisConfigu003Cu002Fpu003Eu003Cpreu003Eimport com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;u003Cbru003Eimport java.net.UnknownHostException;u003Cbru003Eu003Cbru003E@ConfigurationpublicclassRedisConfig{u003Cbru003E@Bean@ConditionalOnMissingBean(name = "redisTemplate")publicRedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throwsUnknownHostException{u003Cbru003EJackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = newJackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper om = newObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om);u003Cbru003ERedisTemplate<String, Object> template= newRedisTemplate<String, Object>();template.setConnectionFactory(redisConnectionFactory);template.setKeySerializer(jackson2JsonRedisSerializer);template.setValueSerializer(jackson2JsonRedisSerializer);template.setHashKeySerializer(jackson2JsonRedisSerializer);template.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();returntemplate;}u003Cbru003Eu003Cbru003E@Bean@ConditionalOnMissingBean(StringRedisTemplate.class)publicStringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)throwsUnknownHostException{StringRedisTemplatetemplate= newStringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);returntemplate;}}u003Cu002Fpreu003Eu003Cpu003E至此 Redis 在 SpringBoot 项目中的配置已经完成,可以愉快的使用了。u003Cu002Fpu003Eu003Cpu003E1.3 Redis 的数据结构类型u003Cu002Fpu003Eu003Cpu003ERedis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。u003Cu002Fpu003Eu003Cpu003E下面来对这5种数据结构类型作简单的介绍:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fa9307b3a92ef4d9a80c51f0fccc57e4f” img_width=”774″ img_height=”434″ alt=”如何使用 Redis 实现高性能点赞,取消点赞?” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E1.4 点赞数据在 Redis 中的存储格式u003Cu002Fpu003Eu003Cpu003E用 Redis 存储两种数据,一种是记录点赞人、被点赞人、点赞状态的数据,另一种是每个用户被点赞了多少次,做个简单的计数。u003Cu002Fpu003Eu003Cpu003E由于需要记录点赞人和被点赞人,还有点赞状态(点赞、取消点赞),还要固定时间间隔取出 Redis 中所有点赞数据,分析了下 Redis 数据格式中 Hash 最合适。u003Cu002Fpu003Eu003Cpu003E因为 Hash 里的数据都是存在一个键里,可以通过这个键很方便的把所有的点赞数据都取出。这个键里面的数据还可以存成键值对的形式,方便存入点赞人、被点赞人和点赞状态。u003Cu002Fpu003Eu003Cpu003E设点赞人的 id 为 likedPostId,被点赞人的 id 为 likedUserId ,点赞时状态为 1,取消点赞状态为 0。将点赞人 id 和被点赞人 id 作为键,两个 id 中间用 :: 隔开,点赞状态作为值。u003Cu002Fpu003Eu003Cpu003E所以如果用户点赞,存储的键为:likedUserId::likedPostId,对应的值为 1 。u003Cu002Fpu003Eu003Cpu003E取消点赞,存储的键为:likedUserId::likedPostId,对应的值为 0 。u003Cu002Fpu003Eu003Cpu003E取数据时把键用 :: 切开就得到了两个id,也很方便。u003Cu002Fpu003Eu003Cpu003E在可视化工具 RDM 中看到的是这样子u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002Fa63593ebdd694067b32327aed9a1b503″ img_width=”1080″ img_height=”278″ alt=”如何使用 Redis 实现高性能点赞,取消点赞?” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fba9a83643d974756b9a952d48638976c” img_width=”1080″ img_height=”253″ alt=”如何使用 Redis 实现高性能点赞,取消点赞?” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E1.5 操作 Redisu003Cu002Fpu003Eu003Cpu003ERedis 各种数据格式的操作方法可以看看 这篇文章 ,写的非常好。u003Cu002Fpu003Eu003Cpu003E将具体操作方法封装到了 RedisService 接口里u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003ERedisService.javau003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003Eimport com.solo.coderiver.user.dataobject.UserLike;import com.solo.coderiver.user.dto.LikedCountDTO;u003Cbru003Eimport java.util.List;u003Cbru003EpublicinterfaceRedisService{u003Cbru003Eu002F** * 点赞。状态为1 * @param likedUserId * @param likedPostId *u002Fvoid saveLiked2Redis(String likedUserId, String likedPostId);u003Cbru003Eu002F** * 取消点赞。将状态改变为0 * @param likedUserId * @param likedPostId *u002Fvoid unlikeFromRedis(String likedUserId, String likedPostId);u003Cbru003Eu002F** * 从Redis中删除一条点赞数据 * @param likedUserId * @param likedPostId *u002Fvoid deleteLikedFromRedis(String likedUserId, String likedPostId);u003Cbru003Eu002F** * 该用户的点赞数加1 * @param likedUserId *u002Fvoid incrementLikedCount(String likedUserId);u003Cbru003Eu002F** * 该用户的点赞数减1 * @param likedUserId *u002Fvoid decrementLikedCount(String likedUserId);u003Cbru003Eu002F** * 获取Redis中存储的所有点赞数据 * @return *u002FList<UserLike> getLikedDataFromRedis();u003Cbru003Eu002F** * 获取Redis中存储的所有点赞数量 * @return *u002FList<LikedCountDTO> getLikedCountFromRedis();u003Cbru003E}u003Cu002Fpreu003Eu003Cblockquoteu003Eu003Cpu003E实现类 RedisServiceImpl.javau003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003Eimport com.solo.coderiver.user.dataobject.UserLike;import com.solo.coderiver.user.dto.LikedCountDTO;import com.solo.coderiver.user.enums.LikedStatusEnum;import com.solo.coderiver.user.service.LikedService;import com.solo.coderiver.user.service.RedisService;import com.solo.coderiver.user.utils.RedisKeyUtils;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.Cursor;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ScanOptions;import org.springframework.stereotype.Service;u003Cbru003Eimport java.util.ArrayList;import java.util.List;import java.util.Map;u003Cbru003E@Service@Slf4jpublicclassRedisServiceImplimplementsRedisService{u003Cbru003E@AutowiredRedisTemplate redisTemplate;u003Cbru003E@AutowiredLikedService likedService;u003Cbru003E@Overridepublicvoid saveLiked2Redis(String likedUserId, String likedPostId) {String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId); redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.LIKE.getCode());}u003Cbru003E@Overridepublicvoid unlikeFromRedis(String likedUserId, String likedPostId) {String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId); redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED, key, LikedStatusEnum.UNLIKE.getCode());}u003Cbru003E@Overridepublicvoid deleteLikedFromRedis(String likedUserId, String likedPostId) {String key = RedisKeyUtils.getLikedKey(likedUserId, likedPostId); redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);}u003Cbru003E@Overridepublicvoid incrementLikedCount(String likedUserId) { redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, 1);}u003Cbru003E@Overridepublicvoid decrementLikedCount(String likedUserId) { redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, likedUserId, -1);}u003Cbru003E@OverridepublicList<UserLike> getLikedDataFromRedis() {Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);List<UserLike> list = newArrayList<>();while(cursor.hasNext()){Map.Entry<Object, Object> entry = cursor.next();String key = (String) entry.getKey();u002Fu002F分离出 likedUserId,likedPostIdString[] split = key.split("::");String likedUserId = split[0];String likedPostId = split[1];Integer value = (Integer) entry.getValue();u003Cbru003Eu002Fu002F组装成 UserLike 对象UserLike userLike = newUserLike(likedUserId, likedPostId, value); list.add(userLike);u003Cbru003Eu002Fu002F存到 list 后从 Redis 中删除 redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);}u003Cbru003Ereturn list;}u003Cbru003E@OverridepublicList<LikedCountDTO> getLikedCountFromRedis() {Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);List<LikedCountDTO> list = newArrayList<>();while(cursor.hasNext()){Map.Entry<Object, Object> map = cursor.next();u002Fu002F将点赞数量存储在 LikedCountDTString key = (String)map.getKey();LikedCountDTO dto = newLikedCountDTO(key, (Integer) map.getValue()); list.add(dto);u002Fu002F从Redis中删除这条记录 redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key);}return list;}}u003Cu002Fpreu003Eu003Cpu003E用到的工具类和枚举类u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003ERedisKeyUtils, 用于根据一定规则生成 keyu003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003EpublicclassRedisKeyUtils{u003Cbru003Eu002Fu002F保存用户点赞数据的keypublicstaticfinalString MAP_KEY_USER_LIKED = "MAP_USER_LIKED";u002Fu002F保存用户被点赞数量的keypublicstaticfinalString MAP_KEY_USER_LIKED_COUNT = "MAP_USER_LIKED_COUNT";u003Cbru003Eu002F** * 拼接被点赞的用户id和点赞的人的id作为key。格式 222222::333333 * @param likedUserId 被点赞的人id * @param likedPostId 点赞的人的id * @return *u002FpublicstaticString getLikedKey(String likedUserId, String likedPostId){StringBuilder builder = newStringBuilder(); builder.append(likedUserId); builder.append("::"); builder.append(likedPostId);return builder.toString();}}u003Cu002Fpreu003Eu003Cblockquoteu003Eu003Cpu003ELikedStatusEnum 用户点赞状态的枚举类u003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003Epackage com.solo.coderiver.user.enums;u003Cbru003Eimport lombok.Getter;u003Cbru003Eu002F** * 用户点赞的状态 *u002F@GetterpublicenumLikedStatusEnum{ LIKE(1, "点赞"), UNLIKE(0, "取消点赞u002F未点赞"),;u003Cbru003EprivateInteger code;u003Cbru003EprivateString msg;u003Cbru003ELikedStatusEnum(Integer code, String msg) {this.code = code;this.msg = msg;}}u003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E二、数据库设计u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E数据库表中至少要包含三个字段:被点赞用户id,点赞用户id,点赞状态。再加上主键id,创建时间,修改时间就行了。u003Cu002Fpu003Eu003Cpu003E建表语句u003Cu002Fpu003Eu003Cpreu003Ecreate table `user_like`(`id`intnotnull auto_increment,`liked_user_id` varchar(32) notnull comment '被点赞的用户id',`liked_post_id` varchar(32) notnull comment '点赞的用户id',`status` tinyint(1) default'1' comment '点赞状态,0取消,1点赞',`create_time` timestamp notnulldefault current_timestamp comment '创建时间',`update_time` timestamp notnulldefault current_timestamp on update current_timestamp comment '修改时间', primary key(`id`), INDEX `liked_user_id`(`liked_user_id`), INDEX `liked_post_id`(`liked_post_id`)) comment '用户点赞表';u003Cu002Fpreu003Eu003Cpu003E对应的对象 UserLikeu003Cu002Fpu003Eu003Cpreu003Eimport com.solo.coderiver.user.enums.LikedStatusEnum;import lombok.Data;u003Cbru003Eimport javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;u003Cbru003Eu002F** * 用户点赞表 *u002F@Entity@DatapublicclassUserLike{u003Cbru003Eu002Fu002F主键id@Id@GeneratedValue(strategy = GenerationType.IDENTITY)privateInteger id;u003Cbru003Eu002Fu002F被点赞的用户的idprivateString likedUserId;u003Cbru003Eu002Fu002F点赞的用户的idprivateString likedPostId;u003Cbru003Eu002Fu002F点赞的状态.默认未点赞privateInteger status = LikedStatusEnum.UNLIKE.getCode();u003Cbru003EpublicUserLike() {}u003Cbru003EpublicUserLike(String likedUserId, String likedPostId, Integer status) {this.likedUserId = likedUserId;this.likedPostId = likedPostId;this.status = status;}}u003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E三、数据库操作u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E操作数据库同样封装在接口中u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003ELikedServiceu003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003Eimport com.solo.coderiver.user.dataobject.UserLike;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;u003Cbru003Eimport java.util.List;u003Cbru003EpublicinterfaceLikedService{u003Cbru003Eu002F** * 保存点赞记录 * @param userLike * @return *u002FUserLike save(UserLike userLike);u003Cbru003Eu002F** * 批量保存或修改 * @param list *u002FList<UserLike> saveAll(List<UserLike> list);u003Cbru003Eu003Cbru003Eu002F** * 根据被点赞人的id查询点赞列表(即查询都谁给这个人点赞过) * @param likedUserId 被点赞人的id * @param pageable * @return *u002FPage<UserLike> getLikedListByLikedUserId(String likedUserId, Pageable pageable);u003Cbru003Eu002F** * 根据点赞人的id查询点赞列表(即查询这个人都给谁点赞过) * @param likedPostId * @param pageable * @return *u002FPage<UserLike> getLikedListByLikedPostId(String likedPostId, Pageable pageable);u003Cbru003Eu002F** * 通过被点赞人和点赞人id查询是否存在点赞记录 * @param likedUserId * @param likedPostId * @return *u002FUserLike getByLikedUserIdAndLikedPostId(String likedUserId, String likedPostId);u003Cbru003Eu002F** * 将Redis里的点赞数据存入数据库中 *u002Fvoid transLikedFromRedis2DB();u003Cbru003Eu002F** * 将Redis中的点赞数量数据存入数据库 *u002Fvoid transLikedCountFromRedis2DB();u003Cbru003E}u003Cu002Fpreu003Eu003Cblockquoteu003Eu003Cpu003ELikedServiceImpl 实现类u003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpreu003Eimport com.solo.coderiver.user.dataobject.UserInfo;import com.solo.coderiver.user.dataobject.UserLike;import com.solo.coderiver.user.dto.LikedCountDTO;import com.solo.coderiver.user.enums.LikedStatusEnum;import com.solo.coderiver.user.repository.UserLikeRepository;import com.solo.coderiver.user.service.LikedService;import com.solo.coderiver.user.service.RedisService;import com.solo.coderiver.user.service.UserService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;u003Cbru003Eimport java.util.List;u003Cbru003E@Service@Slf4jpublicclassLikedServiceImplimplementsLikedService{u003Cbru003E@AutowiredUserLikeRepository likeRepository;u003Cbru003E@AutowiredRedisService redisService;u003Cbru003E@AutowiredUserService userService;u003Cbru003E@Override@TransactionalpublicUserLike save(UserLike userLike) {return likeRepository.save(userLike);}u003Cbru003E@Override@TransactionalpublicList<UserLike> saveAll(List<UserLike> list) {return likeRepository.saveAll(list);}u003Cbru003E@OverridepublicPage<UserLike> getLikedListByLikedUserId(String likedUserId, Pageable pageable) {return likeRepository.findByLikedUserIdAndStatus(likedUserId, LikedStatusEnum.LIKE.getCode(), pageable);}u003Cbru003E@OverridepublicPage<UserLike> getLikedListByLikedPostId(String likedPostId, Pageable pageable) {return likeRepository.findByLikedPostIdAndStatus(likedPostId, LikedStatusEnum.LIKE.getCode(), pageable);}u003Cbru003E@OverridepublicUserLike getByLikedUserIdAndLikedPostId(String likedUserId, String likedPostId) {return likeRepository.findByLikedUserIdAndLikedPostId(likedUserId, likedPostId);}u003Cbru003E@Override@Transactionalpublicvoid transLikedFromRedis2DB() {List<UserLike> list = redisService.getLikedDataFromRedis();for(UserLike like : list) {UserLike ul = getByLikedUserIdAndLikedPostId(like.getLikedUserId(), like.getLikedPostId());if(ul == null){u002Fu002F没有记录,直接存入 save(like);}else{u002Fu002F有记录,需要更新 ul.setStatus(like.getStatus()); save(ul);}}}u003Cbru003E@Override@Transactionalpublicvoid transLikedCountFromRedis2DB() {List<LikedCountDTO> list = redisService.getLikedCountFromRedis();for(LikedCountDTO dto : list) {UserInfo user = userService.findById(dto.getId());u002Fu002F点赞数量属于无关紧要的操作,出错无需抛异常if(user != null){Integer likeNum = user.getLikeNum() + dto.getCount(); user.setLikeNum(likeNum);u002Fu002F更新点赞数量 userService.updateInfo(user);}}}}u003Cu002Fpreu003Eu003Cpu003E数据库的操作就这些,主要还是增删改查。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E四、开启定时任务持久化存储到数据库u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E定时任务 Quartz 很强大,就用它了。u003Cu002Fpu003Eu003Cpu003EQuartz 使用步骤:u003Cu002Fpu003Eu003Cpu003E1、 添加依赖u003Cu002Fpu003Eu003Cpreu003E<dependency><groupId>org.springframework.boot<u002FgroupId><artifactId>spring-boot-starter-quartz<u002FartifactId><u002Fdependency>u003Cu002Fpreu003Eu003Cpu003E1、 编写配置文件u003Cu002Fpu003Eu003Cpreu003Epackage com.solo.coderiver.user.config;u003Cbru003Eimport com.solo.coderiver.user.task.LikeTask;import org.quartz.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;u003Cbru003E@ConfigurationpublicclassQuartzConfig{u003Cbru003EprivatestaticfinalString LIKE_TASK_IDENTITY = "LikeTaskQuartz";u003Cbru003E@BeanpublicJobDetail quartzDetail(){returnJobBuilder.newJob(LikeTask.class).withIdentity(LIKE_TASK_IDENTITY).storeDurably().build();}u003Cbru003E@BeanpublicTrigger quartzTrigger(){SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()u002Fu002F .withIntervalInSeconds(10) u002Fu002F设置时间周期单位秒.withIntervalInHours(2) u002Fu002F两个小时执行一次.repeatForever();returnTriggerBuilder.newTrigger().forJob(quartzDetail()).withIdentity(LIKE_TASK_IDENTITY).withSchedule(scheduleBuilder).build();}}u003Cu002Fpreu003Eu003Cpu003E3、 编写执行任务的类继承自 QuartzJobBeanu003Cu002Fpu003Eu003Cpreu003Epackage com.solo.coderiver.user.task;u003Cbru003Eimport com.solo.coderiver.user.service.LikedService;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.time.DateUtils;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.QuartzJobBean;u003Cbru003Eimport java.text.SimpleDateFormat;import java.util.Date;u003Cbru003Eu002F** * 点赞的定时任务 *u002F@Slf4jpublicclassLikeTaskextendsQuartzJobBean{u003Cbru003E@AutowiredLikedService likedService;u003Cbru003EprivateSimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");u003Cbru003E@Overrideprotectedvoid executeInternal(JobExecutionContext jobExecutionContext) throwsJobExecutionException{u003Cbru003E log.info("LikeTask——– {}", sdf.format(newDate()));u003Cbru003Eu002Fu002F将 Redis 里的点赞信息同步到数据库里 likedService.transLikedFromRedis2DB(); likedService.transLikedCountFromRedis2DB();}}u003Cu002Fpreu003Eu003Cpu003E在定时任务中直接调用 LikedService 封装的方法完成数据同步。u003Cu002Fpu003E”

原文始发于:如何使用 Redis 实现高性能点赞,取消点赞?

主题测试文章,只做测试使用。发布者:程序员,转转请注明出处:http://www.cxybcw.com/26434.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code