这篇想聊的话题是:分布式多级缓存架构的终章,如何解决大流量、高并发这样的业务场景,取决于你能不能成为这个领域金字塔上层的高手? 能不能把这个问题思考清楚决定了你的成长速度。
很多人在一个行业5年、10年,依然未达到这个行业的中层甚至还停留在底层,因为他们从来不关心这样的话题。作为砥砺前行的践行者,我觉得有必要给大家来分享一下。
开篇
服务端缓存是整个缓存体系中的重头戏,从开始的网站架构演进中,想必你已看到服务端缓存在系统性能的重要性。
但数据库确是整个系统中的“半吊子|慢性子”,有时数据库调优却能够以小搏大,在不改变架构和代码逻辑的前提下,缓存参数的调整往往是条捷径。
在系统开发的过程中,可直接在平台侧使用缓存框架,当缓存框架无法满足系统对性能的要求时,就需要在应用层自主开发应用级缓存。
缓存常用的就是Redis这东西,那到底什么是平台级、应用级缓存呢?
后面给大家揭晓。但有一点可表明,平台级就是你所选择什么开发语言来实现缓存,而应用级缓存,则是通过应用程序来达到目的。
01数据库缓存
为何说数据库是“慢性子”呢? 对现在喜欢快的你来说,慢是解决不了问题的。就好像总感觉感觉妹子回复慢
因为数据库属于IO密集型应用,主要负责数据的管理及存储。数据一多查询本身就有可能变慢, 这也是为啥数据上得了台面时,查询爱用索引提速的原因。当然数据库自身也有“缓存”来解决这个问题。
数据多了查询不应该都慢吗? 小白说吒吒辉你不懂额
。。。这个,你说的也不全是,还得分情况。例如:数据有上亿行
原因:
- 因为简单的SQL的结果不会特别多。你请求也不大,磁盘跟的上
- 并发总量超过磁盘吞吐上限,是谁都没招
就算你们不喜欢吒吒辉,我也要奋笔疾书
数据库缓存是自身一类特殊的缓存机制。大多数数据库不需要配置就可以快速运行,但并没有为特定的需求进行优化。在数据库调优的时候,缓存优化你可以考虑下。
以MySQL为例,MySQL中使用了查询缓冲机制,将SELECT语句和查询结果存放在缓冲区中,以键值对的形式存储。以后对于同样的SELECT语句,将直接从缓冲区中读取结果,以节省查询时间,提高了SQL查询的效率。
1.1.MySQL查询缓存
Query cache作用于整个MySQL实例,主要用于缓存MySQL中的ResultSet,也就是一条SQL语句执行的结果集,所以它只针对select语句。
当打开 Query Cache 功能,MySQL在接收到一条select语句的请求后,如果该语句满足Query Cache的条件,MySQL会直接根据预先设定好的HASH算法将接收到的select语句以字符串方式进行 hash,然后到Query Cache中直接查找是否已经缓存。
如果结果集已经在缓存中,该select请求就会直接将数据返回,从而省略后面所有的步骤(如SQL语句的解析,优化器优化以及向存储引擎请求数据等),从而极大地提高了性能。
当然,若数据变化非常频繁的情况下,使用Query Cache可能会得不偿失。
这是为啥,用它不是提速吗?咋还得不偿失
因为MySQL只要涉及到数据更改,就会重新维护缓存。
- 如果SQL请求量比较大,你在维护的时候,就透过缓存走磁盘检索。这样数据库的压力肯定大。
- 重建缓存数据,它需要mysql后台线程来工作。也会增加数据库的负载。
所以在MySQL8已经取消了它。 故一般在读多写少,数据不怎么变化的场景可用它,例如:博客
Query Cache使用需要多个参数配合,其中最为关键的是query_cache_size和query_cache_type, 前者用于设置缓存ResultSet的内存大小,后者设置在何种场景下使用Query Cache。
这样可以通过计算Query Cache的命中率来进行调整缓存大小。
1.2.检验Query Cache的合理性
检查Query Cache设置的是否合理,可以通过在MySQL控制台执行以下命令观察:
- SHOW VARIABLES LIKE ‘%query_cache%’;
- SHOW STATUS LIKE ‘Qcache%’; 通过检查以下几个参数可以知道query_cache_size设置得是否合理:
- Qcache_inserts:表示Cache多少次未命中然后插入到缓存
- Qcache_hits: 表示命中多少次,它可反映出缓存的使用效果。
如果Qcache_hits的值非常大,则表明查询缓冲使用非常频繁,如果该值较小反而会影响效率,那么可以考虑不用查询缓存;
- Qcache_lowmem_prunes: 表示多少条Query因为内存不足而被清除出Query_Cache。
如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况,因增加缓存容量。
- Qcache_free_blocks: 表示缓存区的碎片
Qcache_free_blocks值非常大,则表明缓存区中的碎片很多,可能需要寻找合适的机会进行整理。
通过 Qcache_hits 和 Qcache_inserts 两个参数可以算出Query Cache的命中率:
通过 Qcache_lowmem_prunes 和 Qcache_free_memory 相互结合&