互联网高速发展的这个时代,为了提高用户访问请求的响应时间,缓存的使用已经成为很多大型系统或者电商网站使用的一个关键技术,合理地设计缓存直接关系到了一个系统或者网站的并发访问能力和用户体验。缓存按照存放地点的不同,可以分为用户端缓存和服务端缓存,如图1-7-1所示。
图1-7-1
缓存调优的关键点说明如下:
(1)如何让缓存的命中率更高?
(2)如何注意防止缓存穿透?
(3)如何控制好缓存的失效时间?
(4)如何做好缓存的监控分析?比如慢日志(Slow Log)分析、连接数监控、内存使用监控等。
(5)如何防止缓存雪崩?缓存雪崩指的是服务器在出现断电等极端异常情况后,缓存中的数据全部丢失,导致大量的请求全部需要从数据库中直接获取数据,从而使数据库压力过大造成数据库崩溃。防止缓存雪崩需要注意:
● 要处理好缓存数据全部丢失后,如何能快速把数据重新加载到缓存中。
● 缓存数据的分布式冗余备份,当出现数据丢失时,可以迅速切换使用备份数据。
同步指的是系统收到一个请求后,在该请求没有处理完成时,就一直不返回响应结果,直到处理完成后才返回响应结果,如图1-7-2所示。
图1-7-2
与同步相比,异步指的是系统收到一个请求后,立即把请求接收成功返回给请求调用方,在请求处理完成后,再异步推送处理结果给调用方,或者请求调用方间隔一定时间之后再重新来获取请求结果,如图1-7-3所示。
图1-7-3
同步转异步主要解决同步请求时的阻塞等待问题。一直处于阻塞等待的请求,往往会造成连接不能快速释放,从而导致在高并发处理时连接数不够用,通过队列异步接收请求后,请求处理方再进行分布式的并行处理,从而达到处理能力扩展,并且网络连接也可以快速释放。
拆分指的是将系统中的复杂业务调用拆分为多个简单的调用,如图1-7-4所示,一般遵循的原则如下:
● 对于高并发的业务请求调用都单独拆分为单个的子系统应用。
● 对于并发访问量接近的业务,可以按照产品业务进行拆分,相同的产品业务都归类到一个新的子系统中。
图1-7-4
系统拆分带来的好处就是高并发的业务不会对低并发业务的性能造成影响,而且系统在硬件扩展时,也可以有针对性地进行扩展,避免资源的浪费。
任务分解与并行计算指的是将一个任务拆分为多个子任务,然后将多个子任务并行进行计算处理,最后只需要再将并行计算的结果合并在一起返回即可。这样处理的目的是通过并行计算的方式来增加处理性能,如图1-7-5所示。
图1-7-5
另外,对于包含多个处理步骤的串行任务,也可以尽量按照如图1-7-6所示的方式转换为并行计算处理。
图1-7-6
索引指应用程序在查询时,尽量使用数据库索引查询,数据库表在创建时也尽量对查询条件的字段建立合适的索引。这里强调一定是合适的索引,如果索引建立不合适,不仅对查询效率没有任何的帮助,反而会使数据库表在插入数据时变得更慢,因为一旦建立了索引后,数据在插入时,索引也会自动更新,这样就加大了数据库数据插入时的资源消耗。比如,数据库表中有一个字段为status,而status的取值只有0、1、2三个值,这时候如果对status建立索引,对查询效率没有任何帮助,因为status字段的值只有0、1、2这三个值,取值范围太少,建立索引后根据status去检索时,需要扫描的数据量还是非常大的。
正确使用索引可以很好地提高查询效率,但是如果一个表的数据量非常庞大,比如达到了亿万级别,此时索引查询很慢,并且新数据插入时也很慢,此时就需要对数据进行分表或者分库。分库一般指的是一个数据库的存储量已经很大了,查询和插入时I/O消耗非常大,此时就需要将数据库拆分成2个库,以减轻读写时I/O的压力,如图1-7-7所示。
图1-7-7
常见的分库分表方式如下:
● 按照冷热数据分离的方式:一般将使用频率较高的数据称为热数据,查询频率较低或者几乎不被查询的数据称之为冷数据,冷热数据分离后,热数据单独存储,这样数据量就会下降下来,查询的性能自然也就提升了,而且还可以更方便地单独针对热数据进行I/O性能调优。
● 按照时间维度的方式:比如可以按照实时数据和历史数据分库分表,也可以按照年份、月份等时间区间进行分库分表,目的是尽可能地减少每个库表中的数据量。
● 按照一定的算法计算的方式:此种方式一般适用于数据都是热数据的情况,比如数据无法做冷热分离,所有的数据都经常被查询到,而且数据量又非常大。此时就可以根据数据中的某个字段执行算法(注意:这个字段一般是数据查询时的检索条件字段),使得数据插入后能均匀地落到不同的分表中去(由算法决定每条数据是进入哪个分表),查询时再根据查询条件字段执行同样的算法,就可以快速定位到是需要到哪个分表中去进行数据查询。
数据分库分表后,带来的另一个好处就是:如果在单次查询时需要查询多个分表,那么此时就可以通过多线程并行的方式去查询每个分表,最后合并每个分表的查询结果即可,这样也可以使得查询的效率更高。