# note **Repository Path**: wuxi_zero/note ## Basic Information - **Project Name**: note - **Description**: 业务解决方案 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-09-17 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # note #### 介绍 业务解决方案 #### 说明 自己写一点点日志,总结一下自己遇到的坑点。 #### "坑",需要 "填" **缓存击穿** 是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。举个例子:也就是大量的请求同时去查询同一个缓存,但是这个缓存又刚好过期或者被删除了,那么所有的请求全部都会打到数据库上,导致严重的性能问题。对于这个问题包括如何解决缓存穿透。 具体解决方法:这里先简单说下解决思路,其实也就是上锁。当一个线程需要去访问这个缓存的时候,如果发现缓存为空,则需要先去竞争一个锁,如果成功则进行正常的数据库读取和写入缓存这一操作,然后再释放锁,否则就等待一段时间之后,重新尝试读取缓存,如果还没有数据就继续去竞争锁。这个是单机场景,如果有多台机器同时去访问同一个缓存项该怎么办呢?如果机器数不是很多的话,这种情况一般来说也不会成为一个问题,不过这里有个优化点,就是从数据库读取到数据之后,再对缓存做一次判断,如果缓存中已经存在数据,就不需要再写一遍缓存了。但是如果机器数也很多的话,那么就得考虑上分布式锁了。此方案的问题是显而易见的,加锁尤其是加分布式锁会对系统性能有重大影响,而且分布式锁的实现非常考验开发者的经验和实力,在高并发场景下这一点显得尤为重要,因此我建议各位,不到万不得已的情况下,不要盲目上分布式锁。 可以借鉴这个: [输入链接说明](https://blog.csdn.net/babyff00/article/details/52658698) **缓存穿透** 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空( _这里是与缓存击穿的重要区别_ ),则不放进缓存。注意当从数据库查询出来的值是空值时,会有大量的请求会去查询数据库,导致缓存穿透了。 既然如此解决方法可以是 将空值也放入缓存中,设置一个比较短的时间来处理,这种好处显而易见,但是会产生明显的数据不一致的问题,所以设置缓存超时时间很重要。 我最后的解决方法是:将当缓存又刚好过期或者被删除了的时候,让分布式锁介入,利用分布式锁来抢资源,始终让一个线程去从数据库中获取支援,一定要再次查一下缓存,没有的情况下,在查询数据库,在写回缓存中。 **缓存雪崩** 缓存雪崩,是指在某一个时间段,缓存集中过期失效。 举个例子: 电商项目的时候,一般我们都会将类目信息和热门商品,banner放到缓存中。相对于热门商品这一块是最容易出现缓存雪崩的,很有可能热门商品处理不当时,会同一时间缓存集中过期。 我们最后解决的方式是,设置一个随机因子,加上为每一个热门商品设置一个有效时间,及开始结束时间(这个时间不是说商品上下架时间,而是这个商品是热门商品的时间),同时也可以根据商品类目进行加上基本缓存时间,这样基本达避免缓存雪崩了。 当然缓存雪崩出现的场景不只有这一点,还有可能比较严重:比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么这个时候数据库一般能顶住压力,无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮,你可以想象一下双11的时候阿里,热门商品秒杀的场景,一秒的数据qps多少,数据库压力有多大。