From dcb60e0d3cd8a28bac1bb248e6bc87f9a20da52f Mon Sep 17 00:00:00 2001 From: "zhipeng.zhang" <345849402@qq.com> Date: Sat, 12 Oct 2019 16:22:49 +0800 Subject: [PATCH] =?UTF-8?q?:ambulance:redis=E9=98=9F=E5=88=97=E8=B6=85?= =?UTF-8?q?=E5=8D=96=E6=83=85=E5=86=B5=E7=9A=84=E5=88=86=E6=9E=90=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seckill/queue/redis/RedisConsumer.java | 76 +++++++++--------- .../queue/redis/RedisSubListenerConfig.java | 78 +++++++++++-------- .../seckill/web/SeckillPageController.java | 2 +- 3 files changed, 87 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/itstyle/seckill/queue/redis/RedisConsumer.java b/src/main/java/com/itstyle/seckill/queue/redis/RedisConsumer.java index 17dd614..53804ab 100644 --- a/src/main/java/com/itstyle/seckill/queue/redis/RedisConsumer.java +++ b/src/main/java/com/itstyle/seckill/queue/redis/RedisConsumer.java @@ -1,38 +1,40 @@ -package com.itstyle.seckill.queue.redis; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.itstyle.seckill.common.entity.Result; -import com.itstyle.seckill.common.enums.SeckillStatEnum; -import com.itstyle.seckill.common.redis.RedisUtil; -import com.itstyle.seckill.common.webSocket.WebSocketServer; -import com.itstyle.seckill.service.ISeckillService; -/** - * 消费者 - * @author 科帮网 By https://blog.52itstyle.com - */ -@Service -public class RedisConsumer { - - @Autowired - private ISeckillService seckillService; - @Autowired - private RedisUtil redisUtil; - - public void receiveMessage(String message) { - //收到通道的消息之后执行秒杀操作(超卖) - String[] array = message.split(";"); - if(redisUtil.getValue(array[0])==null){//control层已经判断了,其实这里不需要再判断了 - Result result = seckillService.startSeckilDBPCC_TWO(Long.parseLong(array[0]), Long.parseLong(array[1])); - if(result.equals(Result.ok(SeckillStatEnum.SUCCESS))){ - WebSocketServer.sendInfo(array[0].toString(), "秒杀成功");//推送给前台 - }else{ - WebSocketServer.sendInfo(array[0].toString(), "秒杀失败");//推送给前台 - redisUtil.cacheValue(array[0], "ok");//秒杀结束 - } - }else{ - WebSocketServer.sendInfo(array[0].toString(), "秒杀失败");//推送给前台 - } - } +package com.itstyle.seckill.queue.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.itstyle.seckill.common.entity.Result; +import com.itstyle.seckill.common.enums.SeckillStatEnum; +import com.itstyle.seckill.common.redis.RedisUtil; +import com.itstyle.seckill.common.webSocket.WebSocketServer; +import com.itstyle.seckill.service.ISeckillService; +/** + * 消费者 + * @author 科帮网 By https://blog.52itstyle.vip + */ +@Service +public class RedisConsumer { + + @Autowired + private ISeckillService seckillService; + @Autowired + private RedisUtil redisUtil; + + public void receiveMessage(String message) { + Thread th=Thread.currentThread(); + System.out.println("Tread name:"+th.getName()); + //收到通道的消息之后执行秒杀操作(超卖) + String[] array = message.split(";"); + if(redisUtil.getValue(array[0])==null){//control层已经判断了,其实这里不需要再判断了 + Result result = seckillService.startSeckilDBPCC_TWO(Long.parseLong(array[0]), Long.parseLong(array[1])); + if(result.equals(Result.ok(SeckillStatEnum.SUCCESS))){ + WebSocketServer.sendInfo(array[0], "秒杀成功");//推送给前台 + }else{ + WebSocketServer.sendInfo(array[0], "秒杀失败");//推送给前台 + redisUtil.cacheValue(array[0], "ok");//秒杀结束 + } + }else{ + WebSocketServer.sendInfo(array[0], "秒杀失败");//推送给前台 + } + } } \ No newline at end of file diff --git a/src/main/java/com/itstyle/seckill/queue/redis/RedisSubListenerConfig.java b/src/main/java/com/itstyle/seckill/queue/redis/RedisSubListenerConfig.java index d0a90b2..aa42565 100644 --- a/src/main/java/com/itstyle/seckill/queue/redis/RedisSubListenerConfig.java +++ b/src/main/java/com/itstyle/seckill/queue/redis/RedisSubListenerConfig.java @@ -1,32 +1,48 @@ -package com.itstyle.seckill.queue.redis; - -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.StringRedisTemplate; -import org.springframework.data.redis.listener.PatternTopic; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; - -@Configuration -public class RedisSubListenerConfig { - //初始化监听器 - @Bean - RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, - MessageListenerAdapter listenerAdapter) { - RedisMessageListenerContainer container = new RedisMessageListenerContainer(); - container.setConnectionFactory(connectionFactory); - container.addMessageListener(listenerAdapter, new PatternTopic("seckill")); - return container; - } - //利用反射来创建监听到消息之后的执行方法 - @Bean - MessageListenerAdapter listenerAdapter(RedisConsumer redisReceiver) { - return new MessageListenerAdapter(redisReceiver, "receiveMessage"); - } - //使用默认的工厂初始化redis操作模板 - @Bean - StringRedisTemplate template(RedisConnectionFactory connectionFactory) { - return new StringRedisTemplate(connectionFactory); - } +package com.itstyle.seckill.queue.redis; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +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.StringRedisTemplate; +import org.springframework.data.redis.listener.PatternTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; + +import java.util.concurrent.*; + +@Configuration +public class RedisSubListenerConfig { + //初始化监听器 + @Bean + RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, + MessageListenerAdapter listenerAdapter) { + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + container.addMessageListener(listenerAdapter, new PatternTopic("seckill")); + /** + * 如果不定义线程池,每一次消费都会创建一个线程,如果业务层面不做限制,就会导致秒杀超卖 + */ + ThreadFactory factory = new ThreadFactoryBuilder() + .setNameFormat("redis-listener-pool-%d").build(); + Executor executor = new ThreadPoolExecutor( + 1, + 1, + 5L, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1000), + factory); + container.setTaskExecutor(executor); + return container; + } + //利用反射来创建监听到消息之后的执行方法 + @Bean + MessageListenerAdapter listenerAdapter(RedisConsumer redisReceiver) { + return new MessageListenerAdapter(redisReceiver, "receiveMessage"); + } + //使用默认的工厂初始化redis操作模板 + @Bean + StringRedisTemplate template(RedisConnectionFactory connectionFactory) { + return new StringRedisTemplate(connectionFactory); + } } \ No newline at end of file diff --git a/src/main/java/com/itstyle/seckill/web/SeckillPageController.java b/src/main/java/com/itstyle/seckill/web/SeckillPageController.java index 63c34bd..2e79e06 100644 --- a/src/main/java/com/itstyle/seckill/web/SeckillPageController.java +++ b/src/main/java/com/itstyle/seckill/web/SeckillPageController.java @@ -55,7 +55,7 @@ public class SeckillPageController { return Result.ok(List); } - @RequestMapping("/startSeckill") + @PostMapping("/startSeckill") public Result startSeckill(String ticket,String randstr,HttpServletRequest request) { HttpMethod method =HttpMethod.POST; MultiValueMap params= new LinkedMultiValueMap();