比特派钱包app官网|超卖
什么是超买超卖? - 知乎
什么是超买超卖? - 知乎首页知乎知学堂发现等你来答切换模式登录/注册投资股票互联网金融炒股什么是超买超卖?关注者15被浏览83,778关注问题写回答邀请回答好问题添加评论分享7 个回答默认排序知乎用户0aGhHx新人学股贴士 关注对某种股票的过度买入称之为超买,反之,对于某种股票的过度卖出则称之为超卖。一般用于onos技术指标分析超买超卖指标OBOS主要是运用一段时间内整个股票市场中涨跌家数的累积差关系,来测量大盘买卖气势的强弱及未来演变趋势,以作为研判股市呈现超买或超卖区的参考指标。OBOS指标和ADR指标一样,是用一段时间内上涨和下跌股票家数的差距来反映当前股市多空力量的对比和强弱。它的主要用途在于衡量大势涨跌气势,在某种程度上是一种加大ADL线振幅的分析方法。OBOS指标的原理主要是对投资者心理面的变化作为假定,认为当股市大势持续上涨时,必然会使部分敏感的主力机构货利了结,从而诱发大势反转向下,而当大势持续下跌时,又会吸引部分先知先觉的机构进场吸纳,触发向上反弹行情。因此,当OBOS指标逐渐向上并进入超越正常水平时,即代表市场的买气逐渐升温并最终导致大盘超买现象。同样,当OBOS指标持续下跌时,则导致超卖现象。对整个股票市场而言,由于OBOS指标在某种程度上反应了部分市场主力的行为模式。因此在预测上,当大盘处于由牛市向熊市转变时,OBOS指标理论上具有领先大盘指数的能力;而当大盘处于由熊市向牛市反转时,OBOS指标理论上稍微落后于大盘指数的缺陷,但从另一种角度看,它可以真正确认大盘的牛转熊是否有效。发布于 2015-12-02 15:54赞同 14添加评论分享收藏喜欢收起达达虾每日实盘讲解--股仓大护法(同名公众号) 关注什么是超买超卖?超买超卖有什么作用?一、什么是超买超卖?超买,是指2113资产的价格升至基本面因5261素无法支持的水4102平,通常发生在价格短时间内急涨之后1653。超买意味着价格很容易出现向下修正;超卖,一种技术分析名词,指一种证券的价格显著下跌后,近期内可能上涨。超买超卖(OBOS)是一种衡量大势涨跌气势的分析工具。将N日内上涨股票个数总和算出,再将这些日内下跌的个数总和算出,相减后,得到的便是OBOS值。股市上出现因某种消息传播而使投资者对大盘或个股作出强烈反应,以致股市或个股过分上升或下跌,于是便产生了超买超卖现象。二、超卖超买有什么作用?一般而言,股票技术指标通常分趋向、能量、量价、强弱、停损、超买超卖、支撑压力、成本共计八大类23个。而今天我们所讲的是超买超卖类指标,有3个。1、KDJ:随机指标1、含义KDJ为随机指标,是目前最常用的技术指标之一。主要就是利用价格波动的真实波幅反映价格走势强弱和超买超卖现象,在价格尚未上升或下降前所发出买卖信号的技术工具。运用KDJ能迅速、快捷、直观研判行情。如下图:KDJ大于80时为超买,小于20为超卖;K在20左右时向上交叉D时为买进信号,K在80左右时向下交叉D时为卖出信号。2、买卖原则1)、K值由右边向下交叉D值作卖,K值由右边向上交叉D值作买。2)、高档连续两次向下交叉确认跌势.低档两次向上交叉确认涨势。3)、D值<20%超卖,D值>80%超买;J>100%超买,J<10%超卖。4)、KD值于50%左右徘徊或交叉时,无意义。5)、投机性太强的个股不适用。6)、可观察KD值与股价之背离,以确认高低点。3、实战案例2、CCI:顺势指标1、含义CCI指标又叫顺势指标,是衡量股价是否超出常态分布范围的一种超买超卖类指标。CCI指标是波动于正无穷大到负无穷大之间,因此不会出现指标钝化现象,这样就有利于投资者更好地研判行情,特别是那些短期内暴涨暴跌的非常态行情。如下图:CCI为正值时为多头市场,为负值时为空头市场;CCI大于100时为买进信号,小于100时为卖出信号。2、买卖原则1)买点:其一,CCI从+100~-100的常态区,由下往上突破+100天线时,为抢进时机。其二,CCI从-100地线下方,由下往上突破-100地线时,买进股票。2)卖点其一,CCI从+100天线之上,由上往下跌破天线时,为加速逃逸时机;其二,CCI从+100~-100的常态区,由上往下跌破-100地线时,为放空卖出时机。3、实战案例3、ROC:变动率指标1、含义是以当日的收盘价和N天前的收盘价比较,通过计算股价某一段时间内收盘价变动的比例,应用价格的移动比较来测量价位动量,达到事先探测股价买卖供需力量的强弱,进而分析股价的趋势及其是否有转势的意愿,属于反趋向的指标之一。如下图:具有超买超卖原则,向上表示强势,上穿100时为买入信号,下穿100时为卖出信号。2、买卖原则当股价与ROC指标线形成背离时买入当股价持续下跌,并不断创出新低时,如果此时ROC指标线但没有继续创出新低反而形成一底比一底高的上涨走势,即股价与ROC指标形成底背离形态,当形态形成时,就意味着虽然股价持续下跌,但是下跌的趋势已经减弱,未来股价即将见底反弹因此,如果ROC线持续上涨,突破零轴时,说明上涨行情已经开启,投资者可以积极买进股票。3、实战案例炒股是一门学问,建议你每天花费一些时间去学习,投资自己的大脑,这是一生受益的事情。最主要是要形成自己的买卖系统,炒股不是赌博,要做大概率的事情,不要相信别人推荐股票分成这样的傻事情你领悟了这个,就比一般散户好了一大半了。股市实现稳定盈利不是梦,就看你愿不愿意花时间学习。投资是一件非常复杂的事情,如果没有足够的精力和时间去学习,那最好还是做一些低风险、低收益的投资,否则容易遭遇高风险,蒙受巨大损失。如果您不清楚手中个股如何操作,以及不知道如何把握买卖点,想了解更多股市投资经验及技巧,关注股仓大护法(同名公众号),您想要都有!发布于 2020-09-19 17:37赞同 30添加评论分享收藏喜欢
股票的超卖和超买是什么? - 知乎
股票的超卖和超买是什么? - 知乎首发于小邦财商切换模式写文章登录/注册股票的超卖和超买是什么?小邦 Bonnie乐邦社,来对的地方滋养成长小邦财商系列原创过去一个月的股市显得萎靡不振,持续阴跌,培训和手游等个别行业的被点名引发了一些股票的暴跌。一位上月正在准备进入股市的在读大学生跑来问,某某股票是否超跌,要不要趁低买入。超跌......并不专业,于是就和他聊起什么叫超卖。超卖(oversold)用朴素的逻辑理解,一个股票价格短时间内暴跌,原因可以是多种多样的,但随后出现的情况应该是抛售,大家都想赶紧逃,导致股价跌得更惨,但卖盘还是太多,始终跌跌不休。不过,一段时间后,一些人开始抱着捡漏的心态买入,后续股价重新上升。超卖是指股票遭遇抛售,股价走低,后续有可能出现价格反弹的情况;但这种情况可能会持续很长时间,价格是否会很快反弹,甚至能否反弹都是不确定的。超跌有几个特点需要注意:它是一个持续的先跌后升的过程,不指某一个时间点;是否超卖可以通过相对强度指数(RSI,Relative Strength Index)和随机指标(stochastic oscillator)等做技术分析;本质上,超卖是主观的,交易员和分析师使用不同的工具得出自己的看法,一些人可能会看到超卖的情况,而另一些人则会看到股价会进一步下跌。基本面的超卖 vs. 技术性的超卖基本面的超卖意思是股价已经下跌至远低于其真实价值的情况,典型的原因包括突发爆出有关公司的坏消息,导致该公司未来前景不佳、行业失宠或整体市场低迷等情况。技术性的超卖是基于一些指标和数据的分析,在没有什么特别的重大消息影响下,一个股票对比起之前某段时间的价格下跌了,出现了一个潜在的上升空间。还是举两个虚构的例子吧,用“买股票投的是未来”的角度去看:A股票是一家巨无霸的互联网上市公司,钱景一直不错,旗下手游板块是业界翘楚,一年营收过千亿。忽然某日,手游被点名是没有营养的,甚至有害的东西,几乎所有手游相关的上市公司都受到影响,没有哪家的股票是不跌的。一个月内,A股票跌去了13%,而且市场普遍还是看跌。不过,综合各种数据看,也考虑到A公司的主营业务是网上购物,整体业绩稳定,分析认为持续大跌的可能性不高,反弹的空间在逐步形成。简而言之,A股票是技术性的超卖。B股票是一家培训行业的上市公司,专注校外K12的辅导业务,过去几年股价持续高增长。最近关于培训行业的坏消息带来近乎毁灭性打击,全部K12相关的辅导业务被即刻叫停,短时间内不可能重启。可以说,整个行业出现了系统性风险,任何同类型公司都无法扭转或者规避这个风险。(更多参考:金融市场:系统性风险和非系统性风险)虽然这家上市公司表示自己有足够的现金流支撑未来的2~3年,但短期内前景不妙已是市场共识。假设他们在未来6~12个月找到新的业务并能够发展下去,股价重新上涨,买盘变得活跃,那么B股票的情况就是基本面超卖。(更多参考:小邦财商:基本面和基本分析)有没有超买(overbought)?有啊,就是超卖的反转,买贵了,即股价已经超过了上市公司的真实价值,没有上升的空间,反而即将下跌。超买的分析也和超卖一样,需要运用各种指标和数据。以上的入门讨论为的是帮助投资小白搞清楚一些基本的概念,下一期就可以聊聊一些关键指标了。编辑于 2021-08-07 14:40股票投资财商教育赞同 3添加评论分享喜欢收藏申请转载文章被以下专栏收录小邦财商财经素养 | Financial Liter
电商系统如何防止超卖? - 知乎
电商系统如何防止超卖? - 知乎首页知乎知学堂发现等你来答切换模式登录/注册电子商务数据库软件开发软件架构运维电商系统如何防止超卖?关注者29被浏览82,717关注问题写回答邀请回答好问题添加评论分享14 个回答默认排序苏三说技术 关注前言说实话在电商系统中,库存超卖问题是一个让人非常头疼的问题。其中这个问题最严重的可能是秒杀系统,在极短的时间内,有大量的购买请求,只有极少数能够购买成功,如何保证不超卖,是有很多技术难点的。高并发下如何设计秒杀系统?这是一个高频面试题。这个问题看似简单,但是里面的水很深,它考查的是高并发场景下,从前端到后端多方面的知识。秒杀一般出现在商城的促销活动中,指定了一定数量(比如:10个)的商品(比如:手机),以极低的价格(比如:0.1元),让大量用户参与活动,但只有极少数用户能够购买成功。这类活动商家绝大部分是不赚钱的,说白了是找个噱头宣传自己。虽说秒杀只是一个促销活动,但对技术要求不低。下面给大家总结一下设计秒杀系统需要注意的9个细节。最近无意间获得一份BAT大厂大佬写的刷题笔记,一下子打通了我的任督二脉,越来越觉得算法没有想象中那么难了。[BAT大佬写的刷题笔记,让我offer拿到手软](这位BAT大佬写的Leetcode刷题笔记,让我offer拿到手软)1 瞬时高并发一般在秒杀时间点(比如:12点)前几分钟,用户并发量才真正突增,达到秒杀时间点时,并发量会达到顶峰。但由于这类活动是大量用户抢少量商品的场景,必定会出现狼多肉少的情况,所以其实绝大部分用户秒杀会失败,只有极少部分用户能够成功。正常情况下,大部分用户会收到商品已经抢完的提醒,收到该提醒后,他们大概率不会在那个活动页面停留了,如此一来,用户并发量又会急剧下降。所以这个峰值持续的时间其实是非常短的,这样就会出现瞬时高并发的情况,下面用一张图直观的感受一下流量的变化:像这种瞬时高并发的场景,传统的系统很难应对,我们需要设计一套全新的系统。可以从以下几个方面入手:页面静态化 CDN加速 缓存 mq异步处理 限流 分布式锁 2. 页面静态化活动页面是用户流量的第一入口,所以是并发量最大的地方。如果这些流量都能直接访问服务端,恐怕服务端会因为承受不住这么大的压力,而直接挂掉。活动页面绝大多数内容是固定的,比如:商品名称、商品描述、图片等。为了减少不必要的服务端请求,通常情况下,会对活动页面做静态化处理。用户浏览商品等常规操作,并不会请求到服务端。只有到了秒杀时间点,并且用户主动点了秒杀按钮才允许访问服务端。这样能过滤大部分无效请求。但只做页面静态化还不够,因为用户分布在全国各地,有些人在北京,有些人在成都,有些人在深圳,地域相差很远,网速各不相同。如何才能让用户最快访问到活动页面呢?这就需要使用CDN,它的全称是Content Delivery Network,即内容分发网络。使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。3 秒杀按钮大部分用户怕错过秒杀时间点,一般会提前进入活动页面。此时看到的秒杀按钮是置灰,不可点击的。只有到了秒杀时间点那一时刻,秒杀按钮才会自动点亮,变成可点击的。但此时很多用户已经迫不及待了,通过不停刷新页面,争取在第一时间看到秒杀按钮的点亮。从前面得知,该活动页面是静态的。那么我们在静态页面中如何控制秒杀按钮,只在秒杀时间点时才点亮呢?没错,使用js文件控制。为了性能考虑,一般会将css、js和图片等静态资源文件提前缓存到CDN上,让用户能够就近访问秒杀页面。看到这里,有些聪明的小伙伴,可能会问:CDN上的js文件是如何更新的?秒杀开始之前,js标志为false,还有另外一个随机参数。当秒杀开始的时候系统会生成一个新的js文件,此时标志为true,并且随机参数生成一个新值,然后同步给CDN。由于有了这个随机参数,CDN不会缓存数据,每次都能从CDN中获取最新的js代码。此外,前端还可以加一个定时器,控制比如:10秒之内,只允许发起一次请求。如果用户点击了一次秒杀按钮,则在10秒之内置灰,不允许再次点击,等到过了时间限制,又允许重新点击该按钮。4 读多写少在秒杀的过程中,系统一般会先查一下库存是否足够,如果足够才允许下单,写数据库。如果不够,则直接返回该商品已经抢完。由于大量用户抢少量商品,只有极少部分用户能够抢成功,所以绝大部分用户在秒杀时,库存其实是不足的,系统会直接返回该商品已经抢完。这是非常典型的:读多写少 的场景。如果有数十万的请求过来,同时通过数据库查缓存是否足够,此时数据库可能会挂掉。因为数据库的连接资源非常有限,比如:mysql,无法同时支持这么多的连接。而应该改用缓存,比如:redis。即便用了redis,也需要部署多个节点。5 缓存问题通常情况下,我们需要在redis中保存商品信息,里面包含:商品id、商品名称、规格属性、库存等信息,同时数据库中也要有相关信息,毕竟缓存并不完全可靠。用户在点击秒杀按钮,请求秒杀接口的过程中,需要传入的商品id参数,然后服务端需要校验该商品是否合法。大致流程如下图所示:根据商品id,先从缓存中查询商品,如果商品存在,则参与秒杀。如果不存在,则需要从数据库中查询商品,如果存在,则将商品信息放入缓存,然后参与秒杀。如果商品不存在,则直接提示失败。这个过程表面上看起来是OK的,但是如果深入分析一下会发现一些问题。5.1 缓存击穿比如商品A第一次秒杀时,缓存中是没有数据的,但数据库中有。虽说上面有如果从数据库中查到数据,则放入缓存的逻辑。然而,在高并发下,同一时刻会有大量的请求,都在秒杀同一件商品,这些请求同时去查缓存中没有数据,然后又同时访问数据库。结果悲剧了,数据库可能扛不住压力,直接挂掉。如何解决这个问题呢?这就需要加锁,最好使用分布式锁。当然,针对这种情况,最好在项目启动之前,先把缓存进行预热。即事先把所有的商品,同步到缓存中,这样商品基本都能直接从缓存中获取到,就不会出现缓存击穿的问题了。是不是上面加锁这一步可以不需要了?表面上看起来,确实可以不需要。但如果缓存中设置的过期时间不对,缓存提前过期了,或者缓存被不小心删除了,如果不加速同样可能出现缓存击穿。其实这里加锁,相当于买了一份保险。5.2 缓存穿透如果有大量的请求传入的商品id,在缓存中和数据库中都不存在,这些请求不就每次都会穿透过缓存,而直接访问数据库了。由于前面已经加了锁,所以即使这里的并发量很大,也不会导致数据库直接挂掉。但很显然这些请求的处理性能并不好,有没有更好的解决方案?这时可以想到布隆过滤器。系统根据商品id,先从布隆过滤器中查询该id是否存在,如果存在则允许从缓存中查询数据,如果不存在,则直接返回失败。虽说该方案可以解决缓存穿透问题,但是又会引出另外一个问题:布隆过滤器中的数据如何更缓存中的数据保持一致?这就要求,如果缓存中数据有更新,则要及时同步到布隆过滤器中。如果数据同步失败了,还需要增加重试机制,而且跨数据源,能保证数据的实时一致性吗?显然是不行的。所以布隆过滤器绝大部分使用在缓存数据更新很少的场景中。如果缓存数据更新非常频繁,又该如何处理呢?这时,就需要把不存在的商品id也缓存起来。下次,再有该商品id的请求过来,则也能从缓存中查到数据,只不过该数据比较特殊,表示商品不存在。需要特别注意的是,这种特殊缓存设置的超时时间应该尽量短一点。6 库存问题对于库存问题看似简单,实则里面还是有些东西。真正的秒杀商品的场景,不是说扣完库存,就完事了,如果用户在一段时间内,还没完成支付,扣减的库存是要加回去的。所以,在这里引出了一个预扣库存的概念,预扣库存的主要流程如下:扣减库存中除了上面说到的预扣库存和回退库存之外,还需要特别注意的是库存不足和库存超卖问题。6.1 数据库扣减库存使用数据库扣减库存,是最简单的实现方案了,假设扣减库存的sql如下:update product set stock=stock-1 where id=123;
这种写法对于扣减库存是没有问题的,但如何控制库存不足的情况下,不让用户操作呢?这就需要在update之前,先查一下库存是否足够了。伪代码如下:int stock = mapper.getStockById(123);
if(stock > 0) {
int count = mapper.updateStock(123);
if(count > 0) {
addOrder(123);
}
}
大家有没有发现这段代码的问题?没错,查询操作和更新操作不是原子性的,会导致在并发的场景下,出现库存超卖的情况。有人可能会说,这样好办,加把锁,不就搞定了,比如使用synchronized关键字。确实,可以,但是性能不够好。还有更优雅的处理方案,即基于数据库的乐观锁,这样会少一次数据库查询,而且能够天然的保证数据操作的原子性。只需将上面的sql稍微调整一下:update product set stock=stock-1 where id=product and stock > 0;
在sql最后加上:stock > 0,就能保证不会出现超卖的情况。但需要频繁访问数据库,我们都知道数据库连接是非常昂贵的资源。在高并发的场景下,可能会造成系统雪崩。而且,容易出现多个请求,同时竞争行锁的情况,造成相互等待,从而出现死锁的问题。6.2 redis扣减库存redis的incr方法是原子性的,可以用该方法扣减库存。伪代码如下: boolean exist = redisClient.query(productId,userId);
if(exist) {
return -1;
}
int stock = redisClient.queryStock(productId);
if(stock <=0) {
return 0;
}
redisClient.incrby(productId, -1);
redisClient.add(productId,userId);
return 1;
代码流程如下:先判断该用户有没有秒杀过该商品,如果已经秒杀过,则直接返回-1。 查询库存,如果库存小于等于0,则直接返回0,表示库存不足。 如果库存充足,则扣减库存,然后将本次秒杀记录保存起来。然后返回1,表示成功。 估计很多小伙伴,一开始都会按这样的思路写代码。但如果仔细想想会发现,这段代码有问题。有什么问题呢?如果在高并发下,有多个请求同时查询库存,当时都大于0。由于查询库存和更新库存非原则操作,则会出现库存为负数的情况,即库存超卖。当然有人可能会说,加个synchronized不就解决问题?调整后代码如下: boolean exist = redisClient.query(productId,userId);
if(exist) {
return -1;
}
synchronized(this) {
int stock = redisClient.queryStock(productId);
if(stock <=0) {
return 0;
}
redisClient.incrby(productId, -1);
redisClient.add(productId,userId);
}
return 1;
加synchronized确实能解决库存为负数问题,但是这样会导致接口性能急剧下降,每次查询都需要竞争同一把锁,显然不太合理。为了解决上面的问题,代码优化如下:boolean exist = redisClient.query(productId,userId);
if(exist) {
return -1;
}
if(redisClient.incrby(productId, -1)<0) {
return 0;
}
redisClient.add(productId,userId);
return 1;
该代码主要流程如下:先判断该用户有没有秒杀过该商品,如果已经秒杀过,则直接返回-1。 扣减库存,判断返回值是否小于0,如果小于0,则直接返回0,表示库存不足。 如果扣减库存后,返回值大于或等于0,则将本次秒杀记录保存起来。然后返回1,表示成功。 该方案咋一看,好像没问题。但如果在高并发场景中,有多个请求同时扣减库存,大多数请求的incrby操作之后,结果都会小于0。虽说,库存出现负数,不会出现超卖的问题。但由于这里是预减库存,如果负数值负的太多的话,后面万一要回退库存时,就会导致库存不准。那么,有没有更好的方案呢?6.3 lua脚本扣减库存我们都知道lua脚本,是能够保证原子性的,它跟redis一起配合使用,能够完美解决上面的问题。lua脚本有段非常经典的代码: StringBuilder lua = new StringBuilder();
lua.append("if (redis.call('exists', KEYS[1]) == 1) then");
lua.append(" local stock = tonumber(redis.call('get', KEYS[1]));");
lua.append(" if (stock == -1) then");
lua.append(" return 1;");
lua.append(" end;");
lua.append(" if (stock > 0) then");
lua.append(" redis.call('incrby', KEYS[1], -1);");
lua.append(" return stock;");
lua.append(" end;");
lua.append(" return 0;");
lua.append("end;");
lua.append("return -1;");
该代码的主要流程如下:先判断商品id是否存在,如果不存在则直接返回。 获取该商品id的库存,判断库存如果是-1,则直接返回,表示不限制库存。 如果库存大于0,则扣减库存。 如果库存等于0,是直接返回,表示库存不足。 7 分布式锁之前我提到过,在秒杀的时候,需要先从缓存中查商品是否存在,如果不存在,则会从数据库中查商品。如果数据库中,则将该商品放入缓存中,然后返回。如果数据库中没有,则直接返回失败。大家试想一下,如果在高并发下,有大量的请求都去查一个缓存中不存在的商品,这些请求都会直接打到数据库。数据库由于承受不住压力,而直接挂掉。那么如何解决这个问题呢?这就需要用redis分布式锁了。7.1 setNx加锁使用redis的分布式锁,首先想到的是setNx命令。if (jedis.setnx(lockKey, val) == 1) {
jedis.expire(lockKey, timeout);
}
用该命令其实可以加锁,但和后面的设置超时时间是分开的,并非原子操作。假如加锁成功了,但是设置超时时间失败了,该lockKey就变成永不失效的了。在高并发场景中,该问题会导致非常严重的后果。那么,有没有保证原子性的加锁命令呢?7.2 set加锁使用redis的set命令,它可以指定多个参数。String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
return true;
}
return false;
其中:lockKey:锁的标识 requestId:请求id NX:只在键不存在时,才对键进行设置操作。 PX:设置键的过期时间为 millisecond 毫秒。 expireTime:过期时间 由于该命令只有一步,所以它是原子操作。7.3 释放锁接下来,有些朋友可能会问:在加锁时,既然已经有了lockKey锁标识,为什么要需要记录requestId呢?答:requestId是在释放锁的时候用的。if (jedis.get(lockKey).equals(requestId)) {
jedis.del(lockKey);
return true;
}
return false;
在释放锁的时候,只能释放自己加的锁,不允许释放别人加的锁。这里为什么要用requestId,用userId不行吗?答:如果用userId的话,假设本次请求流程走完了,准备删除锁。此时,巧合锁到了过期时间失效了。而另外一个请求,巧合使用的相同userId加锁,会成功。而本次请求删除锁的时候,删除的其实是别人的锁了。当然使用lua脚本也能避免该问题:if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
它能保证查询锁是否存在和删除锁是原子操作。7.4 自旋锁上面的加锁方法看起来好像没有问题,但如果你仔细想想,如果有1万的请求同时去竞争那把锁,可能只有一个请求是成功的,其余的9999个请求都会失败。在秒杀场景下,会有什么问题?答:每1万个请求,有1个成功。再1万个请求,有1个成功。如此下去,直到库存不足。这就变成均匀分布的秒杀了,跟我们想象中的不一样。如何解决这个问题呢?答:使用自旋锁。try {
Long start = System.currentTimeMillis();
while(true) {
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
return true;
}
long time = System.currentTimeMillis() - start;
if (time>=timeout) {
return false;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally{
unlock(lockKey,requestId);
}
return false;
在规定的时间,比如500毫秒内,自旋不断尝试加锁,如果成功则直接返回。如果失败,则休眠50毫秒,再发起新一轮的尝试。如果到了超时时间,还未加锁成功,则直接返回失败。7.5 redisson除了上面的问题之外,使用redis分布式锁,还有锁竞争问题、续期问题、锁重入问题、多个redis实例加锁问题等。这些问题使用redisson可以解决,由于篇幅的原因,在这里先保留一点悬念,有疑问的私聊给我。后面会出一个专题介绍分布式锁,敬请期待。8 mq异步处理我们都知道在真实的秒杀场景中,有三个核心流程:而这三个核心流程中,真正并发量大的是秒杀功能,下单和支付功能实际并发量很小。所以,我们在设计秒杀系统时,有必要把下单和支付功能从秒杀的主流程中拆分出来,特别是下单功能要做成mq异步处理的。而支付功能,比如支付宝支付,是业务场景本身保证的异步。于是,秒杀后下单的流程变成如下:如果使用mq,需要关注以下几个问题:8.1 消息丢失问题秒杀成功了,往mq发送下单消息的时候,有可能会失败。原因有很多,比如:网络问题、broker挂了、mq服务端磁盘问题等。这些情况,都可能会造成消息丢失。那么,如何防止消息丢失呢?答:加一张消息发送表。在生产者发送mq消息之前,先把该条消息写入消息发送表,初始状态是待处理,然后再发送mq消息。消费者消费消息时,处理完业务逻辑之后,再回调生产者的一个接口,修改消息状态为已处理。如果生产者把消息写入消息发送表之后,再发送mq消息到mq服务端的过程中失败了,造成了消息丢失。这时候,要如何处理呢?答:使用job,增加重试机制。最近无意间获得一份BAT大厂大佬写的刷题笔记,一下子打通了我的任督二脉,越来越觉得算法没有想象中那么难了。[BAT大佬写的刷题笔记,让我offer拿到手软](这位BAT大佬写的Leetcode刷题笔记,让我offer拿到手软)用job每隔一段时间去查询消息发送表中状态为待处理的数据,然后重新发送mq消息。8.2 重复消费问题本来消费者消费消息时,在ack应答的时候,如果网络超时,本身就可能会消费重复的消息。但由于消息发送者增加了重试机制,会导致消费者重复消息的概率增大。那么,如何解决重复消息问题呢?答:加一张消息处理表。消费者读到消息之后,先判断一下消息处理表,是否存在该消息,如果存在,表示是重复消费,则直接返回。如果不存在,则进行下单操作,接着将该消息写入消息处理表中,再返回。有个比较关键的点是:下单和写消息处理表,要放在同一个事务中,保证原子操作。8.3 垃圾消息问题这套方案表面上看起来没有问题,但如果出现了消息消费失败的情况。比如:由于某些原因,消息消费者下单一直失败,一直不能回调状态变更接口,这样job会不停的重试发消息。最后,会产生大量的垃圾消息。那么,如何解决这个问题呢?每次在job重试时,需要先判断一下消息发送表中该消息的发送次数是否达到最大限制,如果达到了,则直接返回。如果没有达到,则将次数加1,然后发送消息。这样如果出现异常,只会产生少量的垃圾消息,不会影响到正常的业务。8.4 延迟消费问题通常情况下,如果用户秒杀成功了,下单之后,在15分钟之内还未完成支付的话,该订单会被自动取消,回退库存。那么,在15分钟内未完成支付,订单被自动取消的功能,要如何实现呢?我们首先想到的可能是job,因为它比较简单。但job有个问题,需要每隔一段时间处理一次,实时性不太好。还有更好的方案?答:使用延迟队列。我们都知道rocketmq,自带了延迟队列的功能。下单时消息生产者会先生成订单,此时状态为待支付,然后会向延迟队列中发一条消息。达到了延迟时间,消息消费者读取消息之后,会查询该订单的状态是否为待支付。如果是待支付状态,则会更新订单状态为取消状态。如果不是待支付状态,说明该订单已经支付过了,则直接返回。还有个关键点,用户完成支付之后,会修改订单状态为已支付。9 如何限流?通过秒杀活动,如果我们运气爆棚,可能会用非常低的价格买到不错的商品(这种概率堪比买福利彩票中大奖)。但有些高手,并不会像我们一样老老实实,通过秒杀页面点击秒杀按钮,抢购商品。他们可能在自己的服务器上,模拟正常用户登录系统,跳过秒杀页面,直接调用秒杀接口。如果是我们手动操作,一般情况下,一秒钟只能点击一次秒杀按钮。但是如果是服务器,一秒钟可以请求成上千接口。这种差距实在太明显了,如果不做任何限制,绝大部分商品可能是被机器抢到,而非正常的用户,有点不太公平。所以,我们有必要识别这些非法请求,做一些限制。那么,我们该如何现在这些非法请求呢?目前有两种常用的限流方式:基于nginx限流 基于redis限流 9.1 对同一用户限流为了防止某个用户,请求接口次数过于频繁,可以只针对该用户做限制。限制同一个用户id,比如每分钟只能请求5次接口。9.2 对同一ip限流有时候只对某个用户限流是不够的,有些高手可以模拟多个用户请求,这种nginx就没法识别了。这时需要加同一ip限流功能。限制同一个ip,比如每分钟只能请求5次接口。但这种限流方式可能会有误杀的情况,比如同一个公司或网吧的出口ip是相同的,如果里面有多个正常用户同时发起请求,有些用户可能会被限制住。9.3 对接口限流别以为限制了用户和ip就万事大吉,有些高手甚至可以使用代理,每次都请求都换一个ip。这时可以限制请求的接口总次数。在高并发场景下,这种限制对于系统的稳定性是非常有必要的。但可能由于有些非法请求次数太多,达到了该接口的请求上限,而影响其他的正常用户访问该接口。看起来有点得不偿失。9.4 加验证码相对于上面三种方式,加验证码的方式可能更精准一些,同样能限制用户的访问频次,但好处是不会存在误杀的情况。通常情况下,用户在请求之前,需要先输入验证码。用户发起请求之后,服务端会去校验该验证码是否正确。只有正确才允许进行下一步操作,否则直接返回,并且提示验证码错误。此外,验证码一般是一次性的,同一个验证码只允许使用一次,不允许重复使用。普通验证码,由于生成的数字或者图案比较简单,可能会被破解。优点是生成速度比较快,缺点是有安全隐患。还有一个验证码叫做:移动滑块,它生成速度比较慢,但比较安全,是目前各大互联网公司的首选。最近无意间获得一份BAT大厂大佬写的刷题笔记,一下子打通了我的任督二脉,越来越觉得算法没有想象中那么难了。[BAT大佬写的刷题笔记,让我offer拿到手软](这位BAT大佬写的Leetcode刷题笔记,让我offer拿到手软)9.5 提高业务门槛上面说的加验证码虽然可以限制非法用户请求,但是有些影响用户体验。用户点击秒杀按钮前,还要先输入验证码,流程显得有点繁琐,秒杀功能的流程不是应该越简单越好吗?其实,有时候达到某个目的,不一定非要通过技术手段,通过业务手段也一样。12306刚开始的时候,全国人民都在同一时刻抢火车票,由于并发量太大,系统经常挂。后来,重构优化之后,将购买周期放长了,可以提前20天购买火车票,并且可以在9点、10、11点、12点等整点购买火车票。调整业务之后(当然技术也有很多调整),将之前集中的请求,分散开了,一下子降低了用户并发量。回到这里,我们通过提高业务门槛,比如只有会员才能参与秒杀活动,普通注册用户没有权限。或者,只有等级到达3级以上的普通用户,才有资格参加该活动。这样简单的提高一点门槛,即使是黄牛党也束手无策,他们总不可能为了参加一次秒杀活动,还另外花钱充值会员吧?最后说一句(求关注,别白嫖我)如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力。求一键三连:点赞、转发、在看。 链接:https://pan.baidu.com/s/1UECE5yuaoTTRpJfi5LU5TQ 密码:bhbe不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激! @苏三说技术 发布于 2022-04-23 12:17赞同 467 条评论分享收藏喜欢收起吴小浩 关注一般都是有专门的一套系统的 精确的把握仓库的库存 尤其是出货量比较多的大店小店的话 仓库那边到库货物检查登记就可以了发布于 2020-06-19 17:06赞同添加评论分享收藏喜欢
超卖_百度百科
度百科 网页新闻贴吧知道网盘图片视频地图文库资讯采购百科百度首页登录注册进入词条全站搜索帮助首页秒懂百科特色百科知识专题加入百科百科团队权威合作下载百科APP个人中心超卖播报讨论上传视频股市用语收藏查看我的收藏0有用+10超卖:股市用语。一种技术分析名词,指一种证券的价格显著下跌后,短期内可能上涨。中文名超卖性 质股市用语目录1概念专业2相关概念3投资意义4技术分析5适时测度6四类指标概念专业播报编辑经济学over sold oversold超卖——超买的相对称,是指就基本面因素而言,资产价格已跌至不合理的水平,通常发生在价格短期内急跌之后。超卖意味着价格很容易出现向上调整。在技术分析上,当一种金融工具的相对强弱指数低于25%时,一般视为出现“超卖”。相反的情况称为“超买”。相关概念播报编辑买盘强势:股市交易中买方的欲望强烈,造成股价上涨。卖压沉重:股市交易中持股者争相抛售股票,造成股价下跌。超买:股价持续上升到一定高度,买方力量基本用尽,股价即将下跌。超卖:股价持续下跌到一定低点,卖方力量基本用尽,股价即将回升。投资意义播报编辑股市上,经常会出现因某种消息的传播而使投资者对大盘或个股作出强烈的反应,以致引起股市或个股出现过分的上升或下跌,于是便产生了超买超卖现象。当投资者的情绪平静下来以后,超买超卖所造成的影响会逐渐得到适当的调整。因此,超买之后就会是股价出现一段回落;超卖之后,则会出现相当程度的反弹。投资者如了解这种超买超卖现象,并及时把握住其运动规律,就又能在股市中增加获利机会。这里的关键是,如何适时地测度出股市上的超卖现象。目前,测度超卖现象的技术分析方法很多,主要有相对强弱指数(RSI)、摆动指数(OCS)、随机指数(KDJ)及百分比等。技术分析播报编辑这里的关键是,如何适时地测度出股市上的超买超卖现象。目前,测度超买超卖现象的技术分析方法很多,主要有相对强弱指数(RSI)、摆动指数(OCS)、随机指数(KDJ)及百分比等KDJ随机指数源于期货市场,是由Georgelane发明的,属于波动于0—100之间的超买超卖指标,由K、D、J三条曲线组成,在实战应用时应注意:1.KD取值。KD的取值范围都是0—100,可划分为:80以上为超买区,20以下为超卖区,其余为徘徊区。但KD值进入超买或超卖区后,会发生指标徘徊和钝化现象,因此没有实战指导意义。2.KD形态。当KD值在较高或较低的位置形成了头肩形和多重顶、底时,是实战中极好的买卖信号。形态一定要在较高位置或较低位置出现,位置越高或越低,结论越可靠。某股票的超卖K线图3.KD交叉。可分为K从下向上与D金叉和K从上向下与D死叉。以K从下向上与D交叉为例,K上穿D是金叉,为买入信号。但金叉出现并不一定是买入信号,首先金叉的位置应该比较低,在超卖区的位置,越低越好;其次K与D相交的次数,以2次为最少,越多越好;最后交叉点相对于KD线低点的位置要“右侧相交”原则,K是在D已经抬头向上时才同D相交,比D还在下降时与之相交要可靠得多。大盘1307见底,周K线图上K、D就是两次金叉并符合右侧相交原则的。4.KD背离。在KD处在高位或低位,往往出现与股价走向的背离。当KD处在高位并形成两个依次向下的峰,此时股价还在继续上涨,为顶背离,是卖出信号,大盘1748见顶后震荡下行,KD就在超买区形成顶背离;KD处在低位并形成一底比一底高,股价还继续下跌,为底背离,是买入信号。5.J值。超过100和低于0,属于价格的非正常区域,大于100为超买,为短线卖出信号,小于0为超卖,为短线买入信号。实战中KDJ只能起辅助研判的功能,主要还是依据K线、均线、波浪、量价分析等,同时在单个指标运用时,要注意结合日、周、月指标的综合研判。总结:K上穿D是金叉,为买入信号!适时测度播报编辑1.所谓外汇头寸,就是指外汇银行所持有的各种外币帐户余额状况,即外汇银行的外汇买卖的余缺状况。简单点说就是你帐户里的钱数。2.外汇银行买入的外汇小于其卖出的外汇时,外汇头寸出现空头或缺头(Short Position),亦称为超卖(Oversold)。简单说来就是你卖出的外汇比买入的外汇多。3.以美圆/日圆超卖举例说明:你购买美圆比日圆多,你的外汇头寸即是空头,就是超卖。KDJ随机指数源于期货市场,是由Georgelane发明的,属于波动于0―100之间的超买超卖指标,由K、D、J三条曲线组成,在实战应用时应注意:四类指标播报编辑腾落指数ADL某股票的超卖K线图腾落指数ADL是以股票每天上涨或下跌之家数作为计算与观察的对象,以了解股市人气状况,探测大势内在的资金动能是强势还是弱势,用以研判股市未来动向的技术性指标。其计算方法十分简单,只要将每天收盘价上涨股票家数减去收盘价下跌的股票家数计算结果即可。腾落指数只反映大势的走向与趋势,不对个股的涨跌提供讯号。由于市场中常常存在通过拉抬打压大盘指标股,使得指数走势失去本来面目的现象,从而影响投资者的准确研判分析,腾落指数ADL可以很好地消除这类失真影响。当股指持续上涨,腾落指数亦上升,股指可能仍将继续上升。涨跌比率ADR是将一定期间内,股价上涨的股票家数与下跌的股票家数做一统计求出其比率。其理论基础是“钟摆原理”,由于股市的供需有若钟摆的两个极端位置,当供给量大时,会产生物极必反的效果,则往需求方向摆动的拉力越强,反之,亦然。对大势而言,涨跌比率有先行示警作用,尤其是在短期反弹或回档方面,更能比股市领先出现征兆。涨跌比率ADR的计算周期是14天,一般涨跌比率是在1.5-0.5之间反复徘徊,表示股价处于正常的震荡波动行情中,市场没有出现超买或超卖现象。 当涨跌比率大于1.5时,表示股指经过长期大幅上涨后,有严重超买的迹象,股指可能将转入下跌。而当涨跌比率小于0.5时,表示股指经过长期大幅下跌后,有严重超卖的迹象,股指可能将恢复上涨。当涨跌比率超出两倍以上时,表示市场进入严重超买区,这时候投资者要注意获利了结;如果涨跌比率进入0.3以下时,表示股市已进入严重超卖区,这时候投资者要注意不能恐慌性杀跌。指数平滑广量指标STIX指数平滑广量指标STIX,是从ADR涨跌比率演变而来,主要是将ADR指标,经由指数平均的方式平滑算出。在正常的市场状况中,STIX指标出现超出超买超卖区的概率不多。STIX指标一般波动于+42─+58之间,当STIX指标上升至+56时,大盘已进入超买区,通常被视为获利了结的位置。当STIX指标下跌至+45时,表示大盘已进入超卖区,通常是适宜投资者建仓的时机,除非是长期跌势或大暴跌之外,否则,指标很少跌至+42以下,因此投资者在这一区域不宜盲目杀跌。超买超卖线OBOS超买超卖线OBOS主要用途在衡量大势涨跌气势,通过计算涨跌家数的相关差异性,藉以解整个市场买卖气势之强弱,以及未来大势走向如何。OBOS计算累计天数一般是设定为10日。10日OBOS对大势有先行指标之功能,一般走在大势之前,非常有参考价值。 OBOS的数值可为正数亦可为负数,当OBOS为正数时,市场处于上涨行情,反之为下跌行情。当OBOS达到一定正数值时,大势处于超买阶段,可选择时机卖出。反之,当OBOS达到一定负数值时,大势超卖,可选择时机买进。OBOS的超买和超卖的具体数据没有一定的标准,因为中国股市处于不断得高速扩容中,上市公司也在不断增加,所以,OBOS超买和超卖的具体标准也在同步变化,但总的数量标准是处于不断增加的趋势中。 就目前的市场现状来说,当OBOS的负值低于-300以下,而且OBOS走势与股指运行之间出现明显底背离时,投资者不宜盲目杀跌。新手上路成长任务编辑入门编辑规则本人编辑我有疑问内容质疑在线客服官方贴吧意见反馈投诉建议举报不良信息未通过词条申诉投诉侵权信息封禁查询与解封©2024 Baidu 使用百度前必读 | 百科协议 | 隐私政策 | 百度百科合作平台 | 京ICP证030173号 京公网安备110000020000超买和超卖是什么意思? - 知乎
超买和超卖是什么意思? - 知乎切换模式写文章登录/注册超买和超卖是什么意思?海投排行APP已认证账号“超买”和”超卖”描述的是短期股价的极端情况,表明股价在某一特定方向上走得太远。当一只股票被归类为市场超买时,意味着专家认为它的售价超过了它的实际价值。另一方面,超卖的股票是指分析师认为其交易价格低于其实际价值的股票。小贴士:超买和超卖的股票是指那些被分析师认为没有按其真实价值交易的股票。超买的股票可能会以高于其价值的价格出售,而超卖的股票可能比其当前的交易价格更有价值。多少才算超买和超卖?超买指的是价格在几天内急剧上升的百分比大于正常水平,或者价格连续几天向同一方向移动的数量越来越多。例如,股票可能是市场超买,因为它们在三天内跳涨了5%–比平时更多–或者因为它们连续六天收涨–也是不寻常的。超卖的意思正好相反。急剧下降或连续几天价格收跌。当一只股票超买时,意味着买盘将价格推得太高,预计会出现反应,称为价格回调。当股票超卖时,意味着卖盘将价格推得太低,预期会出现反应,称为价格反弹。为什么会有超买和超卖?投资者往往对消息反应过度,他们的买入或卖出会使价格向某一特定方向过度发展。更多的买家可能因为价格上涨而不断买入;更多的卖家可能因为价格下跌而不断卖出。到了某个时候,能量耗尽后,他们才意识到事情可能没那么坏,也没那么好,随之而来的是反方向的修正行动。例如,美国联邦储备委员会的一次降息,会引起几天的热情买盘;欧债危机的一系列悲观报道,会引起几天的大量卖盘。但随后投资者开始意识到,美联储的行动并没有解决所有问题,欧洲也没有分崩离析,因此价格从极端情况下撤退。超买和超卖的问题股票涨幅过大或跌幅过大,并不意味着股票仍然不能上涨或下跌。超卖和超买股票往往是反映某人对市场的看法,可能是准确的,也可能是不准确的。例如,在熊市中,股票往往在几波卖盘中下跌,然后暂时停顿后继续下跌。超卖不一定意味着下跌的结束,只是说可能会出现暂时的反弹,之后会恢复下跌。超买股和超卖股也不是精确的衡量标准。例如,经过五天不间断的推进,股票在一些市场观察者看来可能开始超买,但价格仍然继续推进几天,这将使它们更加市场超买或极度超买。发布于 2022-08-15 09:22外汇赞同 2添加评论分享喜欢收藏申请
秒杀:超卖问题(图解+秒懂+史上最全)-CSDN博客
>秒杀:超卖问题(图解+秒懂+史上最全)-CSDN博客
秒杀:超卖问题(图解+秒懂+史上最全)
最新推荐文章于 2024-03-02 15:07:54 发布
40岁资深老架构师尼恩
最新推荐文章于 2024-03-02 15:07:54 发布
阅读量1.2w
收藏
87
点赞数
16
分类专栏:
java
文章标签:
面试
java
数据库
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/crazymakercircle/article/details/120521674
版权
java
专栏收录该内容
203 篇文章
394 订阅
订阅专栏
文章很长,而且持续更新,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源:
免费赠送 经典图书 : 极致经典 + 社群大片好评 《 Java 高并发 三部曲 》 面试必备 + 大厂必备 + 涨薪必备免费赠送 经典图书 : 《Netty Zookeeper Redis 高并发实战》 面试必备 + 大厂必备 +涨薪必备 (加尼恩领取)免费赠送 经典图书 : 《SpringCloud、Nginx高并发核心编程》 面试必备 + 大厂必备 + 涨薪必备 (加尼恩领取)免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 (加尼恩领取)
推荐:入大厂 、做架构、大力提升Java 内功 的 精彩博文
入大厂 、做架构、大力提升Java 内功 必备的精彩博文2021 秋招涨薪1W + 必备的精彩博文1:Redis 分布式锁 (图解-秒懂-史上最全)2:Zookeeper 分布式锁 (图解-秒懂-史上最全)3: Redis与MySQL双写一致性如何保证? (面试必备)4: 面试必备:秒杀超卖 解决方案 (史上最全)5:面试必备之:Reactor模式6: 10分钟看懂, Java NIO 底层原理7:TCP/IP(图解+秒懂+史上最全)8:Feign原理 (图解)9:DNS图解(秒懂 + 史上最全 + 高薪必备)10:CDN图解(秒懂 + 史上最全 + 高薪必备)10: 分布式事务( 图解 + 史上最全 + 吐血推荐 )
Java 面试题 30个专题 , 史上最全 , 面试必刷阿里、京东、美团… 随意挑、横着走!!!1: JVM面试题(史上最强、持续更新、吐血推荐)2:Java基础面试题(史上最全、持续更新、吐血推荐3:架构设计面试题 (史上最全、持续更新、吐血推荐)4:设计模式面试题 (史上最全、持续更新、吐血推荐)17、分布式事务面试题 (史上最全、持续更新、吐血推荐)一致性协议 (史上最全)29、多线程面试题(史上最全)30、HR面经,过五关斩六将后,小心阴沟翻船!9.网络协议面试题(史上最全、持续更新、吐血推荐)更多专题, 请参见【 疯狂创客圈 高并发 总目录 】
SpringCloud 精彩博文 nacos 实战(史上最全) sentinel (史上最全+入门教程) SpringCloud gateway (史上最全)更多专题, 请参见【 疯狂创客圈 高并发 总目录 】
前言
先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超买,以防止造成不必要的损失是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。
在秒杀系统设计中,超卖是一个经典、常见的问题,任何商品都会有数量上限,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的难点。
一、问题描述
在多个用户同时发起对同一个商品的下单请求时,先查询商品库存,再修改商品库存,会出现资源竞争问题,导致库存的最终结果出现异常。问题: 当商品A一共有库存15件,用户甲先下单10件,用户乙下单8件,这时候库存只能满足一个人下单成功,如果两个人同时提交,就出现了超卖的问题。
二、解决的三种方案
悲观锁
通过悲观锁解决超卖
乐观锁
通过乐观锁解决超卖
分段执行的排队方案
通过分段执行的排队方案解决超卖
解决方案1: 悲观锁
当查询某条记录时,即让数据库为该记录加锁,锁住记录后别人无法操作,使用类似如下语法:
beginTranse(开启事务)
try{
query('select amount from s_store where goodID = 12345');
if(库存 > 0){
//quantity为请求减掉的库存数量
query('update s_store set amount = amount - quantity where goodID = 12345');
}
}catch( Exception e ){
rollBack(回滚)
}
commit(提交事务)
问题:
注意,上面的代码容易出现死锁,采用不多。
有社群小伙伴,对死锁的的原因比较关心,这里简单分析一下。
上面的语句,可能出现死锁的简单的原因,在事务的隔离级别为Serializable时,假设事务t1通过 select拿到了共享锁,而其他事务如果拿到了 排他锁,此时t1 去拿排他锁的时候, 就有可能会出现死锁,注意,这里是可能,并不是一定。实际的原因,与事务的隔离级别和语句的复杂度,都有关系。
总之,避免死锁的方式之一(稍后介绍):为了在单个 InnoDB 表上执行多个并发写入操作时避免死锁,可以在事务开始时通过为预期要修改的每个元祖(行)使用 SELECT … FOR UPDATE 语句来获取必要的锁,即使这些行的更改语句是在之后才执行的。
解决方案:一般提前采用 select for update,提前加上写锁。
beginTranse(开启事务)
try{
query('select amount from s_store where goodID = 12345 for update');
if(库存 > 0){
//quantity为请求减掉的库存数量
query('update s_store set amount = amount - quantity where goodID = 12345');
}
}catch( Exception e ){
rollBack(回滚)
}
commit(提交事务)
行锁和表锁
行锁:分为 共享锁 和 排它锁。
**共享锁又称:**读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
上共享锁的写法:lock in share mode
例如: select math from zje where math>60 lock in share mode;
**排它锁又称:**写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。
上排它锁的写法:for update
例如:select math from zje where math >60 for update;
死锁
**死锁:**例如说两个事务,事务A锁住了15行,同时事务B锁住了610行,此时事务A请求锁住610行,就会阻塞直到事务B施放610行的锁,而随后事务B又请求锁住15行,事务B也阻塞直到事务A释放15行的锁。死锁发生时,会产生Deadlock错误。
表锁:不会出现死锁,发生锁冲突几率高,并发低。
表锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁。但是表锁效率低。
**行锁:**会出现死锁,发生锁冲突几率低,并发高。
3.行锁的要点
注意几点:
1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
2.两个事务不能锁同一个索引,例如:
事务A先执行:
select math from zje where math>60 for update;
事务B再执行:
select math from zje where math<60 for update;
这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞,
但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。
3.insert ,delete , update在事务中都会自动默认加上排它锁。
实现:
会话1:会话2:begin; select math from zje where math>60 for update;begin; update zje set math=99 where math=68; 阻塞
MyISAM与InnoDB 的区别
**MyISAM:**MyISAM是默认存储引擎(Mysql5.1前),每个MyISAM在磁盘上存储成三个文件,每一个文件的名字均以表的名字开始,扩展名指出文件类型。
.frm文件存储表定义
·MYD (MYData)文件存储表的数据
.MYI (MYIndex)文件存储表的索引
**InnoDB:**MySQL的默认存储引擎,给 MySQL 提供了具有事务(transaction)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)、多版本并发控制(multi-versioned concurrency control)的事务安全(transaction-safe (ACID compliant))型表。InnoDB 提供了行级锁(locking on row level),提供与 Oracle 类似的不加锁读取(non-locking read in SELECTs)。
MyISAM与InnoDB 的区别
InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务; InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败; 聚集索引 VS 非聚集索引
InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值
but, MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
总结
也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。
InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
那么为什么InnoDB没有了这个变量呢?
因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。 如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据。和上面提到的问题一样,如果此时存在多个事务的话这种方案也不太好用。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS
Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了 MyISAM表格可以被压缩后进行查询操作 InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁
InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。
例如:
t_user(uid, uname, age, sex) innodb;
uid PK
无其他索引
update t_user set age=10 where uid=1; 命中索引,行锁。
update t_user set age=10 where uid != 1; 未命中索引,表锁。
update t_user set age=10 where name='chackca'; 无索引,表锁。
8、InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有
9、Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
Innodb:frm是表定义文件,ibd是数据文件
Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
如何选择:
1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。
3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;
4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。
InnoDB为什么推荐使用自增ID作为主键?
答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。
innodb引擎的4大特性
插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)
事务与死锁
在MySQL的InnoDB中,预设的Tansaction isolation level 为REPEATABLE READ(可重读)
在SELECT 的读取锁定主要分为两种方式:
SELECT … LOCK IN SHARE MODE
SELECT … FOR UPDATE
这两种方式在事务(Transaction) 进行当中SELECT 到同一个数据表时,都必须等待其它事务数据被提交(Commit)后才会执行。
而主要的不同在于共享锁(lock in share mode) 在有一方事务要Update 同一个表单时很容易造成死锁。
简单的说,如果SELECT 后面若要UPDATE 同一个表单,最好使用SELECT … UPDATE。
MySQL SELECT … FOR UPDATE 的Row Lock 与Table Lock
上面介绍过SELECT … FOR UPDATE 的用法,不过锁定(Lock)的数据是判别就得要注意一下了。由于InnoDB 预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。
举个例子:
假设有个表单products ,里面有id 跟name 二个栏位,id 是主键。
例1: (明确指定主键,并且有此数据,row lock)
SELECT * FROM products WHERE id=‘3’ FOR UPDATE;
例2: (明确指定主键,若查无此数据,无lock)
SELECT * FROM products WHERE id=’-1’ FOR UPDATE;
例2: (无主键,table lock)
SELECT * FROM products WHERE name=‘Mouse’ FOR UPDATE;
例3: (主键不明确,table lock)
SELECT * FROM products WHERE id<>‘3’ FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM products WHERE id LIKE ‘3’ FOR UPDATE;
淘宝是如何使用悲观锁的
那么后端的数据库在高并发和超卖下会遇到什么问题呢?主要会有如下3个问题:(主要讨论写的问题,读的问题通过增加cache可以很容易的解决)
I: 首先MySQL自身对于高并发的处理性能就会出现问题,一般来说,MySQL的处理性能会随着并发thread上升而上升,但是到了一定的并发度之后会出现明显的拐点,之后一路下降,最终甚至会比单thread的性能还要差。
II: 其次,超卖的根结在于减库存操作是一个事务操作,需要先select,然后insert,最后update -1。最后这个-1操作是不能出现负数的,但是当多用户在有库存的情况下并发操作,出现负数这是无法避免的。
III:最后,当减库存和高并发碰到一起的时候,由于操作的库存数目在同一行,就会出现争抢InnoDB行锁的问题,导致出现互相等待甚至死锁,从而大大降低MySQL的处理性能,最终导致前端页面出现超时异常。
针对上述问题,如何解决呢? 我们先看眼淘宝的高大上解决方案:
I: 关闭死锁检测,提高并发处理性能。
在一个高并发的MySQL服务器上,事务会递归检测死锁,当超过一定的深度时,性能的下降会变的不可接受。FACEBOOK早就提出了禁止死锁检测。
我们做了一个实验,在禁止死锁检测后,TPS得到了极大的提升,如下图所示:
禁止死锁检测后,即使死锁发生,也不会回滚事务,而是全部等待到超时
Mysql 的 innobase_deadlock_check是在innodb里新加的系统变量,用于控制是否打开死锁检测
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,可以认为如果一个资源被锁定,它总会在以后某个时间被释放。而死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。 InnoDB的并发写操作会触发死锁,InnoDB也提供了死锁检测机制,可以通过设置innodb_deadlock_detect参数可以打开或关闭死锁检测:
innodb_deadlock_detect = on 打开死锁检测,数据库发生死锁时自动回滚(默认选项) innodb_deadlock_detect = off 关闭死锁检测,发生死锁的时候,用锁超时来处理,通过设置锁超时参数innodb_lock_wait_timeout 可以在超时发生时回滚被阻塞的事务
设置mysql 事务锁超时时间 innodb_lock_wait_timeout
Mysql数据库采用InnoDB模式,默认参数:innodb_lock_wait_timeout设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错。
mysql> SHOW GLOBAL VARIABLES LIKE ‘innodb_lock_wait_timeout’; ±-------------------------±------+ | Variable_name | Value | ±-------------------------±------+ | innodb_lock_wait_timeout | 50 | ±-------------------------±------+ 1 row in set (0.00 sec)
mysql> SET GLOBAL innodb_lock_wait_timeout=120; Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GLOBAL VARIABLES LIKE ‘innodb_lock_wait_timeout’; ±-------------------------±------+ | Variable_name | Value | ±-------------------------±------+ | innodb_lock_wait_timeout | 120 | ±-------------------------±------+ 1 row in set (0.00 sec)
mysql>
设置InnoDB Monitors方法
还可以通过设置InnDB Monitors来进一步观察锁冲突详细信息
建立test库
mysql>create database test;
Query OK, 1 row affected (0.20 sec)
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create table innodb_monitor(a INT) engine=innodb;
Query OK, 0 rows affected (1.04 sec)
mysql> create table innodb_tablespace_monitor(a INT) engine=innodb;
Query OK, 0 rows affected (0.70 sec)
mysql> create table innodb_lock_monitor(a INT) engine=innodb;
Query OK, 0 rows affected (0.36 sec)
mysql> create table innodb_table_monitor(a INT) engine=innodb;
Query OK, 0 rows affected (0.08 sec)
可以通过show engine innodb status命令查看死锁信息
mysql> show engine innodb status \G
*************************** 1. row ***************************
Type: InnoDB
Name:
Status:
=====================================
2018-05-10 09:17:10 0x7f1fbc21a700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 46 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 53 srv_active, 0 srv_shutdown, 240099 srv_idle
srv_master_thread log flush and writes: 0
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 2007
OS WAIT ARRAY INFO: signal count 1987
RW-shared spins 3878, rounds 5594, OS waits 1735
RW-excl spins 3, rounds 91, OS waits 4
RW-sx spins 1, rounds 30, OS waits 1
Spin rounds per wait: 1.44 RW-shared, 30.33 RW-excl, 30.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 78405
Purge done for trx's n:o < 78404 undo n:o < 10 state: running but idle
History list length 21
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421249967052640, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
.............................................................................
.............................................................................
.............................................................................
II:请求排队
修改源代码,将排队提到进入引擎层前,降低引擎层面的并发度。
如果请求一股脑的涌入数据库,势必会由于争抢资源造成性能下降,通过排队,让请求从混沌到有序,从而避免数据库在协调大量请求时过载。
请求排队:如果请求一股脑的涌入数据库,势必会由于争抢资源造成性能下降,通过排队,让请求从混沌到有序,从而避免数据库在协调大量请求时过载。
III:请求合并(组提交)
请求合并(组提交),降低server和引擎的交互次数,降低IO消耗。
甲买了一个商品,乙也买了同一个商品,与其把甲乙当做当做单独的请求分别执行一次商品库存减一的操作,不如把他们合并后统一执行一次商品库存减二的操作,请求合并的越多,效率提升的就越大。
实操建议
不过结合我们的实际,死锁监测可以关闭,但是,改mysql源码这种高大上的解决方案显然有那么一点不切实际。
InnoDB锁定模式及实现机制
考虑到行级锁定均由各个存储引擎自行实现,而且具体实现也各有差别,而InnoDB是目前事务型存储引擎中使用最为广泛的存储引擎,所以这里我们就主要分析一下InnoDB的锁定特性。 总的来说,InnoDB的锁定机制和Oracle数据库有不少相似之处。InnoDB的行级锁定同样分为两种类型,共享锁和排他锁,而在锁定机制的实现过程中为了让行级锁定和表级锁定共存,InnoDB也同样使用了意向锁(表级锁定)的概念,也就有了意向共享锁和意向排他锁这两种。 当一个事务需要给自己需要的某个资源加锁的时候,如果遇到一个共享锁正锁定着自己需要的资源的时候,自己可以再加一个共享锁,不过不能加排他锁。但是,如果遇到自己需要锁定的资源已经被一个排他锁占有之后,则只能等待该锁定释放资源之后自己才能获取锁定资源并添加自己的锁定。而意向锁的作用就是当一个事务在需要获取资源锁定的时候,如果遇到自己需要的资源已经被排他锁占用的时候,该事务可以需要锁定行的表上面添加一个合适的意向锁。如果自己需要一个共享锁,那么就在表上面添加一个意向共享锁。而如果自己需要的是某行(或者某些行)上面添加一个排他锁的话,则先在表上面添加一个意向排他锁。意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。
InnoDB的锁定模式实际上可以分为四种:共享锁(S),排他锁(X),意向共享锁(IS)和意向排他锁(IX),我们可以通过以下表格来总结上面这四种所的共存逻辑关系:
如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。
意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE
用SELECT … IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。
但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT… FOR UPDATE方式获得排他锁。
间隙锁(Next-Key锁)
当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁; 对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。 例: 假如emp表中只有101条记录,其empid的值分别是 1,2,…,100,101,下面的SQL:
mysql> select * from emp where empid > 100 for update;
是一个范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。 InnoDB使用间隙锁的目的: (1)防止幻读,以满足相关隔离级别的要求。对于上面的例子,要是不使用间隙锁,如果其他事务插入了empid大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读; (2)为了满足其恢复和复制的需要。 很显然,在使用范围条件检索并锁定记录时,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会对性能造成很大的危害。 除了间隙锁给InnoDB带来性能的负面影响之外,通过索引实现锁定的方式还存在其他几个较大的性能隐患: (1)当Query无法利用索引的时候,InnoDB会放弃使用行级别锁定而改用表级别的锁定,造成并发性能的降低; (2)当Query使用的索引并不包含所有过滤条件的时候,数据检索使用到的索引键所只想的数据可能有部分并不属于该Query的结果集的行列,但是也会被锁定,因为间隙锁锁定的是一个范围,而不是具体的索引键; (3)当Query在使用索引定位数据的时候,如果使用的索引键一样但访问的数据行不同的时候(索引只是过滤条件的一部分),一样会被锁定。 因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。 还要特别说明的是,InnoDB除了通过范围条件加锁时使用间隙锁外,如果使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁。
并发事务有什么什么问题?应该如何解决?
并发事务可能造成:脏读、不可重复读和幻读等问题 ,这些问题其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决,解决方案如下:
加锁:在读取数据前,对其加锁,阻止其他事务对数据进行修改。提供数据多版本并发控制(MultiVersion Concurrency Control,简称 MVCC 或 MCC),也称为多版本数据库:不用加任何锁, 通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot), 并用这个快照来提供一定级别 (语句级或事务级) 的一致性读取,从用户的角度来看,好象是数据库可以提供同一数据的多个版本。
什么是 MVCC?
MVCC 全称是多版本并发控制系统,InnoDB 和 Falcon 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决幻读问题。
MVCC 是怎么工作的?
InnoDB 的 MVCC 是通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间,一个保存行的过期时间(删除时间)。当然存储的并不是真实的时间而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动新增,事务开始时刻的系统版本号会作为事务的版本号,用来查询到每行记录的版本号进行比较。
REPEATABLE READ(可重读)隔离级别下 MVCC 如何工作?
SELECT:InnoDB 会根据以下条件检查每一行记录:第一,InnoDB 只查找版本早于当前事务版本的数据行,这样可以确保事务读取的行要么是在开始事务之前已经存在要么是事务自身插入或者修改过的。第二,行的删除版本号要么未定义,要么大于当前事务版本号,这样可以确保事务读取到的行在事务开始之前未被删除。INSERT:InnoDB 为新插入的每一行保存当前系统版本号作为行版本号。DELETE:InnoDB 为删除的每一行保存当前系统版本号作为行删除标识。UPDATE:InnoDB 为插入的一行新纪录保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为删除标识保存这两个版本号,使大多数操作都不用加锁。它不足之处是每行记录都需要额外的存储空间,需要做更多的行检查工作和一些额外的维护工作。
快照读和当前读
在mysql中select分为快照读和当前读,执行下面的语句
select * from table where id = ?; 执行的是快照读,读的是数据库记录的快照版本,是不加锁的。(这种说法在隔离级别为Serializable中不成立)
select加锁分析
下面六句Sql的区别呢
select * from table where id = ? select * from table where id < ? select * from table where id = ? lock in share mode select * from table where id < ? lock in share mode select * from table where id = ? for update select * from table where id < ? for update
在不同的事务隔离级别下,是否加锁,加的是共享锁还是排他锁,是否存在间隙锁,您能说出来嘛? 要回答这个问题,先问自己三个问题
当前事务隔离级别是什么id列是否存在索引如果存在索引是聚簇索引还是非聚簇索引呢?
关于mysql的索引,啰嗦一下:
innodb一定存在聚簇索引,默认以主键作为聚簇索引有几个索引,就有几棵B+树(不考虑hash索引的情形)聚簇索引的叶子节点为磁盘上的真实数据。非聚簇索引的叶子节点还是索引,指向聚簇索引B+树。
锁类型
共享锁(S锁):假设事务T1对数据A加上共享锁,那么事务T2可以读数据A,不能修改数据A。排他锁(X锁):假设事务T1对数据A加上共享锁,那么事务T2不能读数据A,不能修改数据A。 我们通过update、delete等语句加上的锁都是行级别的锁。只有LOCK TABLE … READ和LOCK TABLE … WRITE才能申请表级别的锁。意向共享锁(IS锁):一个事务在获取(任何一行/或者全表)S锁之前,一定会先在所在的表上加IS锁。意向排他锁(IX锁):一个事务在获取(任何一行/或者全表)X锁之前,一定会先在所在的表上加IX锁。
意向锁存在的目的?
这里说一下意向锁存在的目的。假设事务T1,用X锁来锁住了表上的几条记录,那么此时表上存在IX锁,即意向排他锁。那么此时事务T2要进行LOCK TABLE … WRITE的表级别锁的请求,可以直接根据意向锁是否存在而判断是否有锁冲突。
Record Locks:简单翻译为行锁吧。注意了,该锁是对索引记录进行加锁!锁是在加索引上而不是行上的。注意了,innodb一定存在聚簇索引,因此行锁最终都会落到聚簇索引上!Gap Locks:简单翻译为间隙锁,是对索引的间隙加锁,其目的只有一个,防止其他事物插入数据。在Read Committed隔离级别下,不会使用间隙锁。
这里我对官网补充一下,隔离级别比Read Committed低的情况下,也不会使用间隙锁,如隔离级别为Read Uncommited时,也不存在间隙锁。当隔离级别为Repeatable Read和Serializable时,就会存在间隙锁。
Next-Key Locks:这个理解为Record Lock + 索引前面的Gap Lock。记住了,锁住的是索引前面的间隙!比如一个索引包含值,10,11,13和20。那么,间隙锁的范围如下
(negative infinity, 10] (10, 11] (11, 13] (13, 20] (20, positive infinity)
索引原理介绍
先来一张带主键的表,如下所示,pId是主键
pIdnamebirthday5zhangsan2016-10-028lisi2015-10-0411wangwu2016-09-0213zhaoliu2015-10-07
画出该表的结构图如下
如上图所示,分为上下两个部分,上半部分是由主键形成的B+树,下半部分就是磁盘上真实的数据!那么,当我们, 执行下面的语句
select * from table where pId='11'
那么,执行过程如下 如上图所示,从根开始,经过3次查找,就可以找到真实数据。如果不使用索引,那就要在磁盘上,进行逐行扫描,直到找到数据位置。显然,使用索引速度会快。但是在写入数据的时候,需要维护这颗B+树的结构,因此写入性能会下降!
聚簇索引、非聚簇索引
**聚簇索引:**将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据
**非聚簇索引:**将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置
在innodb中,在聚簇索引之上创建的索引称之为辅助索引,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引。辅助索引叶子节点存储的不再是行的物理位置,而是主键值,辅助索引访问数据总是需要二次查找。
InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。(重点在于通过其他键需要建立辅助索引)
聚簇索引具有唯一性,由于聚簇索引是将数据跟索引结构放到一块,因此一个表仅有一个聚簇索引。
表中行的物理顺序和索引中行的物理顺序是相同的,在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行 按照一定的顺序排列,并且自动维护这个顺序;
聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索引代替。如果没有这样的索引,InnoDB 会**隐式定义一个主键(类似oracle中的RowId)**来作为聚簇索引。如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。
MyISAM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。
使用聚簇索引的优势:
**每次使用辅助索引检索都要经过两次B+树查找,**看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?
1.由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。
2.辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化;或者是我们需要查找的数据,在上一次IO读写的缓存中没有,需要发生一次新的IO操作时,可以避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储空间大小。
注:我们知道一次io读写,可以获取到16K大小的资源,我们称之为读取到的数据区域为Page。而我们的B树,B+树的索引结构,叶子节点上存放好多个关键字(索引值)和对应的数据,都会在一次IO操作中被读取到缓存中,所以在访问同一个页中的不同记录时,会在内存里操作,而不用再次进行IO操作了。除非发生了页的分裂,即要查询的行数据不在上次IO操作的换村里,才会触发新的IO操作。
3.因为MyISAM的主索引并非聚簇索引,那么他的数据的物理地址必然是凌乱的,拿到这些物理地址,按照合适的算法进行I/O读取,于是开始不停的寻道不停的旋转。聚簇索引则只需一次I/O。(强烈的对比)
4.不过,如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。
聚簇索引需要注意的地方
当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出线新增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。
建议使用int类型的自增,方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,主键值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量。
为什么主键通常建议使用自增id
聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想 象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一 页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。
四个隔离级别
我们先回忆一下事务的四个隔离级别,他们由弱到强如下所示:
Read Uncommited(RU):读未提交,一个事务可以读到另一个事务未提交的数据!Read Committed (RC):读已提交,一个事务可以读到另一个事务已提交的数据!Repeatable Read:(RR):可重复读,加入间隙锁,一定程度上避免了幻读的产生!注意了,只是一定程度上,并没有完全避免!我会在下一篇文章说明!另外就是记住从该级别才开始加入间隙锁(这句话记下来,后面有用到)!Serializable:串行化,该级别下读写串行化,且所有的select语句后都自动加上lock in share mode,即使用了共享锁。因此在该隔离级别下,使用的是当前读,而不是快照读。
select 分析的表数据
为了便于说明,我来个例子,假设有表数据如下,pId为主键索引
pId(int)name(varchar)num(int)1aaa1002bbb2007ccc200
隔离级别:RC/RU ,条件列: 非索引
(1)select * from table where num = 200 不加任何锁,是快照读。 (2)select * from table where num > 200 不加任何锁,是快照读。 (3)select * from table where num = 200 lock in share mode 当num = 200,有两条记录。这两条记录对应的pId=2,7,因此在pId=2,7的聚簇索引上加行级S锁,采用当前读。 (4)select * from table where num > 200 lock in share mode 当num > 200,有一条记录。这条记录对应的pId=3,因此在pId=3的聚簇索引上加上行级S锁,采用当前读。 (5)select * from table where num = 200 for update 当num = 200,有两条记录。这两条记录对应的pId=2,7,因此在pId=2,7的聚簇索引上加行级X锁,采用当前读。 (6)select * from table where num > 200 for update 当num > 200,有一条记录。这条记录对应的pId=3,因此在pId=3的聚簇索引上加上行级X锁,采用当前读。
隔离级别:RC/RU ,条件列: 聚簇索引
大家应该知道pId是主键列,因此pId用的就是聚簇索引。此情况其实和RC/RU+条件列非索引情况是类似的。 (1)select * from table where pId = 2 不加任何锁,是快照读。 (2)select * from table where pId > 2 不加任何锁,是快照读。 (3)select * from table where pId = 2 lock in share mode 在pId=2的聚簇索引上,加S锁,为当前读。 (4)select * from table where pId > 2 lock in share mode 在pId=3,7的聚簇索引上,加S锁,为当前读。 (5)select * from table where pId = 2 for update 在pId=2的聚簇索引上,加X锁,为当前读。 (6)select * from table where pId > 2 for update 在pId=3,7的聚簇索引上,加X锁,为当前读。
为什么条件列加不加索引,加锁情况是一样的?
其实是不一样的。在RC/RU隔离级别中,MySQL做了优化。在条件列没有索引的情况下,尽管通过聚簇索引来扫描全表,进行全表加锁。但是,MySQL Server层会进行过滤并把不符合条件的锁当即释放掉,因此你看起来最终结果是一样的。但是RC/RU+条件列非索引比本例多了一个释放不符合条件的锁的过程!
隔离级别:RC/RU ,条件列: 非聚簇索引
在num列上建上非唯一索引。此时有一棵聚簇索引(主键索引,pId)形成的B+索引树,其叶子节点为硬盘上的真实数据。以及另一棵非聚簇索引(非唯一索引,num)形成的B+索引树,其叶子节点依然为索引节点,保存了num列的字段值,和对应的聚簇索引。
(1)select * from table where num = 200 不加任何锁,是快照读。 (2)select * from table where num > 200 不加任何锁,是快照读。 (3)select * from table where num = 200 lock in share mode 当num = 200,由于num列上有索引,因此先在 num = 200的两条索引记录上加行级S锁。接着,去聚簇索引树上查询,这两条记录对应的pId=2,7,因此在pId=2,7的聚簇索引上加行级S锁,采用当前读。 (4)select * from table where num > 200 lock in share mode 当num > 200,由于num列上有索引,因此先在符合条件的 num = 300的一条索引记录上加行级S锁。接着,去聚簇索引树上查询,这条记录对应的pId=3,因此在pId=3的聚簇索引上加行级S锁,采用当前读。 (5)select * from table where num = 200 for update 当num = 200,由于num列上有索引,因此先在 num = 200的两条索引记录上加行级X锁。接着,去聚簇索引树上查询,这两条记录对应的pId=2,7,因此在pId=2,7的聚簇索引上加行级X锁,采用当前读。 (6)select * from table where num > 200 for update 当num > 200,由于num列上有索引,因此先在符合条件的 num = 300的一条索引记录上加行级X锁。接着,去聚簇索引树上查询,这条记录对应的pId=3,因此在pId=3的聚簇索引上加行级X锁,采用当前读。
隔离级别:RR/Serializable,条件列: 非索引
RR级别需要多考虑的就是gap lock,他的加锁特征在于,无论你怎么查都是锁全表。接下来分析开始 (1)select * from table where num = 200 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,在pId = 1,2,3,7(全表所有记录)的聚簇索引上加S锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock (2)select * from table where num > 200 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,在pId = 1,2,3,7(全表所有记录)的聚簇索引上加S锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock (3)select * from table where num = 200 lock in share mode 在pId = 1,2,3,7(全表所有记录)的聚簇索引上加S锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock (4)select * from table where num > 200 lock in share mode 在pId = 1,2,3,7(全表所有记录)的聚簇索引上加S锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock (5)select * from table where num = 200 for update 在pId = 1,2,3,7(全表所有记录)的聚簇索引上加X锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock (6)select * from table where num > 200 for update 在pId = 1,2,3,7(全表所有记录)的聚簇索引上加X锁。并且在 聚簇索引的所有间隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
隔离级别:RR/Serializable,条件列: 聚簇索引
大家应该知道pId是主键列,因此pId用的就是聚簇索引。该情况的加锁特征在于,如果where后的条件为精确查询(=的情况),那么只存在record lock。如果where后的条件为范围查询(>或<的情况),那么存在的是record lock+gap lock。 (1)select * from table where pId = 2 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,是当前读,在pId=2的聚簇索引上加S锁,不存在gap lock。 (2)select * from table where pId > 2 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,是当前读,在pId=3,7的聚簇索引上加S锁。在(2,3)(3,7)(7,+∞)加上gap lock (3)select * from table where pId = 2 lock in share mode 是当前读,在pId=2的聚簇索引上加S锁,不存在gap lock。 (4)select * from table where pId > 2 lock in share mode 是当前读,在pId=3,7的聚簇索引上加S锁。在(2,3)(3,7)(7,+∞)加上gap lock (5)select * from table where pId = 2 for update 是当前读,在pId=2的聚簇索引上加X锁。 (6)select * from table where pId > 2 for update 在pId=3,7的聚簇索引上加X锁。在(2,3)(3,7)(7,+∞)加上gap lock (7)select * from table where pId = 6 [lock in share mode|for update] 注意了,pId=6是不存在的列,这种情况会在(3,7)上加gap lock。 (8)select * from table where pId > 18 [lock in share mode|for update] 注意了,pId>18,查询结果是空的。在这种情况下,是在(7,+∞)上加gap lock。
隔离级别:RR/Serializable,条件列: 非聚簇索引
这里非聚簇索引,需要区分是否为唯一索引。因为如果是非唯一索引,间隙锁的加锁方式是有区别的。 先说一下,唯一索引的情况。如果是唯一索引,情况和RR/Serializable+条件列是聚簇索引类似,唯一有区别的是:这个时候有两棵索引树,加锁是加在对应的非聚簇索引树和聚簇索引树上!大家可以自行推敲! 下面说一下,非聚簇索引是非唯一索引的情况,他和唯一索引的区别就是通过索引进行精确查询以后,不仅存在record lock,还存在gap lock。而通过唯一索引进行精确查询后,只存在record lock,不存在gap lock。老规矩在num列建立非唯一索引 (1)select * from table where num = 200 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,是当前读,在pId=2,7的聚簇索引上加S锁,在num=200的非聚集索引上加S锁,在(100,200)(200,300)加上gap lock。 (2)select * from table where num > 200 在RR级别下,不加任何锁,是快照读。 在Serializable级别下,是当前读,在pId=3的聚簇索引上加S锁,在num=300的非聚集索引上加S锁。在(200,300)(300,+∞)加上gap lock (3)select * from table where num = 200 lock in share mode 是当前读,在pId=2,7的聚簇索引上加S锁,在num=200的非聚集索引上加S锁,在(100,200)(200,300)加上gap lock。 (4)select * from table where num > 200 lock in share mode 是当前读,在pId=3的聚簇索引上加S锁,在num=300的非聚集索引上加S锁。在(200,300)(300,+∞)加上gap lock。 (5)select * from table where num = 200 for update 是当前读,在pId=2,7的聚簇索引上加S锁,在num=200的非聚集索引上加X锁,在(100,200)(200,300)加上gap lock。 (6)select * from table where num > 200 for update 是当前读,在pId=3的聚簇索引上加S锁,在num=300的非聚集索引上加X锁。在(200,300)(300,+∞)加上gap lock (7)select * from table where num = 250 [lock in share mode|for update] 注意了,num=250是不存在的列,这种情况会在(200,300)上加gap lock。 (8)select * from table where num > 400 [lock in share mode|for update] 注意了,pId>400,查询结果是空的。在这种情况下,是在(400,+∞)上加gap lock。
死锁
MyISAM表锁是deadlock free的,这是因为MyISAM总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但在InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,当两个事务都需要获得对方持有的排他锁才能继续完成事务,这种循环锁等待就是典型的死锁。
如何避免死锁?
为了在单个 InnoDB 表上执行多个并发写入操作时避免死锁,可以在事务开始时通过为预期要修改的每个元祖(行)使用 SELECT … FOR UPDATE 语句来获取必要的锁,即使这些行的更改语句是在之后才执行的。 在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应先申请共享锁、更新时再申请排他锁,因为这时候当用户再申请排他锁时,其他事务可能又已经获得了相同记录的共享锁,从而造成锁冲突,甚至死锁 如果事务需要修改或锁定多个表,则应在每个事务中以相同的顺序使用加锁语句。在应用中,如果不同的程序会并发存取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会 在程序以批量方式处理数据的时候,如果事先对数据排序,保证每个线程按固定的顺序来处理记录,也可以大大降低出现死锁的可能。 在REPEATABLE-READ隔离级别下,如果两个线程同时对相同条件记录用SELECT…FOR UPDATE加排他锁,在没有符合该条件记录情况下,两个线程都会加锁成功。程序发现记录尚不存在,就试图插入一条新记录,如果两个线程都这么做,就会出现死锁。这种情况下,将隔离级别改成READ COMMITTED,就可避免问题。 当隔离级别为READ COMMITTED时,如果两个线程都先执行SELECT…FOR UPDATE,判断是否存在符合条件的记录,如果没有,就插入记录。此时,只有一个线程能插入成功,另一个线程会出现锁等待,当第1个线程提交后,第2个线程会因主键重出错,但虽然这个线程出错了,却会获得一个排他锁。这时如果有第3个线程又来申请排他锁,也会出现死锁。对于这种情况,可以直接做插入操作,然后再捕获主键重异常,或者在遇到主键重错误时,总是执行ROLLBACK释放获得的排他锁
InnoDB 默认是如何对待死锁的?
InnoDB 默认是使用设置死锁时间来让死锁超时的策略,默认 innodblockwait_timeout 设置的时长是 50s。
如何开启死锁检测?
设置 innodbdeadlockdetect 设置为 on 可以主动检测死锁,在 Innodb 中这个值默认就是 on 开启的状态。
解决方案2:乐观锁
乐观锁
乐观锁并不是真实存在的锁,而是在更新的时候判断此时的库存是否是之前查询出的库存,如果相同,表示没人修改,可以更新库存,否则表示别人抢过资源,不再执行库存更新。类似如下操作:
update tb_sku set stock=2 where id=1 and stock=7;
SKU.objects.filter(id=1, stock=7).update(stock=2)
使用乐观锁需修改数据库的事务隔离级别:
使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交(Read committed)。 修改方式:
MySQL事务隔离级别
事务隔离级别脏读不可重复读幻读读未提交(read-uncommitted)是是是不可重复读(read-committed)否是是可重复读(repeatable-read)否否是串行化(serializable)否否否
mysql默认的事务隔离级别为repeatable-read
并发事务会带来哪些问题?
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
三、MySQL事务隔离级别
Mysql默认的事务隔离级别为repeatable-read
四、用例子说明各个隔离级别的情况
1、读未提交:
(1)打开一个客户端A,并设置当前事务模式为read uncommitted(未提交读),查询表account的初始值:
(2)在客户端A的事务提交之前,打开另一个客户端B,更新表account:
(3)这时,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据:
(4)一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据:
(5)在客户端A执行更新语句update account set balance = balance - 50 where id =1,lilei的balance没有变成350,居然是400,是不是很奇怪,数据不一致啊,如果你这么想就太天真 了,在应用程序中,我们会用400-50=350,并不知道其他会话回滚了,要想解决这个问题可以采用读已提交的隔离级别
2、读已提交
(1)打开一个客户端A,并设置当前事务模式为read committed(提交读),查询表account的所有记录:
(2)在客户端A的事务提交之前,打开另一个客户端B,更新表account:
(3)这时,客户端B的事务还没提交,客户端A不能查询到B已经更新的数据,解决了脏读问题:
(4)客户端B的事务提交
(5)客户端A执行与上一步相同的查询,结果 与上一步不一致,即产生了不可重复读的问题
3、可重复读
(1)打开一个客户端A,并设置当前事务模式为repeatable read,查询表account的所有记录
(2)在客户端A的事务提交之前,打开另一个客户端B,更新表account并提交
(3)在客户端A查询表account的所有记录,与步骤(1)查询结果一致,没有出现不可重复读的问题
(4)在客户端A,接着执行update balance = balance - 50 where id = 1,balance没有变成400-50=350,lilei的balance值用的是步骤(2)中的350来算的,所以是300,数据的一致性倒是没有被破坏。可重复读的隔离级别下使用了MVCC机制,select操作不会更新版本号,是快照读(历史版本);insert、update和delete会更新版本号,是当前读(当前版本)。
(5)重新打开客户端B,插入一条新数据后提交
(6)在客户端A查询表account的所有记录,没有 查出 新增数据,所以没有出现幻读
4.串行化
(1)打开一个客户端A,并设置当前事务模式为serializable,查询表account的初始值:
mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from account;
+------+--------+---------+
| id | name | balance |
+------+--------+---------+
| 1 | lilei | 10000 |
| 2 | hanmei | 10000 |
| 3 | lucy | 10000 |
| 4 | lily | 10000 |
+------+--------+---------+
4 rows in set (0.00 sec)
(2)打开一个客户端B,并设置当前事务模式为serializable,插入一条记录报错,表被锁了插入失败,mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。
mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into account values(5,'tom',0);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
补充:
1、事务隔离级别为读提交时,写数据只会锁住相应的行
2、事务隔离级别为可重复读时,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。
3、事务隔离级别为串行化时,读写数据都会锁住整张表
4、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
乐观锁在高并发场景下的问题
乐观锁在高并发场景下的问题,是严重的空自旋
具体可以参考 入大厂必备的基础书籍: 《Java高并发核心编程 卷2》
超卖解决方案3:分阶段排队下单方案
分阶段排队下单方案的思想来源
最优的解决方案,其实思想来自于JUC的原理
JUC是如何提高性能的,引入队列
原始的CLH队列
用于减少线程争用的最简单的队列,CLH队列,具体可以参考 入大厂必备的基础书籍: 《Java高并发核心编程 卷2》
JUC的AQS内部队列
AQS内部队列是JUC高性能的基础,AQS队列,具体可以参考 入大厂必备的基础书籍: 《Java高并发核心编程 卷2》
分阶段排队下单方案
将提交操作变成两段式:
第一阶段申请,申请预减减库,申请成功之后,进入消息队列; 第二阶段确认,从消息队列消费申请令牌,然后完成下单操作。 查库存 -> 创建订单 -> 扣减库存。通过分布式锁保障解决多个provider实例并发下单产生的超卖问题。
申请阶段:
将存库从MySQL前移到Redis中,所有的预减库存的操作放到内存中,由于Redis中不存在锁故不会出现互相等待,并且由于Redis的写性能和读性能都远高于MySQL,这就解决了高并发下的性能问题。
确认阶段:
然后通过队列等异步手段,将变化的数据异步写入到DB中。
引入队列,然后数据通过队列排序,按照次序更新到DB中,完全串行处理。当达到库存阀值的时候就不在消费队列,并关闭购买功能。这就解决了超卖问题。
分阶段排队架构图
基于分段的排队执行方案的性能提升
一个高性能秒杀的场景:
假设一个商品1分钟6000订单,每秒的 600个下单操作。
在排队阶段,每秒的 600个预减库存的操作,对于 Redis 来说,没有任何压力。甚至每秒的 6000个预减库存的操作,对于 Redis 来说,也是压力不大。
但是在下单阶段,就不一样了。假设加锁之后,释放锁之前,查库存 -> 创建订单 -> 扣减库存,经过优化,每个IO操作100ms,大概200毫秒,一秒钟5个订单。600个订单需要120s,2分钟才能彻底消化。
如何提升下单阶段的性能呢?
可以使用Redis 分段锁。
为了达到每秒600个订单,可以将锁分成 600 /5 =120 个段,每个段负责5个订单,600个订单,在第二个阶段1秒钟下单完成。
有关Redis分段锁的详细知识,请阅读下面的博文:
Redis分布式锁 (图解-秒懂-史上最全)
基于分段的排队执行方案优点:
解决超卖问题,库存读写都在内存中,故同时解决性能问题。
基于分段的排队执行方案缺点:
数据不一致的问题:
由于异步写入DB,可能存在数据不一致,存在某一时刻DB和Redis中数据不一致的风险。
可能存在少买
可能存在少买,也就是如果拿到号的人不真正下订单,可能库存减为0,但是订单数并没有达到库存阀值。
参考文献:
https://www.cnblogs.com/rjzheng/p/9950951.html
https://blog.csdn.net/caoxiaohong1005/article/details/78292457
https://www.cnblogs.com/wyaokai/p/10921323.html
优惠劵
40岁资深老架构师尼恩
关注
关注
16
点赞
踩
87
收藏
觉得还不错?
一键收藏
知道了
1
评论
秒杀:超卖问题(图解+秒懂+史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源:免费赠送 经典图书 : 极致经典 + 社群大片好评 《 Java 高并发 三部曲 》 面试必备 + 大厂必备 + 涨薪必备免费赠送 经典图书 : 《Netty Zookeeper Redis 高并发实战》 面试必备 + 大厂必备 +涨薪必备 (加尼恩领取)免费赠送 经典图书 : 《SpringCloud、Nginx高并发核心编程》 面试必备 + 大
复制链接
扫一扫
专栏目录
Spring Boot + redis解决商品秒杀库存超卖
06-11
在众多抢购活动中,在有限的商品数量的限制下如何保证抢购到商品的用户数不能大于商品数量,也就是不能出现超卖的问题;还有就是抢购时会出现大量用户的访问,如何提高用户体验效果也是一个问题,也就是要解决秒杀系统的性能问题。本文主要介绍基于redis 实现商品秒杀功能。先来跟大家讲下大概思路
并发秒杀系统中超卖问题与重复下单问题的解决思路
xzystart的博客
02-07
5181
什么是超卖问题
问题原始描述:两用户查询某商品库存都是1,导致卖出2个商品,产生了超卖问题。
超卖导致的原因:
不同用户检查库存够用,然后并发下订单,减库存,由于检查库存和减少库存这两个操作不保证原子性,所以可能会出现本线程检查库存够用到实际减少库存操作之间,其他线程抢先扣除库存导致本线程扣除库存后库存出现负数,引发超卖。
秒杀下单流程
判断用户是否登陆,是否有收货地址等
判断库存是否够用
判断是否已经秒杀到了,防止重复下单
减库存
创建订单
流程中可能会出现的问题
超卖问题,由于步骤2与步骤4并不是
1 条评论
您还未登录,请先
登录
后发表或查看评论
【Redis】电商项目秒杀问题之超卖问题与一人一单问题
qq_61903414的博客
05-10
1957
在如双11等购物需求剧增的背景下,一个物品库存里有100件但是由于并发等问题可能会导致该物品被卖出超过100件。这就是超卖问题,他是由于库存量被高并发请求而产生的线程安全问题。
订单业务中的重要问题:超卖问题的解决方案
lyq1525761478的博客
05-28
823
超卖问题,通俗的来说就是我们商家只有100件库存但是卖出去了100+件商品,出现了多买的问题。出现的场景:举个简单的例子:比如此时只剩下了最后一个商品,有两个人在抢这最后一个商品,此时A进行到了下单的页面,但是网速很慢卡在了这里,此时库存的数量还是没有扣除的一直在转圈圈,但是此时另一个人的网速快已经下单并且支付成功了,此时数据库中的库存数量已经减一变成了0,突然此时A结束转圈了去支付了,也下单了,那么库存就变成了-1,这只是有两个人在同时抢,那么你想想如果有10w人在一起抢呢?
基于Springboot的电商秒杀系统+源代码+文档说明
11-29
# miaoshaSystem
基于Springboot的电商秒杀系统
使用技术栈:mysql+springboot+Redis+RabbitMQ
防止超卖手段:
1. 在sql加上判断防止数据变为负数(MYSQL的行锁支持)
2. 数据库唯一索引,防止重复购买
3. 使用消息队列
## 项目备注
1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!
2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。
3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。
下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
商城超卖问题的几种解决方案
热门推荐
yongde123的专栏
02-19
1万+
一、描述:
商城设计的过程中,必然会考虑到一个库存扣除的问题,超卖将会带来一定的损失和麻烦,在某一个时间段的瞬间的流量会造成库存的并发性操作带来库存超额扣除。针对这类的问题,我先来分析原因吧。
二、为什么会被超卖
只有弄清楚为什么会被超卖才能解决超卖问题,这里我们要弄清楚mysql的默认的扣除方式,update 表 store=store-1 where id=指定的id
首先我们看这样的语句有哪些问题呢?
库存有可能扣到
超卖问题及其解决方法
E_N_T_J的博客
03-02
9155
超卖问题介绍
在高并发的场景下,比如商城秒杀活动中,一件商品的销售数量>库存数量的问题,称为超卖问题。主要原因是在高并发场景下,大量请求几乎同时到达,对库存资源进行竞争,由于没有适当的并发控制策略导致的错误。
简单的下单操作
如果没有并发的控制策略,则在下单时只需要考虑如下几步:查询库存数量、判断是否满足订单数量需求,提示库存不足或者减库存下单成功。通常我们会按照如下写法
public Serve...
分布式商城系统架构中的超卖问题深度剖析(从问题原因到解决方案到优化总结)以及重复下单问题
xjx666666的博客
03-20
1225
最终决定把数据都存到redis,然后尝试了redis分布式锁,发现其并发量并不高,因为redis分布式锁实质是一种分布式悲观锁,它将处理串行化。就是并发场景下,多线程或者多进程对共享资源(库存资源)进行竞争导致的(因为MySQL数据库中的数据对于它们来说属于共享资源),因此这种多线程以及多进程环境下对于共享资源的竞争问题我们需要对共享资源进行保护。下就需要分布式锁,如Redis实现分布式锁。首先,超卖问题的出现是由于高并发环境下,大量秒杀请求同时发给服务端导致的秒杀商品的销售数量>其库存数量的问题。
商品超买超卖问题分析及实战
弹指天下
02-23
4171
商品超买超卖是高并发下非常典型的问题,也是面试中秒杀场景常常会问到的问题。
常见的问题有:
1、怎么设计一个秒杀系统?
2、商品超买、超卖问题产生的原因?
3、怎么防止商品出现超买|超卖问题?
4、乐观锁和悲观锁的适用场景是什么?
5、提高事务的隔离级别能解决超买|超卖问题吗?
超卖问题解决大全
fly_miqiqi的博客
02-17
9742
文章目录什么是库存超卖??方式一:扣减库存时限制库存量大于0方式二:悲观锁方式三:乐观锁方式四:将请求放队列方式五:通过事务控制超卖方式六使用redis分布式来解决(悲观锁)基于redis实现分布式锁基于redisson开源框架实现redis分布式锁的缺点redis分布式锁优化redis分布式锁优化缺点方式七使用redis的原子操作解决超卖共享锁和排他锁共享锁和排他锁的加锁原则Spring事务-数...
Java开发商品秒杀+限流+限时抢购+隐藏接口源码.zip
06-02
Java开发商品秒杀+限流+限时抢购+隐藏接口源码。适用于高并发场景下商品秒杀,包含内容商品超卖问题、接口访问限流问题、Redis限时抢购、隐藏秒杀接口、单用户限制访问频率!为什么使用秒杀】
严格防止超卖
库存100件 你卖了120件 等着辞职吧!
防止黑客
假如我们网站想下发优惠给群众,但是被黑客利用技术将下发给群众的利益收入囊中
保证用户体验
高并发场景下,网页不能打不开、订单不能支付 要保证网站的使用
搭建数据库
create database stockdb;
use stockdb;
# 用户
create table `user`(
uid int primary key auto_increment,
uname varchar(100),
upwd varchar(50)
);
# 商品
create table stock(
id int primary key auto_increment,
`name` varchar(50),
`count` int, #库存数量
sale int, #已售
`version` int #版本号(乐观
PHP+Redis链表解决高并发下商品超卖问题(实现原理及步骤)
01-19
上一篇文章聊了一下使用Redis事务来解决高并发商品超卖问题,今天我们来聊一下使用Redis链表来解决高并发商品超卖问题。
实现原理
使用redis链表来做,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用。
实现步骤
第一步,先将商品库存入队列
/**
* 添加商品数量到商品队列
* @param int $couponId 优惠券ID
*/
function addCoupons($couponId)
{
//1.初始化Redis连接
$redis = new Redis();
if (!$redis->connect('127.0.0.1', 6379
Redis的类库及Redis解决订单秒杀超卖问题,极光推送代码
07-09
1.C# .Net Core 极光推送代码
2.Redis的类库
3.Redis中的String类型及使用Redis解决订单秒杀超卖问题
php+redis实现商城秒杀功能
10-18
主要为大家详细介绍了php+redis实现商城秒杀功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
基于 SpringBoot+Mybatis+Redis+RabbitMQ 秒杀系统
05-29
1)、页面缓存、商品详情静态化、订单静态化(感兴趣可以把所有页面都做静态化)
2)、加入消息队列RabbitMQ,对秒杀接口进行优化。
3)、隐藏秒杀接口地址
4)、接口限流防刷
5)、解决超卖问题
PHP+Redis事务解决高并发下商品超卖问题(推荐)
12-17
我所在的公司也遇到了同样的问题,问题发生在优惠券被超量抢购上,在问题发生后我们开始想办法解决问题,由于自己使用redis比较多,我准备使用redis来解决这个问题。利用redis的高性能和事务特性来解决线上优惠券被...
Redis中的String类型及使用Redis解决订单秒杀超卖问题
01-19
本系列将和大家分享Redis分布式缓存,本章主要简单介绍下Redis中的String类型,以及如何使用Redis解决订单秒杀超卖问题。 Redis中5种数据结构之String类型:key-value的缓存,支持过期,value不超过512M。 Redis是...
javaWeb的个人学习05
m0_74304371的博客
03-01
310
javaWeb的个人学习05
《剑指 Offer》专项突破版 - 面试题 65、66 和 67 : 关于前缀树应用的面试题(C++ 实现)
最新发布
melonyzzZ的博客
03-02
855
面试题 65 : 最短的单词编码
面试题 66 : 单词之和
面试题 67 : 最大的异或
秒杀系统超卖少卖问题
09-10
在秒杀系统中,超卖和少卖是常见的问题。超卖指的是在秒杀活动中售卖的商品数量超过了实际库存数量,而少卖则是指实际库存数量大于秒杀活动中售卖的商品数量。这两个问题都会给商家和消费者带来一些困扰。
超卖问题可能出现在秒杀活动赶上热销商品时,由于系统处理延迟、并发请求等原因,导致实际销售数量超过了库存数量。这会造成一些消费者购买了实际上已经售罄的商品,给消费者带来不满和投诉,同时也对商家的声誉和销售利益造成损害。
少卖问题则是指实际库存数量大于秒杀活动中售卖的商品数量。这可能是由于系统数据同步延迟、售卖过程中出现异常等原因导致的。对于商家来说,这会导致潜在的销售机会的浪费,同时也会让消费者失去购买心愿。
为了解决超卖和少卖问题,秒杀系统需要做到以下几点:
1. 系统实时库存更新:系统需确保在秒杀活动中及时更新库存数量,避免超卖和少卖的情况发生。
2. 并发请求处理:系统需要具备足够的并发处理能力,能够同时处理大量用户的请求,避免因系统处理延迟而导致的超卖问题。
3. 限制购买数量:通过设置购买数量限制,可以避免某些用户一次性购买大量商品,从而平衡库存和需求之间的关系。
4. 实时监控和报警机制:建立实时监控和报警机制,及时发现库存异常变动,以便及时采取措施解决问题。
总之,秒杀系统超卖和少卖问题是需要特别留意的,商家需要通过合理的系统设计和管理措施来减少这类问题的发生,以提供良好的用户体验和保护商家的利益。
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
40岁资深老架构师尼恩
CSDN认证博客专家
CSDN认证企业博客
码龄6年
暂无认证
432
原创
2064
周排名
1221
总排名
199万+
访问
等级
1万+
积分
9773
粉丝
3874
获赞
452
评论
2万+
收藏
私信
关注
热门文章
TCP协议详解 (史上最全)
77973
Zookeeper 分布式锁 - 图解 - 秒懂
69140
Linux命令大全:2W多字,一次实现Linux自由
62544
Java面试题(2021版),持续整理中ing.......
56390
Docker面试题(史上最全 + 持续更新)
50602
分类专栏
面试
202篇
技术圣经
42篇
高并发
5篇
linux
1篇
java
203篇
最新评论
限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)
m0_62616608:
博主请问 令牌桶的发放速度可以改变 为什么漏桶的漏水速率不能改变?
限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)
m0_62616608:
你再仔细看看
Akka 入门 实战
CSDN-Ada助手:
多亏了你这篇博客, 解决了问题: https://ask.csdn.net/questions/7975834, 请多输出高质量博客, 帮助更多的人
TCP协议详解 (史上最全)
CodingZP:
写的真好,好好好好好好好好好好好好
阿里面试:Seata如何实现RC?保证事务的隔离性?
九阳雕大侠:
非常受益
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
600万订单每秒Disruptor +SpringBoot,如何解决消息不丢失?
阿里面试:最佳线程数,如何确定?
绝命一问:秒杀Redis分段锁,如何设计?
2024年23篇
2023年201篇
2022年42篇
2021年61篇
2020年30篇
2019年47篇
2018年34篇
目录
目录
分类专栏
面试
202篇
技术圣经
42篇
高并发
5篇
linux
1篇
java
203篇
目录
评论 1
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
添加红包
祝福语
请填写红包祝福语或标题
红包数量
个
红包个数最小为10个
红包总金额
元
红包金额最低5元
余额支付
当前余额3.43元
前往充值 >
需支付:10.00元
取消
确定
下一步
知道了
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝
规则
hope_wisdom 发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
0
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。
余额充值
超买超卖_百度百科
_百度百科 网页新闻贴吧知道网盘图片视频地图文库资讯采购百科百度首页登录注册进入词条全站搜索帮助首页秒懂百科特色百科知识专题加入百科百科团队权威合作下载百科APP个人中心超买超卖播报讨论上传视频金融学术语收藏查看我的收藏0有用+10对某种金融交易标的物的过度买入称之为超买,反之,过度卖出则称之为超卖。在学习识别超买超卖指标之前,首先要对其有个大概的了解。所谓的超买超卖指标是因为价格的运行趋势的惯性存在因素造成的。中文名超买超卖超 买对某种股票的过度买入超 卖对于某种股票的过度卖出原 因股价的运行趋势的惯性存在造成目录1研判方法2作用3逆转交易研判方法播报编辑OBOS的研判方法主要便是将指数线与OBOS线相联系再判断。与均量线的判别方法一样,如果二线同升,便是好现象;二线同降,便是坏行情;指数线上升,OBOS下降,表明许多小盘股已走下坡路。道理很简单:指数是由众多股票组成的,指数上升,表明占权重较大的大盘股还在上升,而OBOS并非加权算法,它只算个数。OBOS的下降,说明整个市场许多股票都在下跌,但这些跌股却是指数中占权重不大的小盘股;尽管如此,小盘股的下跌预示着股市将转为弱势,所以,是个卖出信号。同理,指数若在下降,OBOS却在上升,表明中小盘股已有起色,所以股市即将反转。通过KDJ和RSI指标来分析,我们知道其正常的波动范围在20-80之间,那么,我们就可以认为,如果波动范围超过80我们即为超买,低于20即称为超卖。钝化情况是发生在指标停在超买和超卖区3个交易日以上。作用播报编辑超买超卖(OBOS)是一种衡量大势涨跌气势的分析工具,计算简单,分析方法也简单,却很实用。我们将N日内上涨股票个数总和算出,再将这些日内下跌的个数总和算出,相减后,得到的便是OBOS值,比如说,第一日涨了20家股票,跌了10家,第二日却涨了29家股票,跌了1家,那么OBOS2的值便是20+29-(10+1)=38。当然,在实际分析中,这个N日的取值不宜过 [1]小,一般取10日左右为宜。股市上,经常会出现因某种消息的传播而使投资者对大盘或个股作出强烈的反应,以致引起股市或个股出现过分的上升或下跌,于是便产生了超买超卖现象。当投资者的情绪平静下来以后,超买超卖所造成的影响会逐渐得到适当的调整。因此,超买之后就会是股价出现一段回落;超卖之后,则会出现相当程度的反弹。投资者如了解这种超买超卖现象,并及时把握住其运动规律,就又能在股市中增加获利机会。这里的关键是,如何适时地测度出股市上的超买超卖现象.测度超买超卖现象的技术分析方法很多,主要有相对强弱指数(RSI)、摆动指数(OSC)、随机指数(KDJ)及百分比等。逆转交易播报编辑历史情况记录分析显示,在背驰的情况下进行操作,交易能达到80%的成功率。我们可以通过两个方面来判断股价在短时间内是否会发生逆转 [2]。1,背驰情况是否存在。意思是股价在新高和新低的时候,指标并未在新高和新低,这就是背驰。甚至出现一种情况是股价和指标的新高、新低位置正相反,也就是所谓的“勾头”,这也就预示着,应该是我们进行反向操作的时候了。2,由于参考常用指标的分析者非常多,所以导致失真情况发生。所以,建议大家可以参考其他的一些技术指标,或是将指标的时间参数调整的略长一些,从而使其的变化不会太敏感,这样可参考性也就提高了很多。新手上路成长任务编辑入门编辑规则本人编辑我有疑问内容质疑在线客服官方贴吧意见反馈投诉建议举报不良信息未通过词条申诉投诉侵权信息封禁查询与解封©2024 Baidu 使用百度前必读 | 百科协议 | 隐私政策 | 百度百科合作平台 | 京ICP证030173号 京公网安备110000020000什么是超买和超卖?如何准确判断?丨实战技巧 - 交易知识丨FxGoPlus
什么是超买和超卖?如何准确判断?丨实战技巧 - 交易知识丨FxGoPlus
跳至内容普拉斯财经 - 汇集全球热点新闻,为投资交易者提供最有价值的证券、期货、外汇、大宗商品、贵金属、数字货币等金融财经信息。 Search Search 普拉斯财经实时行情黄金白银原油美元欧元英镑新闻资讯热点新闻经纪商新闻监管公告知识百科交易知识加密货币外汇股票期货基金期权技术分析常见问题交易经验入门视频经纪商活动通知赠金活动交易通知交易支持热门书籍 Menu普拉斯财经实时行情黄金白银原油美元欧元英镑新闻资讯热点新闻经纪商新闻监管公告知识百科交易知识加密货币外汇股票期货基金期权技术分析常见问题交易经验入门视频经纪商活动通知赠金活动交易通知交易支持热门书籍什么是超买和超卖?如何准确判断?丨实战技巧首页 » 交易知识 » 什么是超买和超卖?如何准确判断?丨实战技巧 作者: 交易员的261天 更新日期:2020-12-19 评分 识别超买和超卖状态是交易股票、商品和一系列其他市场的关键部分。它们可以帮助交易员准确的判断进场和出场的位置。 因此,了解超买和超卖是什么以及如何准确的识别它们是很重要的。那今天我们就给大家详细的介绍一下。 文章目录 什么是超买和超卖?超买和超卖水平描述了一项资产的价格与其真实价值的关系。它们有助于确定市场条件和未来趋势,为一系列资产类别提供买入和卖出点。这些水平最常见的是与股票相关,但也可用于交易期权、外汇和商品。例如,当一只股票被归类为超买时,意味着之前价格一直在持续上涨。这可能导致该资产的交易价格高于其实际价值。一旦市场达到一个成熟点,交易者认为它太贵了,回调就很有可能出现,价格就会下降。另一方面,一只超卖的股票,就是当前的价格低于其实际价值。这表明下跌行情即将结束,反弹可能即将到来。超买和超卖的情况是由对新闻、财经数据和其他市场变动事件的过度反应引起的,往往会将价格带到极端。因此,识别这些价格走势何时达到成熟期,是一个好的交易策略的基石。如何识别超买和超卖?识别超买和超卖水平的最佳方法是通过技术分析,使用价格图表和技术指标来突出市场运动的模式。技术分析是基于这样的假设:历史趋势会重复出现,因此之前的水平可以帮助预测未来的走势。有各种技术指标可用于识别超买和超卖水平,但有些指标比其他指标更有效。用于绘制超买和超卖条件图表的两个最流行的指标是相对强弱指数(RSI)和随机指标。随机震荡指标全详解(Stochastic Oscillator)你可以单独使用这两个指标,也可以结合其他技术指标使用。相对强弱指数 RSI指标RSI是一个动量指标,用于衡量价格变动的速度。它以在零和100之间移动的百分比表示。如果百分比超过70,一般认为市场超买,如果低于30,通常会被认为是超卖。需要注意的是,RSI可以在这些点位的上方和下方停留很长时间。人们很容易选择任何一个顶部或底部,并认为市场会转向,但市场保持超买或超卖的时间可能比你预期的要长。当使用RSI时,关键是要等到指标水平回到70以下或30以上交叉。这表明市场条件真正发生了变化。RSI指标详解 随机指标 stoch随机指标用于比较资产的当前价格水平和其在设定的时间范围,通常是14个周期。在上升趋势中,市场将倾向于接近其高点,而在下降趋势中,它将接近其低点。当价格远离这些极端值而向价格区间的中间移动时,通常是动能耗尽的迹象,很可能改变方向。和RSI一样,随机指标在零和100之间波动。随机指数的值超过80通常表示超买状态,而20或更低的值通常表示超卖状态。随机指标也和RSI一起使用由于RSI水平可以在相当长的时间内保持在高位或低位,通过添加随机指标,可以看到何时动能发生变化,价格开始远离极端值。当您进行差价合约交易时,您可以在一个巨大的市场范围内做多或做空,这使得超买和超卖信号成为一个很好的选择。为了利用超买水平,您将瞄准确定市场达到最高极值的点位。在这一点上,您会开立空头头寸,利用市场修正到较低价格的机会。对于超卖水平,你会采取相反的策略,找到市场的底部,开立多头仓位,利用即将到来的上涨行情。请记住,找到合适的出场信号也是同样的重要。RSI和随机震荡指标都可以用来观察趋势何时结束,表明是时候结束交易了。超买和超卖的总结超买和超卖水平用于描述资产的价格与其实际价值的关系。最常用于股票交易,但也适用于其他市场,如期权、外汇和商品。超买是当价格大幅上涨,导致该资产的价格高于其实际价值,随后可能会出现一段低迷期。超卖是经历了持续的价格下跌,导致资产价值低于其真实价值,价格很快会开始反弹。识别超买和超卖水平的最佳方法是使用技术分析观察价格图表和指标,以突出市场运动的模式。两个流行的超买和超卖指标是相对强弱指数和随机震荡指标。确定交易的进场和出场价位很重要。有几种常见的工具可以用来补充超买和超卖信号。以下是可以增强您的交易决策方法。识别趋势:对趋势进行过滤可以帮助交易者利用超买和超卖信号选择入场点。例如,利用MACD指标进行趋势交易,在上升趋势中,交易者会过滤掉错误的超卖信号,这与趋势的方向相关。反之,则适用于下跌趋势。风险管理:使用适当的风险回报比率,这与止损和止盈的设定水平有关,应予以遵守。 外汇中级知识, 外汇技术指标 Facebook Twitter LinkedIn Telegram Prev上一页RSI指标详解 相对强弱指标 下一页什么是负利率?负利率时代真的来了Next 经纪商活动 热门经纪商了解更多>> 热门标签外汇知识股票知识基金知识期货知识期权知识加密货币知识日本蜡烛图技术指标MT4监管机构热门文章美元黄金白银英镑欧元原油澳元日元加元 Menu外汇知识股票知识基金知识期货知识期权知识加密货币知识日本蜡烛图技术指标MT4监管机构热门文章美元黄金白银英镑欧元原油澳元日元加元热门文章 什么是投机交易?初学者指南 2022-03-20 什么是场外交易市场(OTC)? 2021-12-04 什么是金融衍生品?(Derivatives) 2021-12-03 什么是能量潮指标?丨OBV指标详解和实战用法 2021-05-03 如何通过做空股票赚钱? 2021-04-21 页岩油和石油的区别 2021-02-26 延伸阅读 相关基础知识 更多>> 什么是黑天鹅?丨Black Swan Theory 2023-12-04 什么是高频交易(High-Frequency Trading)? 2022-11-27 什么是交易台丨Trading Desk 2022-10-29 社区交易和复制交易的区别 2022-05-02 什么是外汇互换(掉期)? 2022-04-05 技术分析 更多>> 黄金价格预测:XAU/USD有向1990美元上升的空间,技术面看涨 2022-03-25 黄金价格预测:回撤至1922美元支撑位 2022-03-23 黄金价格分析:市场气氛不一,XAU/USD在1795美元处盘整 2021-12-23 黄金价格分析:尽管美联储态度鹰派,但XAU/USD继续上行 2021-12-16 英镑/美元在1.3250附近徘徊 关注英国和美国PMI、英国央行货币政策 2021-12-16 经纪商IC MarktesXMExnessIC MarktesXMExness客户支持赠金活动入门书籍赠金活动入门书籍关于我们站内地图隐私政策条款和条件站内地图隐私政策条款和条件© 2023 金融交易市场存在极大的不确定性和风险,投资者在开立账户时应仔细阅读券商及产品的法律文件,了解产品风险和收益特征(包括系统性风险和特定产品所特有的投资风险等)。投资者应根据自身资产状况、风险承受能力选择适合的产品。普拉斯财经提供的宣传材料仅供投资者参考,不构成任何推荐或投资建议。投资者应审慎决策、独立承担风险。风险提示:交易差价合约时,平均有70%– 90%的散户投资者亏损,差价合约交易存在很高的亏损风险。
超买和超卖是什么意思? - 交易知识丨FxGoPlus
超买和超卖是什么意思? - 交易知识丨FxGoPlus
跳至内容普拉斯财经 - 汇集全球热点新闻,为投资交易者提供最有价值的证券、期货、外汇、大宗商品、贵金属、数字货币等金融财经信息。 Search Search 普拉斯财经实时行情黄金白银原油美元欧元英镑新闻资讯热点新闻经纪商新闻监管公告知识百科交易知识加密货币外汇股票期货基金期权技术分析常见问题交易经验入门视频经纪商活动通知赠金活动交易通知交易支持热门书籍 Menu普拉斯财经实时行情黄金白银原油美元欧元英镑新闻资讯热点新闻经纪商新闻监管公告知识百科交易知识加密货币外汇股票期货基金期权技术分析常见问题交易经验入门视频经纪商活动通知赠金活动交易通知交易支持热门书籍超买和超卖是什么意思?首页 » 交易知识 » 超买和超卖是什么意思? 作者: 交易员的261天 更新日期:2021-02-09 评分 “超买”和”超卖”描述的是短期股价的极端情况,表明股价在某一特定方向上走得太远。当一只股票被归类为市场超买时,意味着专家认为它的售价超过了它的实际价值。另一方面,超卖的股票是指分析师认为其交易价格低于其实际价值的股票。小贴士:超买和超卖的股票是指那些被分析师认为没有按其真实价值交易的股票。超买的股票可能会以高于其价值的价格出售,而超卖的股票可能比其当前的交易价格更有价值。多少才算超买和超卖?超买指的是价格在几天内急剧上升的百分比大于正常水平,或者价格连续几天向同一方向移动的数量越来越多。例如,股票可能是市场超买,因为它们在三天内跳涨了5%–比平时更多–或者因为它们连续六天收涨–也是不寻常的。超卖的意思正好相反。急剧下降或连续几天价格收跌。当一只股票超买时,意味着买盘将价格推得太高,预计会出现反应,称为价格回调。当股票超卖时,意味着卖盘将价格推得太低,预期会出现反应,称为价格反弹。为什么会有超买和超卖?投资者往往对消息反应过度,他们的买入或卖出会使价格向某一特定方向过度发展。更多的买家可能因为价格上涨而不断买入;更多的卖家可能因为价格下跌而不断卖出。到了某个时候,能量耗尽后,他们才意识到事情可能没那么坏,也没那么好,随之而来的是反方向的修正行动。例如,美国联邦储备委员会的一次降息,会引起几天的热情买盘;欧债危机的一系列悲观报道,会引起几天的大量卖盘。但随后投资者开始意识到,美联储的行动并没有解决所有问题,欧洲也没有分崩离析,因此价格从极端情况下撤退。超买和超卖的问题股票涨幅过大或跌幅过大,并不意味着股票仍然不能上涨或下跌。超卖和超买股票往往是反映某人对市场的看法,可能是准确的,也可能是不准确的。例如,在熊市中,股票往往在几波卖盘中下跌,然后暂时停顿后继续下跌。超卖不一定意味着下跌的结束,只是说可能会出现暂时的反弹,之后会恢复下跌。超买股和超卖股也不是精确的衡量标准。例如,经过五天不间断的推进,股票在一些市场观察者看来可能开始超买,但价格仍然继续推进几天,这将使它们更加市场超买或极度超买。 外汇中级知识, 外汇技术指标 Facebook Twitter LinkedIn Telegram Prev上一页原油期货的交易策略 下一页外汇交易中趋势线的局限性Next 经纪商活动 热门经纪商了解更多>> 热门标签外汇知识股票知识基金知识期货知识期权知识加密货币知识日本蜡烛图技术指标MT4监管机构热门文章美元黄金白银英镑欧元原油澳元日元加元 Menu外汇知识股票知识基金知识期货知识期权知识加密货币知识日本蜡烛图技术指标MT4监管机构热门文章美元黄金白银英镑欧元原油澳元日元加元热门文章 什么是投机交易?初学者指南 2022-03-20 什么是场外交易市场(OTC)? 2021-12-04 什么是金融衍生品?(Derivatives) 2021-12-03 什么是能量潮指标?丨OBV指标详解和实战用法 2021-05-03 如何通过做空股票赚钱? 2021-04-21 页岩油和石油的区别 2021-02-26 延伸阅读 相关基础知识 更多>> 什么是黑天鹅?丨Black Swan Theory 2023-12-04 什么是高频交易(High-Frequency Trading)? 2022-11-27 什么是交易台丨Trading Desk 2022-10-29 社区交易和复制交易的区别 2022-05-02 什么是外汇互换(掉期)? 2022-04-05 技术分析 更多>> 黄金价格预测:XAU/USD有向1990美元上升的空间,技术面看涨 2022-03-25 黄金价格预测:回撤至1922美元支撑位 2022-03-23 黄金价格分析:市场气氛不一,XAU/USD在1795美元处盘整 2021-12-23 黄金价格分析:尽管美联储态度鹰派,但XAU/USD继续上行 2021-12-16 英镑/美元在1.3250附近徘徊 关注英国和美国PMI、英国央行货币政策 2021-12-16 经纪商IC MarktesXMExnessIC MarktesXMExness客户支持赠金活动入门书籍赠金活动入门书籍关于我们站内地图隐私政策条款和条件站内地图隐私政策条款和条件© 2023 金融交易市场存在极大的不确定性和风险,投资者在开立账户时应仔细阅读券商及产品的法律文件,了解产品风险和收益特征(包括系统性风险和特定产品所特有的投资风险等)。投资者应根据自身资产状况、风险承受能力选择适合的产品。普拉斯财经提供的宣传材料仅供投资者参考,不构成任何推荐或投资建议。投资者应审慎决策、独立承担风险。风险提示:交易差价合约时,平均有70%– 90%的散户投资者亏损,差价合约交易存在很高的亏损风险。