基于rocketMq秒杀系统demo
生活随笔
收集整理的這篇文章主要介紹了
基于rocketMq秒杀系统demo
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
基于RocketMQ設計秒殺。
要求:
1.?????秒殺商品LagouPhone,數量100個。
2.?????秒殺商品不能超賣。
3.?????搶購鏈接隱藏
4.?????Nginx+Redis+RocketMQ+Tomcat+MySQL
?
?
實現
接口說明:https://www.liuchengtu.com/swdt/#R9f978d0d00ef9be99f00258c3035b648
實現代碼:
訂單接口:
package com.lagou.rocket.controller;import com.alibaba.fastjson.JSONObject; import com.google.common.util.concurrent.RateLimiter; import com.lagou.rocket.service.OrderService; import com.lagou.rocket.service.StockService; import com.lagou.rocket.service.UserService; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;import java.util.concurrent.ExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;@Controller public class OrderController {private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);@Autowiredprivate OrderService orderService;@Autowiredprivate UserService userService;@Autowiredprivate StockService stockService;@Autowiredprivate RocketMQTemplate rocketMQTemplate;// Guava令牌桶:每秒放行10個請求RateLimiter rateLimiter = RateLimiter.create(10);// 延時時間:預估讀數據庫數據業務邏輯的耗時,用來做緩存再刪除private static final int DELAY_MILLSECONDS = 1000;// 延時雙刪線程池private static ExecutorService cachedThreadPool = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());/*** 下單接口:導致超賣的錯誤示范* @param sid* @return*/@RequestMapping("/createWrongOrder/{sid}")@ResponseBodypublic String createWrongOrder(@PathVariable int sid) {int id = 0;try {id = orderService.createWrongOrder(sid);LOGGER.info("創建訂單id: [{}]", id);} catch (Exception e) {LOGGER.error("Exception", e);}return String.valueOf(id);}/*** 下單接口:樂觀鎖更新庫存 + 令牌桶限流* @param sid* @return*/@RequestMapping("/createOptimisticOrder/{sid}")@ResponseBodypublic String createOptimisticOrder(@PathVariable int sid) {// 1. 阻塞式獲取令牌LOGGER.info("等待時間" + rateLimiter.acquire());// 2. 非阻塞式獲取令牌 // if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) { // LOGGER.warn("你被限流了,真不幸,直接返回失敗"); // return "你被限流了,真不幸,直接返回失敗"; // }int id;try {id = orderService.createOptimisticOrder(sid);LOGGER.info("購買成功,剩余庫存為: [{}]", id);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}return String.format("購買成功,剩余庫存為:%d", id);}/*** 下單接口:悲觀鎖更新庫存 事務for update更新庫存* @param sid* @return*/@RequestMapping("/createPessimisticOrder/{sid}")@ResponseBodypublic String createPessimisticOrder(@PathVariable int sid) {int id;try {id = orderService.createPessimisticOrder(sid);LOGGER.info("購買成功,剩余庫存為: [{}]", id);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}return String.format("購買成功,剩余庫存為:%d", id);}/*** 驗證接口:下單前用戶獲取驗證值* @return*/@RequestMapping(value = "/getVerifyHash", method = {RequestMethod.GET})@ResponseBodypublic String getVerifyHash(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId) {String hash;try {hash = userService.getVerifyHash(sid, userId);} catch (Exception e) {LOGGER.error("獲取驗證hash失敗,原因:[{}]", e.getMessage());return "獲取驗證hash失敗";}return hash;}/*** 下單接口:要求用戶驗證的搶購接口* @param sid* @return*/@RequestMapping(value = "/createOrderWithVerifiedUrl", method = {RequestMethod.GET})@ResponseBodypublic String createOrderWithVerifiedUrl(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId,@RequestParam(value = "verifyHash") String verifyHash) {int stockLeft;try {stockLeft = orderService.createVerifiedOrder(sid, userId, verifyHash);LOGGER.info("購買成功,剩余庫存為: [{}]", stockLeft);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return e.getMessage();}return "ok";}/*** 下單接口:要求用戶驗證的搶購接口* @param sid* @return*/@RequestMapping(value = "/pay", method = {RequestMethod.GET})@ResponseBodypublic String pay(@RequestParam(value = "sid") Integer sid, @RequestParam(value = "userId") Integer userId) {return orderService.pay(sid,userId);}/*** 下單接口:要求驗證的搶購接口 + 單用戶限制訪問頻率* @param sid* @return*/@RequestMapping(value = "/createOrderWithVerifiedUrlAndLimit", method = {RequestMethod.GET})@ResponseBodypublic String createOrderWithVerifiedUrlAndLimit(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId,@RequestParam(value = "verifyHash") String verifyHash) {int stockLeft;try {int count = userService.addUserCount(userId);LOGGER.info("用戶截至該次的訪問次數為: [{}]", count);boolean isBanned = userService.getUserIsBanned(userId);if (isBanned) {return "購買失敗,超過頻率限制";}stockLeft = orderService.createVerifiedOrder(sid, userId, verifyHash);LOGGER.info("購買成功,剩余庫存為: [{}]", stockLeft);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return e.getMessage();}return String.format("購買成功,剩余庫存為:%d", stockLeft);}/*** 下單接口:先刪除緩存,再更新數據庫* @param sid* @return*/@RequestMapping("/createOrderWithCacheV1/{sid}")@ResponseBodypublic String createOrderWithCacheV1(@PathVariable int sid) {int count = 0;try {// 刪除庫存緩存stockService.delStockCountCache(sid);// 完成扣庫存下單事務orderService.createPessimisticOrder(sid);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}LOGGER.info("購買成功,剩余庫存為: [{}]", count);return String.format("購買成功,剩余庫存為:%d", count);}/*** 下單接口:先更新數據庫,再刪緩存* @param sid* @return*/@RequestMapping("/createOrderWithCacheV2/{sid}")@ResponseBodypublic String createOrderWithCacheV2(@PathVariable int sid) {int count = 0;try {// 完成扣庫存下單事務orderService.createPessimisticOrder(sid);// 刪除庫存緩存stockService.delStockCountCache(sid);} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}LOGGER.info("購買成功,剩余庫存為: [{}]", count);return String.format("購買成功,剩余庫存為:%d", count);}/*** 下單接口:先刪除緩存,再更新數據庫,緩存延時雙刪* @param sid* @return*/@RequestMapping("/createOrderWithCacheV3/{sid}")@ResponseBodypublic String createOrderWithCacheV3(@PathVariable int sid) {int count;try {// 刪除庫存緩存stockService.delStockCountCache(sid);// 完成扣庫存下單事務count = orderService.createPessimisticOrder(sid);LOGGER.info("完成下單事務");// 延時指定時間后再次刪除緩存cachedThreadPool.execute(new delCacheByThread(sid));} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}LOGGER.info("購買成功,剩余庫存為: [{}]", count);return String.format("購買成功,剩余庫存為:%d", count);}/*** 下單接口:先更新數據庫,再刪緩存,刪除緩存失敗重試,通知消息隊列* @param sid* @return*/@RequestMapping("/createOrderWithCacheV4/{sid}")@ResponseBodypublic String createOrderWithCacheV4(@PathVariable int sid) {int count;try {// 完成扣庫存下單事務count = orderService.createPessimisticOrder(sid);LOGGER.info("完成下單事務");// 刪除庫存緩存stockService.delStockCountCache(sid);// 延時指定時間后再次刪除緩存// cachedThreadPool.execute(new delCacheByThread(sid));// 假設上述再次刪除緩存沒成功,通知消息隊列進行刪除緩存sendToDelCache(String.valueOf(sid));} catch (Exception e) {LOGGER.error("購買失敗:[{}]", e.getMessage());return "購買失敗,庫存不足";}LOGGER.info("購買成功,剩余庫存為: [{}]", count);return "購買成功";}/*** 下單接口:異步處理訂單* @param sid* @return*/@RequestMapping(value = "/createOrderWithMq", method = {RequestMethod.GET})@ResponseBodypublic String createOrderWithMq(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId) {try {// 檢查緩存中商品是否還有庫存Integer count = stockService.getStockCount(sid);if (count == 0) {return "秒殺請求失敗,庫存不足.....";}// 有庫存,則將用戶id和商品id封裝為消息體傳給消息隊列處理// 注意這里的有庫存和已經下單都是緩存中的結論,存在不可靠性,在消息隊列中會查表再次驗證LOGGER.info("有庫存:[{}]", count);JSONObject jsonObject = new JSONObject();jsonObject.put("sid", sid);jsonObject.put("userId", userId);sendToOrderQueue(jsonObject.toJSONString());return "秒殺請求提交成功";} catch (Exception e) {LOGGER.error("下單接口:異步處理訂單異常:", e);return "秒殺請求失敗,服務器正忙.....";}}/*** 下單接口:異步處理訂單* @param sid* @return*/@RequestMapping(value = "/createUserOrderWithMq", method = {RequestMethod.GET})@ResponseBodypublic String createUserOrderWithMq(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId) {try {// 檢查緩存中該用戶是否已經下單過Boolean hasOrder = orderService.checkUserOrderInfoInCache(sid, userId);if (hasOrder != null && hasOrder) {LOGGER.info("該用戶已經搶購過");return "你已經搶購過了,不要太貪心.....";}// 沒有下單過,檢查緩存中商品是否還有庫存LOGGER.info("沒有搶購過,檢查緩存中商品是否還有庫存");Integer count = stockService.getStockCount(sid);if (count == 0) {return "秒殺請求失敗,庫存不足.....";}// 有庫存,則將用戶id和商品id封裝為消息體傳給消息隊列處理// 注意這里的有庫存和已經下單都是緩存中的結論,存在不可靠性,在消息隊列中會查表再次驗證LOGGER.info("有庫存:[{}]", count);JSONObject jsonObject = new JSONObject();jsonObject.put("sid", sid);jsonObject.put("userId", userId);sendToOrderQueue(jsonObject.toJSONString());return "秒殺請求提交成功";} catch (Exception e) {LOGGER.error("下單接口:異步處理訂單異常:", e);return "秒殺請求失敗,服務器正忙.....";}}/*** 檢查緩存中用戶是否已經生成訂單* @param sid* @return*/@RequestMapping(value = "/checkOrderByUserIdInCache", method = {RequestMethod.GET})@ResponseBodypublic String checkOrderByUserIdInCache(@RequestParam(value = "sid") Integer sid,@RequestParam(value = "userId") Integer userId) {// 檢查緩存中該用戶是否已經下單過try {Boolean hasOrder = orderService.checkUserOrderInfoInCache(sid, userId);if (hasOrder != null && hasOrder) {return "恭喜您,已經搶購成功!";}} catch (Exception e) {LOGGER.error("檢查訂單異常:", e);}return "很抱歉,你的訂單尚未生成,繼續排隊。";}/*** 緩存再刪除線程*/private class delCacheByThread implements Runnable {private int sid;public delCacheByThread(int sid) {this.sid = sid;}public void run() {try {LOGGER.info("異步執行緩存再刪除,商品id:[{}], 首先休眠:[{}] 毫秒", sid, DELAY_MILLSECONDS);Thread.sleep(DELAY_MILLSECONDS);stockService.delStockCountCache(sid);LOGGER.info("再次刪除商品id:[{}] 緩存", sid);} catch (Exception e) {LOGGER.error("delCacheByThread執行出錯", e);}}}/*** 向消息隊列delCache發送消息* @param message*/private void sendToDelCache(String message) {LOGGER.info("這就去通知消息隊列開始重試刪除緩存:[{}]", message); // this.rabbitTemplate.convertAndSend("delCache", message);// 用于向broker發送消息// 第一個參數是topic名稱// 第二個參數是消息內容this.rocketMQTemplate.convertAndSend("tp_springboot_01",message);}/*** 向消息隊列orderQueue發送消息* @param message*/private void sendToOrderQueue(String message) {LOGGER.info("這就去通知消息隊列開始下單:[{}]", message); // this.rabbitTemplate.convertAndSend("orderQueue", message);// 用于向broker發送消息// 第一個參數是topic名稱// 第二個參數是消息內容this.rocketMQTemplate.convertAndSend("tp_springboot_01",message);}@GetMapping("/send")@ResponseBodypublic void testSendMessage() {// 用于向broker發送消息// 第一個參數是topic名稱// 第二個參數是消息內容this.rocketMQTemplate.convertAndSend("tp_springboot_01","springboot: hello lagou2222222222222222");}}庫存接口:
package com.lagou.rocket.controller;import com.lagou.rocket.service.StockService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;@Controller public class StockController {private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);@Autowiredprivate StockService stockService;/*** 查詢庫存:通過數據庫查詢庫存* @param sid* @return*/@RequestMapping("/getStockByDB/{sid}")@ResponseBodypublic String getStockByDB(@PathVariable int sid) {int count;try {count = stockService.getStockCountByDB(sid);} catch (Exception e) {LOGGER.error("查詢庫存失敗:[{}]", e.getMessage());return "查詢庫存失敗";}LOGGER.info("商品Id: [{}] 剩余庫存為: [{}]", sid, count);return String.format("商品Id: %d 剩余庫存為:%d", sid, count);}/*** 查詢庫存:通過緩存查詢庫存* 緩存命中:返回庫存* 緩存未命中:查詢數據庫寫入緩存并返回* @param sid* @return*/@RequestMapping("/getStockByCache/{sid}")@ResponseBodypublic String getStockByCache(@PathVariable int sid) {Integer count;try {count = stockService.getStockCount(sid);} catch (Exception e) {LOGGER.error("查詢庫存失敗:[{}]", e.getMessage());return "查詢庫存失敗";}LOGGER.info("商品Id: [{}] 剩余庫存為: [{}]", sid, count);return String.format("商品Id: %d 剩余庫存為:%d", sid, count);}@RequestMapping("/static/home")public String toHome(Model model){return "home";} }業務處理:
訂單服務:
package com.lagou.rocket.service.impl;import com.lagou.rocket.entity.Stock; import com.lagou.rocket.entity.User; import com.lagou.rocket.mapper.UserMapper; import com.lagou.rocket.service.StockService; import com.lagou.rocket.service.UserService; import com.lagou.rocket.utils.CacheKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils;import java.util.concurrent.TimeUnit;@Service public class UserServiceImpl implements UserService {private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);private static final String SALT = "randomString";private static final int ALLOW_COUNT = 10;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate UserMapper userMapper;@Autowiredprivate StockService stockService;@Overridepublic String getVerifyHash(Integer sid, Integer userId) throws Exception {// 驗證是否在搶購時間內 // LOGGER.info("請自行驗證是否在搶購時間內");// 檢查用戶合法性User user = userMapper.selectByPrimaryKey(userId.longValue());if (user == null) {throw new Exception("用戶不存在");}LOGGER.info("用戶信息:[{}]", user.toString());// 檢查商品合法性Stock stock = stockService.getStockById(sid);if (stock == null) {throw new Exception("商品不存在");}LOGGER.info("商品信息:[{}]", stock.toString());// 生成hashString verify = SALT + sid + userId;String verifyHash = DigestUtils.md5DigestAsHex(verify.getBytes());// 將hash和用戶商品信息存入redisString hashKey = CacheKey.HASH_KEY.getKey() + "_" + sid + "_" + userId;stringRedisTemplate.opsForValue().set(hashKey, verifyHash, 3600, TimeUnit.SECONDS);LOGGER.info("Redis寫入:[{}] [{}]", hashKey, verifyHash);return verifyHash;}@Overridepublic int addUserCount(Integer userId) throws Exception {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);int limit = -1;if (limitNum == null) {stringRedisTemplate.opsForValue().set(limitKey, "0", 3600, TimeUnit.SECONDS);} else {limit = Integer.parseInt(limitNum) + 1;stringRedisTemplate.opsForValue().set(limitKey, String.valueOf(limit), 3600, TimeUnit.SECONDS);}return limit;}@Overridepublic boolean getUserIsBanned(Integer userId) {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);if (limitNum == null) {LOGGER.error("該用戶沒有訪問申請驗證值記錄,疑似異常");return true;}return Integer.parseInt(limitNum) > ALLOW_COUNT;} }用戶服務:
package com.lagou.rocket.service.impl;import com.lagou.rocket.entity.Stock; import com.lagou.rocket.entity.User; import com.lagou.rocket.mapper.UserMapper; import com.lagou.rocket.service.StockService; import com.lagou.rocket.service.UserService; import com.lagou.rocket.utils.CacheKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils;import java.util.concurrent.TimeUnit;@Service public class UserServiceImpl implements UserService {private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);private static final String SALT = "randomString";private static final int ALLOW_COUNT = 10;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate UserMapper userMapper;@Autowiredprivate StockService stockService;@Overridepublic String getVerifyHash(Integer sid, Integer userId) throws Exception {// 驗證是否在搶購時間內 // LOGGER.info("請自行驗證是否在搶購時間內");// 檢查用戶合法性User user = userMapper.selectByPrimaryKey(userId.longValue());if (user == null) {throw new Exception("用戶不存在");}LOGGER.info("用戶信息:[{}]", user.toString());// 檢查商品合法性Stock stock = stockService.getStockById(sid);if (stock == null) {throw new Exception("商品不存在");}LOGGER.info("商品信息:[{}]", stock.toString());// 生成hashString verify = SALT + sid + userId;String verifyHash = DigestUtils.md5DigestAsHex(verify.getBytes());// 將hash和用戶商品信息存入redisString hashKey = CacheKey.HASH_KEY.getKey() + "_" + sid + "_" + userId;stringRedisTemplate.opsForValue().set(hashKey, verifyHash, 3600, TimeUnit.SECONDS);LOGGER.info("Redis寫入:[{}] [{}]", hashKey, verifyHash);return verifyHash;}@Overridepublic int addUserCount(Integer userId) throws Exception {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);int limit = -1;if (limitNum == null) {stringRedisTemplate.opsForValue().set(limitKey, "0", 3600, TimeUnit.SECONDS);} else {limit = Integer.parseInt(limitNum) + 1;stringRedisTemplate.opsForValue().set(limitKey, String.valueOf(limit), 3600, TimeUnit.SECONDS);}return limit;}@Overridepublic boolean getUserIsBanned(Integer userId) {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);if (limitNum == null) {LOGGER.error("該用戶沒有訪問申請驗證值記錄,疑似異常");return true;}return Integer.parseInt(limitNum) > ALLOW_COUNT;} }庫存服務:
package com.lagou.rocket.service.impl;import com.lagou.rocket.entity.Stock; import com.lagou.rocket.entity.User; import com.lagou.rocket.mapper.UserMapper; import com.lagou.rocket.service.StockService; import com.lagou.rocket.service.UserService; import com.lagou.rocket.utils.CacheKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils;import java.util.concurrent.TimeUnit;@Service public class UserServiceImpl implements UserService {private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);private static final String SALT = "randomString";private static final int ALLOW_COUNT = 10;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate UserMapper userMapper;@Autowiredprivate StockService stockService;@Overridepublic String getVerifyHash(Integer sid, Integer userId) throws Exception {// 驗證是否在搶購時間內 // LOGGER.info("請自行驗證是否在搶購時間內");// 檢查用戶合法性User user = userMapper.selectByPrimaryKey(userId.longValue());if (user == null) {throw new Exception("用戶不存在");}LOGGER.info("用戶信息:[{}]", user.toString());// 檢查商品合法性Stock stock = stockService.getStockById(sid);if (stock == null) {throw new Exception("商品不存在");}LOGGER.info("商品信息:[{}]", stock.toString());// 生成hashString verify = SALT + sid + userId;String verifyHash = DigestUtils.md5DigestAsHex(verify.getBytes());// 將hash和用戶商品信息存入redisString hashKey = CacheKey.HASH_KEY.getKey() + "_" + sid + "_" + userId;stringRedisTemplate.opsForValue().set(hashKey, verifyHash, 3600, TimeUnit.SECONDS);LOGGER.info("Redis寫入:[{}] [{}]", hashKey, verifyHash);return verifyHash;}@Overridepublic int addUserCount(Integer userId) throws Exception {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);int limit = -1;if (limitNum == null) {stringRedisTemplate.opsForValue().set(limitKey, "0", 3600, TimeUnit.SECONDS);} else {limit = Integer.parseInt(limitNum) + 1;stringRedisTemplate.opsForValue().set(limitKey, String.valueOf(limit), 3600, TimeUnit.SECONDS);}return limit;}@Overridepublic boolean getUserIsBanned(Integer userId) {String limitKey = CacheKey.LIMIT_KEY.getKey() + "_" + userId;String limitNum = stringRedisTemplate.opsForValue().get(limitKey);if (limitNum == null) {LOGGER.error("該用戶沒有訪問申請驗證值記錄,疑似異常");return true;}return Integer.parseInt(limitNum) > ALLOW_COUNT;} }緩存服務:
package com.lagou.rocket.service.impl;import com.alibaba.fastjson.JSON; import com.lagou.rocket.service.JedisService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.GeoRadiusResponse; import redis.clients.jedis.JedisCluster;import java.util.List; import java.util.Map;@Service public class JedisServiceImpl implements JedisService {@Autowiredprivate JedisCluster jedisCluster;@Overridepublic boolean exists(String key) {boolean flag = false;flag = jedisCluster.exists(key);return flag;}@Overridepublic String set(String key, String value, int seconds) {String responseResult = jedisCluster.set(key,value);if(seconds!=0)jedisCluster.expire(key,seconds);return responseResult;}@Overridepublic String getSet(String key, String value, int seconds) {String jedisClusterSet = jedisCluster.getSet(key, value);jedisCluster.expire(key,seconds);return jedisClusterSet;}@Overridepublic String get(String key) {String str = jedisCluster.get(key);return str;}@Overridepublic Long geoadd(String key, double longitude, double latitude, byte[] obj) {return null;}@Overridepublic List<GeoRadiusResponse> georadius(String key, double longitude, double latitude) {return null;}@Overridepublic void delKey(String key) {jedisCluster.del(key);}@Overridepublic void delNativeKey(String key) {jedisCluster.del(key);}@Overridepublic Map<String, Object> getMapData(String key) {String str = jedisCluster.get(key);Map<String,Object> map = JSON.parseObject(str, Map.class);return map;}/*** @Description: 如為第一次,則加上鎖,每次調用值會自動加1* @Param:* @return:* @Author:*/@Overridepublic boolean lock(String key, int seconds) {if(jedisCluster.incr(key)==1) {jedisCluster.expire(key,seconds);return false;}return true;}@Overridepublic void unlock(String key) {jedisCluster.del(key);}@Overridepublic String getLocakValue(String key) {return jedisCluster.get(key);}}緩存鍵值:
package com.lagou.rocket.utils;public enum CacheKey {HASH_KEY("miaosha_v1_user_hash"),LIMIT_KEY("miaosha_v1_user_limit"),STOCK_COUNT("miaosha_v1_stock_count"),USER_HAS_ORDER("miaosha_v1_user_has_order");private String key;private CacheKey(String key) {this.key = key;}public String getKey() {return key;} }?
總結
以上是生活随笔為你收集整理的基于rocketMq秒杀系统demo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 判断对象所有属性是否全部为空
- 下一篇: sparkSession常见参数设置