• 秒杀服务实战


    针对mysql和mongo的两个小例子:

    mysql:

    import com.example.demo.mapper.OrderInfoMapper;
    import com.example.demo.mapper.ProductInfoMapper;
    import com.example.demo.model.OrderInfo;
    import com.example.demo.model.ProductInfo;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.Date;
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    
    @Service
    public class OrderMysqlService {
        @Autowired
        private OrderInfoMapper orderInfoMapper;
        @Autowired
        private ProductInfoMapper productInfoMapper;
    
        //下单
        public boolean insert(){
            Long productId = 22l;//产品id
            int buyCount = 1;//当前用户下单数量
    
            if(updateProductAmount(productId,buyCount)){
    //            if(true){
    //                throw new RuntimeException();
    //            }
                OrderInfo orderInfo = new OrderInfo();
                orderInfo.setStatus(1);
                orderInfo.setCreateTime(new Date());
                return orderInfoMapper.insertSelective(orderInfo) > 0;
            }
            return false;
        }
    
        //秒杀服务,修改库存
        private boolean updateProductAmount(Long productId,int buyCount) {
            ProductInfo productInfo = productInfoMapper.selectByPrimaryKeyByBuyCount(productId,buyCount);
            if (productInfo == null) {
                return false;
            }
    
            if (productInfoMapper.updateByStock(productId, buyCount) > 0) {
                return true;
            }
    
            //如果更新失败,当前线程休眠,错峰执行(同时执行的话,还是只有一个人抢占到资源,别的都失败,所以错峰执行)
            waitForLock();
            return updateProductAmount(productId, buyCount);
        }
    
        private void waitForLock(){
            try {
                TimeUnit.MILLISECONDS.sleep(new Random().nextInt(10) + 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    mongo:副本集mongodb才能支持事物:4.0之后的版本才能支持事物
                4.0支持事物的步骤搭建:https://blog.csdn.net/quanmaoluo5461/article/details/84880850

    import com.example.demo.model.Order;
    import com.example.demo.model.Product;
    import com.mongodb.client.result.UpdateResult;
    import org.bson.types.ObjectId;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.data.mongodb.core.query.Update;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    
    @Service
    public class OrderMongoService {
        @Autowired
        private MongoTemplate mongoTemplate;
    
        //下单 : 副本集mongodb才能支持事物。意思就是至少两个mongo服务。具体操作查看:https://blog.csdn.net/quanmaoluo5461/article/details/84880850
        @Transactional
        public boolean insert(){
            String productId = "5c23a6b4be592e584c8d7c47";//产品id
            int buyCount = 1;//当前用户下单数量
    
            if(updateProductAmount(productId,buyCount)){
    //            if(true){
    //                throw new RuntimeException();
    //            }
                Order order = new Order();
                order.setStatus(1);
                return mongoTemplate.insert(order).getId() != null;
            }
            return false;
        }
    
        //秒杀服务,修改库存
        private boolean updateProductAmount(String productId,int buyCount) {
            Criteria criteria = Criteria.where("id").is(new ObjectId(productId))
                    .and("stock").gte(buyCount);
            Query query = new Query(criteria);
            Product product = mongoTemplate.findOne(query,Product.class);
            if (product == null) {
                return false;
            }
    
            Update update = new Update();
            update.inc("stock", -buyCount);
            UpdateResult updateResult= mongoTemplate.updateFirst(query, update, Product.class);
            if(updateResult.getModifiedCount() > 0){
                return true;
            }
    
            //如果更新失败,当前线程休眠,错峰执行(同时执行的话,还是只有一个人抢占到资源,别的都失败,所以错峰执行)
            waitForLock();
            return updateProductAmount(productId, buyCount);
        }
    
        private void waitForLock(){
            try {
                TimeUnit.MILLISECONDS.sleep(new Random().nextInt(10) + 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    源码地址:https://github.com/qjm201000/seckill.git

    说明:mysql的sql文件(concurrent.sql)放在项目跟目录下;mongodb的数据库文件纯json字符串,未备份,数据结构和mysql一样。

  • 相关阅读:
    localStorage和sessionStorage的使用方法和一些特性介绍
    python 图片添加水印 pdf 添加水印
    python kayb算法之从一组序列当中获取一组与目标值最接近的算法
    python 中将字符串加载为公钥
    Python中rsa模块【sign 加签验签】的使用
    python中openpyxl的用法【安装,以及一些基本的操作, xlwt教程链接】
    python当中的坑【闭包与lambda】
    python函数参数中带有默认参数list的坑
    Django中辅助技术总结[静态文件,中间件,上传图片,分页案例]
    Django中视图总结[urls匹配,HttpRequest对象,HttpResponse对象,对象序列化接受及案例]
  • 原文地址:https://www.cnblogs.com/qjm201000/p/10184616.html
Copyright © 2020-2023  润新知