1.什么是热点问题

  1. 点表示我们在系统的业务路径上有一个地方存在性能的瓶颈,比如数据库,件系统,网络,甚至于内存等,这个点一般有io,锁等问题构成。
  2. 热表示其被访问的频率很高。

就是说一个被访问频率很高的io或锁自然而然就造成了我们系统业务路径上的性能瓶颈。

这样的热点问题会影响系统稳定性和性能瓶颈,例如支付系统中的热点账户进出款,电商系统中的热点商品参与秒杀,金融系统中的热点理财产品抢购等,都会因为热点问题而影响系统性能。

2.热点问题有哪些

其次我们需要弄清楚我们的热点问题是属于读热点问题还是写热点问题,两种热点问题的处理方案完全不一样,比如我们对一个热门的秒杀商品详情页的访问就属于是读热点问题,对一个秒杀商品的库存抢操作就是一个写热点问题。虽然分离了读热点问题和写热点问题,但是往往在读热点问题时也需要处理写热点问题的解决方案,比如我对一个热门的秒杀商品详情的读热点问题使用了缓存解决方案,但因为商家对商品做了更新价格的东西时立马需要对写热点而造成的缓存脏数据做清理的操作,因此就变成了一个读写混合的热点问题。

3.如何解决—读热点

3.1.读热点—mysql优化

一般我们做系统之出使用数据库,直接对用户的请求做sql的select操作,那对于此类热点问题我们首先想到的是需要优化数据库的读操作,我们对应的查询是否走了索引,走的是否是唯一索引甚至于主健效果最佳,优化了sql性能后,可以借助于mysql innodb的buffer做一些文章,在数据库层面就提供足够的缓冲区,加速对应的性能,实验证明,只要走的是主健或唯一索引,innodb缓冲区足够大的情况下,进行mysql的主从分离和集群化部署,mysql抗上亿的数据也是没有任何问题的。

3.2.读热点—redis缓存

真正出问题的不是点而是热,由于访问频次太高,mysql的cpu扛不住了,这个时候我们考虑到的是将对应的读热点放到例如redis的缓存中用于卸载压力,由于redis4版本以后就可以支持cluster的集群模式,其借助分片集群的效果理论上可以扩展到1000个左右的节点,如此一来我们可以依靠缓存去解决读热点问题,一旦商家变更了读热点的数据,我们可以在业务应用中使用提交后异步清除缓存的方式将redis的数据清除,这样在下一次的请求中可以依靠数据库的回源更新redis数据。

3.3.读热点—redis分片

那既然我们讨论的是读热点问题,就和redis的水平扩展能力无关,因为是个热点数据,则必定会被分片路由到一个redis节点上,当热度大到连redis节点都无法承受的时候,我们可以考虑将原本的一个热点做三分拷贝,比如我们的热点key叫"item_1",我们可以考虑随机的生成三个key分别叫"item_1_key_1",“item_1_key_2”,“item_1_key_3”,对应的value都是这个商品value本身,这样当用户请求过来后可以随机的生成1-3的数字以决定这次请求我们访问哪个key,这样人为的将一个热点的tps降到了原来的三分之一,以空间换时间。

3.4.读热点—本地缓存

另外我们还可以考虑在应用服务器上做本地的cache内存,由于应用服务器本身容量有限,内存中不能放太多数据,也不能存很长时间,我们推荐使用google研发的guava cache包,提供给我们很好的lru cache队列的能力,一般本地的缓存不要设置太长时间,一是出于内存容量考虑,二是出于清理本地缓存不会同步清理redis,需要我们的每台应用服务感知到数据的变更,一般可以用广播型的mq消息解决,推荐rocketmq 的广播型消息,使得订阅对应商品信息变更的所有应用服务器都有机会清理本地缓存。

4.如何解决—写热点

写热点问题比读热点问题更具挑战性,为什么写热点问题处理起来比读热点更难的,因为读操作可以并发,我可以做到无锁操作的解决,但是写操作不行啊,从来没有说写操作可以真正意义上并发的,都需要加锁以防并发的方式写入数据库或者文件存储中,那我们怎么优化呢?

