当前位置: 首页 > 科技观察

分库分表实战:激流勇进-千万级数据优化加缓存

时间:2023-03-16 21:41:57 科技观察

前言经过前面的索引和sql优化,现在查询速度直线上升,接下来我们继续回归日常需求的开发。3个月后,order表的数据已经达到了5000万条,但是一次SQL查询的时间基本稳定在300ms以下。但是有一个星期一,领导开完周会直接来找你,直接说:“哦,周会上DBA来找我,说我们订单组的sql偶尔会超过2s,DBA现在要求优化.平均时间需要优化到300ms以内。不过,在优化之前,你必须先检查为什么sql的查询时间偶尔会突然增加。”Troubleshooting然后我们接手了这个任务,然后根据DBA给的慢sql,去查看这个sql的相关日志,然后结合监控,最后发现这个sql平时是稳定的,但是在期间高峰期,这条sql偶尔会超过2s,此时我们查看订单数据库所在物理机的资源占用情况,发现在高峰期,这台物理机的资源占用率很高,而且CPU和内存占用都很高,这个基本就可以确定原因了,说白了就是高峰期一到,大量的请求去MySQL查询数据,这个时候就会有大量的对数据库的密集请求,会导致数据库所在机器的CPU和内存使用率飙升,最终导致MySQL查询效率急剧下降。领导了解情况后表示:“其实,慢曲数据库ery不一定是MySQL数据量大造成的。比如现在的情况,很明显大量的请求集中请求到数据库,导致数据库的负载增加,大大降低了数据库的查询效率。这个时候,其实我们需要在MySQL前面加一层缓存,进行流量调峰,保证MySQL能够稳定的完成查询。”经过领导的拨通,我们才恍然大悟原来是这么回事。说白了,这个时候我们可以加一些缓存,给MySQL削流量峰。添加缓存后的运行过程大致是这样的:也就是说,按照标准的请求流程,用户的请求会命中数据库,但是添加缓存后就不是这个过程了。此时请求可以直接从缓存中获取数据并返回,这样会减少后续流程的处理,比如查询数据库,从而有效降低数据库的负载。说白了,就是利用缓存来承担大部分的查询请求,达到流量调峰的效果,从而降低数据库的负载,保证MySQL能够稳定高效的完成查询,从而使问题可以解决高峰期My??SQL查询时间突然增加的问题。完美解决。虽然缓存非常好用,但是在使用缓存的过程中,还是要注意缓存的命中率。命中率=正确返回结果数/缓存请求数。命中率是衡量缓存有效性的重要指标。命中率越高,缓存使用率越高。除了关注缓存命中率,我们还需要了解缓存清空策略,比如先进先出策略FIFO(先进先出),最不频繁使用策略LFU(不太频繁使用)和最近最少使用的策略LRU(leastrecentlyused)。如何提高缓存命中率刚才我们说了,命中率是衡量缓存有效性的一个重要指标,那么如何才能提高缓存命中率呢?其实要想提高缓存命中率,需要考虑的点有很多。大概有以下几点:1、选择合适的业务场景。首先,缓存适用于读多写少的场景。最适合高频访问的场景,因为访问频率越高,命中率越高。2、合理设置缓存容量如果缓存容量过小,会触发Redis内存淘汰机制,导致部分缓存key被删除,从而降低缓存命中率。因此,合理设置缓存容量是非常必要的。3、控制缓存粒度缓存粒度越小,缓存命中率越高,因为单个key的数据单元越小,缓存越不容易被改变。4、灵活设置缓存key的过期时间。这里说的是尽量避免缓存同时过期。如果缓存同时过期,如果此时有多个查询请求,那么这些请求都会被发送到数据库。这种情况称为缓存崩溃,它会给数据库带来很大的压力。5.避免缓存穿透我们先来了解一下缓存命中率。比如当一个请求来查询一条数据时,如果在缓存中没有找到这条数据,这时候我们就可以说缓存没有命中。如果大量的查询请求在缓存中,缓存中能查到的数据很少,我们可以说缓存命中率很低。当缓存命中率很低的时候,因为在缓存中找不到数据,此时请求会命中数据,去数据库查询数据。如果在数据库中仍然找不到数据,则说明请求已经穿透了缓存。.一旦缓存被穿透,当有大量的请求进来时,如果不能命中缓存,大量的请求就会转向数据库,数据库处理请求的能力就有限了。这时候数据库可能会因为请求数突然增加而增加。压力过高和停机时间。一旦数据库宕机,极有可能演变成缓存雪崩,导致整个系统大面积瘫痪。这非常可怕。因此,我们需要提前做好预案,避免缓存被穿透。比如当一个查询请求来的时候,如果缓存中没有数据,那么数据库中仍然没有数据。这时候,我们可以在缓存中,为这个查询请求设置一个空对象,然后请求带着这个空对象返回。下次同样的查询请求回来时,可以直接命中缓存中的空对象,不需要再去数据库请求。这样即使有大量的请求进来,缓存的命中率也可以很高,缓存穿透的问题也解决了。6、做好缓存预热一般来说,第一次查询请求都会发送到数据库,所以我们可以提前将数据库数据加载到缓存中,也就是缓存预热,所以第一次查询request也可以直接去缓存。以上几点做好了,那么缓存命中率自然会提高。好了,废话不多说,下面我们一起来个缓存实战,体验下添加缓存后的查询效果。缓存实战场景介绍:历史订单查询不会改变已完成订单的状态,所以再次进行历史订单查询时,查询结果会缓存在redis中,过期时间设置为一小时,所以之前缓存过期,用户再次查询历史订单时,会直接请求redis,减轻数据库压力。不加缓存的查询时间。Redis优化思路在查询历史订单时,会先检查redis中是否有缓存。如果有,则直接返回redis中的数据。如果没有,它会查询MySQL,然后返回查询数据,并将查询结果设置到缓存中,以便下一次查询可以到缓存中。缓存key生成规则用户id+页码+页码生成rediskey缓存核心代码缓存优化效果添加缓存后可以看到第二次请求使用了redis缓存查询,效率有了很大的提升。然后,你加了缓存之后,发现效果真的很好。大量请求命中了缓存,数据库的资源占用率也保持在合理范围内,SQL查询时间也稳定在300ms以下。