文章目录
rabbitmq
优化秒杀接口,目标:2000并发 QPS 4000
思路:要减少数据库的访问,没必要每次都查询数据库
(1)系统初始化,把商品库存数量加载到redis
(2)收到请求,首先看redis的标志,如果已经结束,直接返回,否则进入(3)
(3)入队缓冲,直接返回,并不是返回成功,而是返回排队中,客户端不能直接提示秒杀成功,而是启动定时器,过一段时间再去查是否成功
(4)出队,修改库存,修改结束标志
安装RabbitMQ
网上有很多教程这里就不赘述了
SpringBoot集成RabbitMQ
1.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.application.properties添加配置
#rabbitmq
spring.rabbitmq.host=192.168.56.101
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
#消费者数量
spring.rabbitmq.listener.simple.concurrency= 10
spring.rabbitmq.listener.simple.max-concurrency= 10
#消费者每次从队列获取的消息数量
spring.rabbitmq.listener.simple.prefetch= 1
#消费者自动启动
spring.rabbitmq.listener.simple.auto-startup=true
#消费失败,自动重新入队
spring.rabbitmq.listener.simple.default-requeue-rejected= true
#启用发送重试
spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=1000
spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.max-interval=10000
spring.rabbitmq.template.retry.multiplier=1.0
spring.rabbitmq.host=192.168.56.101
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
#
spring.rabbitmq.listener.simple.concurrency= 10
spring.rabbitmq.listener.simple.max-concurrency= 10
#
spring.rabbitmq.listener.simple.prefetch= 1
#
spring.rabbitmq.listener.simple.auto-startup=true
#
spring.rabbitmq.listener.simple.default-requeue-rejected= true
#
spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=1000
spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.max-interval=10000
spring.rabbitmq.template.retry.multiplier=1.0
3. MQSender创建发送者
package com.pro.miaosha.rabbitmq;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.pro.miaosha.redis.RedisService;
@Service
public class MQSender {
private static Logger log = LoggerFactory.getLogger(MQSender.class);
@Autowired
AmqpTemplate amqpTemplate ;//操作queue的工具类
public void send(Object message) {
String msg = RedisService.beanToString(message);//把bean => string再放到消息队列中
log.info("send message:"+msg);
amqpTemplate.convertAndSend(MQConfig.QUEUE, msg);
}
//
// public void sendTopic(Object message) {
// String msg = RedisService.beanToString(message);
// log.info("send topic message:"+msg);
// amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE, "topic.key1", msg+"1");
// amqpTemplate.convertAndSend(MQConfig.TOPIC_EXCHANGE, "topic.key2", msg+"2");
// }
//
// public void sendFanout(Object message) {
// String msg = RedisService.beanToString(message);
// log.info("send fanout message:"+msg);
// amqpTemplate.convertAndSend(MQConfig.FANOUT_EXCHANGE, "", msg);
// }
//
// public void sendHeader(Object message) {
// String msg = RedisService.beanToString(message);
// log.info("send fanout message:"+msg);
// MessageProperties properties = new MessageProperties();
// properties.setHeader("header1", "value1");
// properties.setHeader("header2", "value2");
// Message obj = new Message(msg.getBytes(), properties);
// amqpTemplate.convertAndSend(MQConfig.HEADERS_EXCHANGE, "", obj);
// }
}
4.MQReceiver:创建消费者
@Service
public class MQReceiver {
private static Logger log = LoggerFactory.getLogger(MQReceiver.class);
@Autowired
RedisService redisService;
@Autowired
GoodsService goodsService;
@Autowired
OrderService orderService;
@Autowired
MiaoshaService miaoshaService;
@RabbitListener(queues=MQConfig.MIAOSHA_QUEUE)//监听的是哪一个queue
public void receive(String message) {
log.info("receive message:"+message);
MiaoshaMessage mm = RedisService. stringToBean(message, MiaoshaMessage.class);
MiaoshaUser user = mm.getUser();
long goodsId = mm.getGoodsId();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
int stock = goods.getStockCount();
if(stock <= 0) {
return;
}
//判断是否已经秒杀到了
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order != null) {
return;
}
//减库存 下订单 写入秒杀订单
miaoshaService.miaosha(user