机缘
在256天前我来到CSDN上这个平台,看到了很多技术大牛,来到这个平台为了和大家一起交流学习编程的心得,还有写编程遇到的bug以及解决方案。
收获
刚来到CSDN这个平台时我JAVA的进度还停留在JDBC还是个编程小白
256天过去了,进度也赶上来了,现在学到了微服务领域的知识,也有个别文章被云原生社区收录。
日常
在大学期间,边上课学专业课的知识,学校的课上完之后,自己自学编程知识,JAVA生态是很大的,知识体系也很多,要掌握更多的技能需要自学
成就
@Scheduled(cron = "0/5 * * * * *")
public void refreshMysqlByRedis(){
// 将redis中的库存数保存到mysql中
List<SeckillGoods> goods = redisTemplate.boundHashOps("seckillGoods").values();
for (SeckillGoods good : goods) {
// 查询mysql中的秒杀商品
SeckillGoods seckillGoods = seckillGoodsMapper.selectById(good.getId());
seckillGoods.setStockCount(good.getStockCount());
seckillGoodsMapper.updateById(seckillGoods);
}
System.out.println("将Mysql中的秒杀商品数据同步到Redis中");
// 获取当前时间
Date date = new Date();
// 将date类型转换为字符串类型
String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
// 构造查询条件
QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper();
/**
* startTime<当前时间<endTime
* 库存(stockCount)>0
*/
queryWrapper.le("startTime",now) // 当前时间晚于开始时间
.ge("endTime",now) // 当前时间早于结束时间
.gt("stockCount",0); // 库存数量大于0
// 查询出复合条件的秒杀商品
List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectList(queryWrapper);
// 删除redis中的数据
redisTemplate.delete("seckillGoods");
// 将数据同步到redis中
for (SeckillGoods seckillGood : seckillGoods) {
redisTemplate.boundHashOps("seckillGoods").put(seckillGood.getGoodsId(),seckillGood);
}
}
package com.itbaizhan.shopping_sckill_service.redis;
import com.itbaizhan.shopping_common.pojo.Orders;
import com.itbaizhan.shopping_common.pojo.SeckillGoods;
import com.itbaizhan.shopping_common.service.SeckillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
@Autowired(required = false)
private RedisTemplate redisTemplate;
@Autowired
private SeckillService seckillService;
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
// 订单过期后可以获取到订单的id
// 获取订单id
String orderId = message.toString();
// 获取副本
Orders orders = (Orders) redisTemplate.opsForValue().get(orderId + "_cp");
Long goodId = orders.getCartGoods().get(0).getGoodId();// 产品id
Integer num = orders.getCartGoods().get(0).getNum(); // 产品数量
// 查询秒杀商品
SeckillGoods seckillGoods = seckillService.findSeckillGoodsByRedis(goodId);
// 将过期订单回退库存
seckillGoods.setStockCount(seckillGoods.getStockCount() + num);
redisTemplate.boundHashOps("seckillGoods").put(goodId,seckillGoods);
// 删除复制订单 因为复制订单也有过期时间 复制订单触发该监听器是没有任何意义的
redisTemplate.delete(orderId+"_cp");
}
}
- 这是电商项目秒杀服务模块的编写
- 实现思路:
- 用户创建秒杀订单后先将数据同步到redis中,当用户付款再将数据同步到mysql进行持久化保存,使用Spring的定时任务主要解决数据不一致的问题,以及秒杀商品库存的可靠性。
憧憬
努力成为一名全栈工程师!