4.1.写热点—mysql优化

首先我们还是一样先解决点的问题再解决热的问题,针对点我们一般写操作会选用数据库之类的文件存储设备,mysql对数据存储有比较好的优化,其基于写事务日志,也就是redo,undo log,然后等系统空闲的时候将数据刷入磁盘的,由于事务日志的存在,即使系统挂了再启动的时候也可以根据redo log恢复数据,那为啥写log比写数据快那么多的,因为写日志是一个顺序追加写的方式,磁盘的磁头不需要随机的移动寻找写入点,只要顺序的写下去即可,配合ssd固态硬盘,整个写入性能可以做到很高。

4.2.写热点—redis缓存

但是磁盘操作终究是磁盘操作,我们试着可以将写入的目标点移到缓存中,比如将秒杀的库存移到redis中,这么一来,点的瓶颈的天花板瞬间就提升到了很多倍,但是一旦将数据落到没有办法保证磁盘落地能力的缓存中就需要去靠一些机制去保证可靠性,不至于在缓存丢失的情况下造成超卖等灾难,我们可以依靠rocketmq异步事务型的消息保持redis和数据库之间的数据同步,解决缓存异常情况下我们可以依靠数据库恢复对应的数据。

4.3.写热点—缓冲入账

那异步化是解决问题的最终方案吗?显然不是,异步化只是将对应的写热点问题延迟到后面去解决,不至于卡住前端的用户体验,但是一旦这个点多了起来,后端服务器和磁盘的压力还在,那我们还有什么方法去解决呢?我们都知道写入操作之所以在热点问题的情况下那么难解决,是因为写同一份数据的操作不能并发,必须得要通过竞争锁的机制去竞争以获得线程的写入权限,我们突然可以想到,锁这个东西本身就是一个耗性能的来源,设想两个人要抢同一个食堂阿姨拿出来的饭,你争我抢,我抢到了吃晚了再给后面的其他人在争,在竞争的过程中所有人,所有线程的资源都被白白消耗掉了,最终还是只有一个人在那个时刻可以吃到饭。那针对这种情况我们是否可以有更好的解决方案呢?还是考虑抢饭吃这个场景,在现实生活中最高效的方式是什么,就是排队,大家都不要竞争,按照先到先得的方式将所有对热点的写入访问操作队列化,使用单线程的方式去队列中取得下一个写入操作,然后写完后再取下一个,这样可以避免掉写锁竞争的无谓cpu和内存消耗,也可以使用单线程的方式解决,没有cpu调度切换的开销。就是我们常说的在无锁的情况下,单线程排队比多线程更高效,这种解决写热点的方式叫做"缓冲入账"。

5.总结

以上大致讲解了一下我们在应对热点问题上的一些解决思路,当然还有许多方式去解决这样的一些热点问题,每种方式都有利有弊,我们需要在实际的业务场景中灵活去分析取舍。无论是读热点还是写热点问题的解决方案,如果流量超过我的系统能力的上限,不好意思,拒绝服务,将内部的等待队列先消化完再来服务您,保证我们可以高效的做完这单再接下单。

