JAVA秒杀系统的简单实现(redis+rabbitmq)

1.分析

上述三点的主要问题就是在高并发的情况下保证数据的一致性。

2.使用的技术和架构

2.1秒杀架构图

JAVA秒杀系统的简单实现(redis+rabbitmq)


2.2流程

2.3流程图

JAVA秒杀系统的简单实现(redis+rabbitmq)

3.准备工作

3.1安装redis cluster

csdn上教程一大堆,这里我就不多赘述了。需要注意的点是,如果使用的是阿里云服务器(centos 7),在安装完后一定要去阿里云服务器控制台添加安全规则,去开放你使用的对应端口号。
https://blog.csdn.net/CFrieman/article/details/83583085

3.2安装RabbitMQ和erlang

还是直接附上链接。需要说明的一点是,在安装erlang时,电脑名称不可以是中文,erlang的版本和rabbitmq的版本一定要对应,负责会安装失败。
https://blog.csdn.net/qq_36505948/article/details/82734133

4.具体实现

4.1SeckillService

public class SeckillService {

	@Autowired
	 private RedisClusterClient rt;

	@Autowired
	private SeckillMapper sm;

	@Autowired
	private RedissonClient redissonClient; // 加锁

	@Autowired
	private RabbitmqSendMessage rsm;

	@Autowired
	private SecorderMapper om;
    
	/**
	 * 初始化 ,将mysql中的商品信息缓存到redis中
	 * @return
	 */
	public List querySeckill() {
		List list =   (List) rt.get("secgoods");
		if(list==null) {
			list = sm.selectByExample(null);
			rt.set("secgoods", list, 60*30);
		}
		return list;
	}

	public boolean queryStartTime(Seckill sec) {
		Date date = new Date();// 比较时间,是否到秒杀时间
		Date startTime = sec.getStarttime();
		// 秒杀活动还未开始
		if (startTime.getTime() > date.getTime()) {
			return false;
		}

		return true;
	}

	// 减库存redis
	public void decreaseStock(String id) {
        int goodsid = Integer.parseInt(id);
        List list =   (List) rt.get("secgoods");
		if (list!=null)
		{
			for (Seckill sec : list)
			{
				if (goodsid==sec.getId())
				{
					sec.setCount(sec.getCount()-1);
					//写回redis
					rt.set("secgoods", list, 60*30);
					
					return ;
				}
			}
		}
	}

	//
	public Seckill findSec(String secid) {
		 List list =   (List) rt.get("secgoods");
		int id = Integer.parseInt(secid);
		for(Seckill sec:list) {
			if(sec.getId()==id) {
				return sec;
			}
		}
		return null;
	}

	// 开始秒杀
	public String goSeckill(String goodsid, String username) {
		String key = username + ":" + goodsid;

		String secid = goodsid;

		Long value = (Long) rt.get(key);
		if (value != null) {
			return "exist";
		}

		Seckill sec = findSec(secid);
		boolean flag = queryStartTime(sec);
		if (!flag) {
			return "notTime";
		}

		RLock rLock = redissonClient.getLock("miaosha");
		rLock.lock();
		if (sec.getCount() > 0) {

			decreaseStock(goodsid); // 减少库存

			rt.set(key, System.currentTimeMillis(), 60*30);

			Secorder newOrder = new Secorder();

			newOrder.setCreatetime(new Date());
			newOrder.setGoodsid(Integer.parseInt(goodsid));
			newOrder.setStatus("未付款");
			newOrder.setUsername(username);

			String json = JSONObject.toJSONString(newOrder);

			rsm.send(json); // 异步下单
			rLock.unlock(); // 解锁

			return "success";

		} else {
			rLock.unlock();
			return "failed";
		}
	}

	// 写入mysql
	public void saveOrder(String json) {
		Secorder order = JSON.parseObject(json, Secorder.class);
		int n = sm.updateCount(order.getGoodsid());
		int m = om.insert(order);
	}
	

}


4.2 RabbitmqListenner

@Service
public class RabbitmqListenner implements MessageListener {
	
	@Autowired
	private SeckillService ss;
	
    @Override
    public void onMessage(Message msg) {
    	byte[] data = msg.getBody();
		try {
			String 	json = new String(data,"utf-8");
			System.out.println(json);
			ss.saveOrder(json);   //将监听到的订单写入MySQL
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
    }
}

4.3 RabbitmqSendMessage

public class RabbitmqSendMessage {

    @Autowired
    private RabbitTemplate   rt;

    private final String QUEEN_NAME = "MIAOSHA";

    /**
     * 发送消息
     * @param msg
     */
    public void send(String msg)
    {
        rt.convertAndSend(QUEEN_NAME,msg);
    }


}

4.4
以上就是整个业务流程的核心代码,使用redisson保证数据一致性,用rabbitmq异步下单将下单及写数据库这个长操作变成两个短操作。GitHub源码地址,关于数据库建表什么的,大家直接去源码里看吧。

5.优化

展开阅读全文

页面更新:2024-03-06

标签:阿里   商品信息   缓存   业务流程   路径   源码   库存   订单   接口   数量   简单   地址   数据库   时间   数据   用户   系统   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top