Redis中秒杀场景下超时与超卖问题的解决方案

 更新时间:2022年05月27日 16:05:46   作者:红糖番薯  
当我们在linux中使用ab来模拟高并发秒杀时可能会遇到两种问题,“超时和超卖”,本文就详细介绍了Redis中秒杀场景下超时与超卖问题的解决方案,感兴趣的可以了解一下

在开发过程中高并发问题是很棘手的一个问题(对于博主这样的小菜鸡来说),当我们学习redis之前,知道redis是单线程运行的所以任务不会出现线程不安全问题。当我们在linux中使用ab来模拟高并发秒杀时可能会遇到两种问题,“超时和超卖”。

超时

1.redis连接超时原因

(1)虚拟机中的配置问题

我们在测试远程连接时redis连接是否成功时控制台可能会报以下错误。
如下所示:

在这里插入图片描述

每次看到控制台红色的文字我就头疼。。。

在控制台中的显示大概意思是显示连接超时导致了失败。
总结了以下三条连接失败原因:

  • Linux中的防火墙没有关闭而导致失败。
  • redis要打开。
  • redis.conf中的bind 127.0.01需要注释掉,然后 需要修改protected-mode no。

之后如果遇到了以上问题请自行查找。

(2)redis成功连接中模拟在高并发中的超时

如图所示:

在这里插入图片描述

2.解决方法

在MySQL中使用jdbc可能会发现连接超时问题,所以我们使用了数据库连接池来解决问题,例如druid、c3p0等等。同理我们在redis中也可以同样使用数据库连接池。
节省每次连接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实例均是可用的;

超卖

1.秒杀超卖现象

在高并发场景下,多个线程并发更新库存,导致库存为负的情况。

看图幻想:

在这里插入图片描述

2.解决方案

(1)利用乐观锁淘汰用户,解决超卖问题

上图:

在这里插入图片描述

//增加乐观锁
jedis.watch(qtkey);
 
//3.判断库存
String qtkeystr = jedis.get(qtkey);
if(qtkeystr==null || "".equals(qtkeystr.trim())) {
	System.out.println("未初始化库存");
	jedis.close();
	return false ;
}
 
int qt = Integer.parseInt(qtkeystr);
if(qt<=0) {
	System.err.println("已经秒光");
	jedis.close();
	return false;
}
 
//增加事务
Transaction multi = jedis.multi();
 
//4.减少库存
//jedis.decr(qtkey);
multi.decr(qtkey);
 
//5.加人
//jedis.sadd(usrkey, uid);
multi.sadd(usrkey, uid);
 
//执行事务
List<Object> list = multi.exec();
 
//判断事务提交是否失败
if(list==null || list.size()==0) {
	System.out.println("秒杀失败");
	jedis.close();
	return false;
}
System.err.println("秒杀成功");
jedis.close();	

在这里插入图片描述

在这里插入图片描述

方案原理:

(1)当用户购买时,通过watch来监视库存,如果库存在watch监视后发生改变,就会捕获异常而放弃对库存进行减一操作。
(2)如果库存没有监视到变化并且数量大于一时,则库存减一,并且执行任务。
弊端

Redis 在尝试完成一个事务的时候,可能会因为事务的失败而重复尝试重新执行
保证商品的库存量正确是一件很重要的事情,但是单纯的使用 WATCH 这样的机制对服务器压力过大

(2)、使用reids的 watch + multi + setnx 指令实现

为什么要自己构建锁?

虽然有类似的 SETNX 命令可以实现 Redis 中的锁的功能,但他锁提供的机制并不完整
并且setnx也不具备分布式锁的一些高级特性,还是得通过我们手动构建。

(1)创建一个redis锁

在 Redis 中,可以通过使用 SETNX 命令来构建锁:rs.setnx(lock_name, uuid值)
而锁要做的事情就是将一个随机生成的 128 位 UUID 设置位键的值,防止该锁被其他进程获取。

(2)释放锁

锁的删除操作很简单,只需要将对应锁的 key 值获取到的 uuid 结果进行判断验证
符合条件(判断uuid值)通过 delete 在 redis 中删除即可,rs.delete(lockname)
此外当其他用户持有同名锁时,由于 uuid 的不同,经过验证后不会错误释放掉别人的锁.

(3)解决锁无法释放问题

在之前的锁中,还出现这样的问题,比如某个进程持有锁之后突然程序崩溃,那么会导致锁无法释放
而其他进程无法持有锁继续工作,为了解决这样的问题,可以在获取锁的时候加上锁的超时功能。

到此这篇关于Redis中秒杀场景下超时与超卖问题的解决方案的文章就介绍到这了,更多相关Redis 超时与超卖内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • redis中队列消息实现应用解耦的方法

    redis中队列消息实现应用解耦的方法

    这篇文章主要给大家介绍了关于redis中队列消息实现应用解耦的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • 利用控制台如何对Redis执行增删改查命令

    利用控制台如何对Redis执行增删改查命令

    这篇文章主要给大家介绍了关于利用控制台如何对Redis执行增删改查命令的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • 深入理解redis_memcached失效原理(小结)

    深入理解redis_memcached失效原理(小结)

    这篇文章主要介绍了深入理解redis_memcached失效原理(小结),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 利用Redis进行数据缓存的项目实践

    利用Redis进行数据缓存的项目实践

    在实际的业务场景中,Redis 一般和其他数据库搭配使用,用来减轻后端数据库的压力,本文就介绍了利用Redis进行数据缓存的项目实践,具有一定的参考价值,感兴趣的可以了解一下
    2022-06-06
  • Redis持久化策略解读以及如何选择

    Redis持久化策略解读以及如何选择

    这篇文章主要介绍了Redis持久化策略解读以及如何选择问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • Redis链表底层实现及生产实战

    Redis链表底层实现及生产实战

    Redis 的 List 是一个双向链表,链表中的每个节点都包含了一个字符串。是redis中最常用的数据结构之一,本文主要介绍了Redis链表底层实现及生产实战,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • redis实现延时队列的两种方式(小结)

    redis实现延时队列的两种方式(小结)

    这篇文章主要介绍了redis实现延时队列的两种方式(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Redis高并发问题的解决方法

    Redis高并发问题的解决方法

    这篇文章主要介绍了Redis高并发问题的解决办法,具有很好的参考价值,感兴趣的小伙伴们可以参考一下,具体如下:
    2018-05-05
  • Redis哨兵机制的使用详解

    Redis哨兵机制的使用详解

    文章讲解了Redis哨兵机制的基本原理、主库和从库自动切换的过程、如何减少误判、哨兵集群的组成和通信机制,以及哨兵在故障发生时如何选举Leader进行主从切换
    2025-01-01
  • Redis key命令key的储存方式

    Redis key命令key的储存方式

    这篇文章主要介绍了Redis key命令key的储存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04

最新评论