解决高并发项目下的热点问题相关推荐

  1. 读数据库遇到空就进行不下去_如何解决高并发场景下缓存+数据库双写不一致问题?...

    推荐阅读: 一只Tom猫:手撕分布式技术:限流.通讯.缓存,全部一锅端走送给你!​zhuanlan.zhihu.com 一只Tom猫:MySQL复习:20道常见面试题(含答案)+21条MySQL性能调 ...

  2. 高并发场景下对热点数据的处理

    什么是热点数据 设想如下场景: 1.有一条现金账号(大商户在mysql上的一条记录),同时有数十万人在往上面转账,账务数据是必须同步持久化的,这种情况下很难做到所有请求同步update这条记录. 2. ...

  3. 高并发环境下热点数据访问的最佳实践。

    前言: 正常情况下,我们为了缓解数据库读写压力,我们会在应用程序中增加一层缓存,但在高并发场景下,热点数据的访问依旧会对缓存造成压力,通过横向扩容也并不能解决本质问题.那么,有没有一种热点预测,精准匹 ...

  4. 高并发场景下的缓存 + 数据库双写不一致问题分析与解决方案设计

    在实际业务中,经常碰见数据库和缓存中数据不一致的问题,缓存作为抵挡前端访问洪峰的工具,用的好的话可以大大减轻服务端压力,但是在一些场景下,如果没有控制好很容易造成数据库和缓存的数据不一致性,尤其是在并 ...

  5. 在高并发情况下如何解决用户超领优惠券问题

    在高并发情况下如何解决单用户超领优惠券问题 一. 场景描述 在近期的项目里面有一个功能是领取优惠券的功能,每一个优惠券一共发行多少张,每个用户可以领取多少张: 如:A优惠券一共发行120张,每一个用户 ...

  6. 面试题:JavaEE项目中,你准备如何解决高并发问题?比如1000万人同时登录。作者——DengJun

    面试中遇到了这样的问题,JavaEE项目中,你准备如何解决高并发问题?比如1000万人同时登录. 1 .从最基础的地方做起,优化我们写的代码,减少必要的资源浪费.    a.避免频繁的使用new对象, ...

  7. java 高并发商城库存订单处理,下单减库存,如何解决高并发减库存问题

    下单减库存,如何解决高并发减库存问题 1. 减库存 一般下单减库存的流程大概是这样的: 1.查询商品库存.这里直接查的Redis中的库存. 2.Redis中的库存减1.这里用到的Redis命令是:in ...

  8. 并发经验八年架构师:带你轻松解决缓存在高并发场景下的问题

    缓存一致性问题 当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象.这就比较依赖缓存的过期和更新策略.一般会在数据发生更改 ...

  9. Redis高并发场景下秒杀超卖解决

    目录 1 什么是秒杀 2 为什么要防止超卖 3 单体架构常规秒杀 3.1 常规减库存代码 3.2 模拟高并发 3.3 超卖现象 3.4 分析原因 4 简单实现悲观乐观锁解决单体架构超卖 4.1 悲观锁 ...

最新文章

  1. 2019年互联网趋势报告
  2. vue 实现动态增加输入框_vue实现一个6个输入框的验证码输入组件
  3. python编写一个登陆验证程序_python项目实战:实现验证码登录网址实例
  4. Dumb Bones UVA - 10529(概率dp)
  5. Linux之环境变量
  6. MySQL优化建议汇总~~~
  7. 13.4. 临时表是否需要建索引
  8. All Friends 极大团
  9. mysql 出现 “1067 - Invalid default value for ‘UPDATE_TIME‘ “ 错误提示的解决办法
  10. python爬虫之喜马拉雅非vip音频下载
  11. 麦子学院3天带你学会Apple Watch开发
  12. svn合并分支到主干
  13. 模拟电子技术基础(一)
  14. 正交试验minitab
  15. sort目标跟踪算法
  16. ps如何保存透明图片
  17. java实现给图片添加水印
  18. SQL在执行JOIN ON时,到底发生了什么?
  19. 蓝桥杯总结及经验教训
  20. 助力2021杭州市网络安全宣传周 | 世平信息精彩活动合集

热门文章

  1. 网件R7800刷OpenWrt固件单臂路由设置经历
  2. 03 数学软件与建模---微分方程建模
  3. 全志h2参数_全志h3芯片性能及参数评测
  4. 【xmind 2021-2022,文件丢失-软件异常-历史版本找回】
  5. 7-52 输出字符画:HAUT
  6. 网页认不出USBKEY
  7. 李宗盛——给自己的歌,两个版本吉他谱
  8. python输出宽度是什么意思_Python输出长度
  9. 金叉走势图解上半年暴跌行情,如何证明macd金叉死叉模型确实有用?
  10. matlab利用magnify作图