1 如何设计一个秒杀系统

2 项目搭建

2.png

2.1 逆向工程

通过逆向工程基于 t_user 表生产对应的POJO、Mapper、Service、ServiceImpl、Controller等类,项目中使用了MybatisPlus,所以逆向工程也是用了MybatisPlus提供的AutoGenerator.

2.2 公共返回对象

  1. //公共返回对象枚举
  2. @Data
  3. @ToString
  4. public enum RespBeanEnum {
  5. //通用
  6. SUCCESS(200, "SUCCESS"),
  7. ERROR(500, "服务端异常"),
  8. //登录模块5002xx
  9. LOGIN_ERROR(500210, "用户名或密码不正确"),
  10. MOBILE_ERROR(500211, "手机号码格式不正确"),
  11. BIND_ERROR(500212, "参数校验异常"),
  12. MOBILE_NOT_EXIST(500213, "手机号码不存在"),
  13. PASSWORD_UPDATE_FAIL(500214, "密码更新失败"),
  14. SESSION_ERROR(500215, "用户不存在"),
  15. //秒杀模块5005xx
  16. EMPTY_STOCK(500500, "库存不足"),
  17. REPEATE_ERROR(500501, "该商品每人限购一件"),
  18. REQUEST_ILLEGAL(500502, "请求非法,请重新尝试"),
  19. ERROR_CAPTCHA(500503, "验证码错误,请重新输入"),
  20. ACCESS_LIMIT_REAHCED(500504, "访问过于频繁,请稍后再试"),
  21. //订单模块5003xx
  22. ORDER_NOT_EXIST(500300, "订单信息不存在"),
  23. ;
  24. private final Integer code;
  25. private final String message;
  26. }
  27. //公共返回对象
  28. @Data
  29. @NoArgsConstructor
  30. @AllArgsConstructor
  31. public class RespBean {
  32. private long code;
  33. private String message;
  34. private Object obj;
  35. /**
  36. * 功能描述: 成功返回结果
  37. */
  38. public static RespBean success(){
  39. return new RespBean(RespBeanEnum.SUCCESS.getCode(),RespBeanEnum.SUCCESS.getMessage(),null);
  40. }
  41. /**
  42. * 功能描述: 成功返回结果
  43. */
  44. public static RespBean success(Object obj){
  45. return new RespBean(RespBeanEnum.SUCCESS.getCode(),RespBean.success().getMessage(),obj);
  46. }
  47. /**
  48. * 功能描述: 失败返回结果
  49. */
  50. public static RespBean error(RespBeanEnum respBeanEnum){
  51. return new RespBean(respBeanEnum.getCode(),respBeanEnum.getMessage(),null);
  52. }
  53. /**
  54. * 功能描述: 失败返回结果
  55. */
  56. public static RespBean error(RespBeanEnum respBeanEnum,Object obj){
  57. return new RespBean(respBeanEnum.getCode(),respBeanEnum.getMessage(),obj);
  58. }
  59. }

3 分布式会话

3.1 实现登陆功能

3.1.1 两次MD5加密

  • 用户端: PASS=MD5(明文+固定Salt)
  • 服务端: PASS=MD5(用户输入+随机Salt)

用户端MD5加密是为了防止用户密码在网络中明文传输,服务端MD5加密是为了提高密码安全性,双重保险,数据库被盗后可能根据加密后的密文和Salt字段反推出明文密码,故存入数据库前再进行一次加密。

引入pom.xml

  1. <!-- md5 依赖 -->
  2. <dependency>
  3. <groupId>commons-codec</groupId>
  4. <artifactId>commons-codec</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.commons</groupId>
  8. <artifactId>commons-lang3</artifactId>
  9. <version>3.6</version>
  10. </dependency>

实现代码

  1. public class MD5Util {
  2. public static String md5(String src){
  3. return DigestUtils.md5Hex(src);
  4. }
  5. private static final String salt="1a2b3c4d";
  6. public static String inputPassToFromPass(String inputPass){
  7. String str = "" +salt.charAt(0)+salt.charAt(2)+inputPass+salt.charAt(5)+salt.charAt(4);
  8. return md5(str);
  9. }
  10. public static String formPassToDBPass(String formPass,String salt){
  11. String str = "" +salt.charAt(0)+salt.charAt(2)+formPass+salt.charAt(5)+salt.charAt(4);
  12. return md5(str);
  13. }
  14. public static String inputPassToDBPass(String inputPass,String salt){
  15. String fromPass = inputPassToFromPass(inputPass);
  16. String dbPass = formPassToDBPass(fromPass, salt);
  17. return dbPass;
  18. }
  19. public static void main(String[] args) {
  20. // d3b1294a61a07da9b49b6e22b2cbd7f9
  21. System.out.println(inputPassToFromPass("123456"));
  22. System.out.println(formPassToDBPass("d3b1294a61a07da9b49b6e22b2cbd7f9","1a2b3c4d"));
  23. System.out.println(inputPassToDBPass("123456","1a2b3c4d"));
  24. }
  25. }

4 秒杀功能

5 系统压测

6 页面优化

7 服务优化

8 安全优化