使用工具 ab 模拟测试:
CentOS6 默认安装
CentOS7 需要手动安装
通过 ab 测试
im postfile 模拟表单提交参数, 以 & 符号结尾,存放当前目录。
内容:prodid=0101&
执行:ab -n 2000 -c 200 -k -p ~/postfile -T application/x-www-form-urlencoded
访问:http://192.168.2.115:8081/Seckill/doseckill
超卖
利用乐观锁淘汰用户,解决超卖问题。
主要代码:
- 1. public class SecKill_redis {
- 2.
- 3. public static void main(String[] args) {
- 4. Jedis jedis =new Jedis("192.168.44.168",6379);
- 5. System.out.println(jedis.ping());
- 6. jedis.close();
- 7. }
- 8.
- 9. //秒杀过程
- 10. public static boolean doSecKill(String uid,String prodid) throws IOException {
- 11. //1 uid和prodid非空判断
- 12. if(uid == null || prodid == null) {
- 13. return false;
- 14. }
- 15.
- 16. //2 连接redis
- 17. //Jedis jedis = new Jedis("192.168.44.168",6379);
- 18. //通过连接池得到jedis对象
- 19. JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
- 20. Jedis jedis = jedisPoolInstance.getResource();
- 21.
- 22. //3 拼接key
- 23. // 3.1 库存key
- 24. String kcKey = "sk:"+prodid+":qt";
- 25. // 3.2 秒杀成功用户key
- 26. String userKey = "sk:"+prodid+":user";
- 27.
- 28. //监视库存
- 29. jedis.watch(kcKey);
- 30.
- 31. //4 获取库存,如果库存null,秒杀还没有开始
- 32. String kc = jedis.get(kcKey);
- 33. if(kc == null) {
- 34. System.out.println("秒杀还没有开始,请等待");
- 35. jedis.close();
- 36. return false;
- 37. }
- 38.
- 39. // 5 判断用户是否重复秒杀操作
- 40. if(jedis.sismember(userKey, uid)) {
- 41. System.out.println("已经秒杀成功了,不能重复秒杀");
- 42. jedis.close();
- 43. return false;
- 44. }
- 45.
- 46. //6 判断如果商品数量,库存数量小于1,秒杀结束
- 47. if(Integer.parseInt(kc)<=0) {
- 48. System.out.println("秒杀已经结束了");
- 49. jedis.close();
- 50. return false;
- 51. }
- 52.
- 53. //7 秒杀过程
- 54. //使用事务
- 55. Transaction multi = jedis.multi();
- 56.
- 57. //组队操作
- 58. multi.decr(kcKey);
- 59. multi.sadd(userKey,uid);
- 60.
- 61. //执行
- 62. List
- 63.
- 64. if(results == null || results.size()==0) {
- 65. System.out.println("秒杀失败了....");
- 66. jedis.close();
- 67. return false;
- 68. }
- 69.
- 70. //7.1 库存-1
- 71. //jedis.decr(kcKey);
- 72. //7.2 把秒杀成功用户添加清单里面
- 73. //jedis.sadd(userKey,uid);
- 74.
- 75. System.out.println("秒杀成功了..");
- 76. jedis.close();
- 77. return true;
- 78. }
- 79. }
-
-
-
连接有限制
增加 - r 参数,-r Don’t exit on socket receive errors。
已经秒光,可是还有库存
已经秒光,可是还有库存。原因:乐观锁导致很多请求都失败。先点的没秒到,后点的可能秒到了。
连接超时,通过连接池解决
节省每次连接 redis 服务带来的消耗,把连接好的实例反复利用。通过参数管理连接的行为,代码见项目中:
连接池参数:
MaxTotal:控制一个 pool 可分配多少个 jedis 实例,通过 pool.getResource () 来获取;如果赋值为 - 1,则表示不限制;如果 pool 已经分配了 MaxTotal 个 jedis 实例,则此时 pool 的状态为 exhausted。
maxIdle:控制一个 pool 最多有多少个状态为 idle (空闲) 的 jedis 实例;
MaxWaitMillis:表示当 borrow 一个 jedis 实例时,最大的等待毫秒数,如果超过等待时间,则直接抛 JedisConnectionException;
testOnBorrow:获得一个 jedis 实例的时候是否检查连接可用性(ping ());如果为 true,则得到的 jedis 实例均是可用的。
LUA 脚本在 Redis 中的优势