性能优化,缓存为王,所以开始先介绍一下缓存。缓存在我们的架构设计中无处不在,常规请求是浏览器发起请求,请求服务端服务,服务端服务再查询数据库中的数据,每次读取数据都至少需要两次网络 I/O,性能会差一些,我们可以在整个流程中增加缓存来提升性能。首先是浏览器测,可以通过 Expires、Cache-Control、Last-Modified、Etag 等相关字段来控制浏览器是否使用本地缓存。
其次我们可以在服务端服务使用本地缓存或者一些中间件来缓存数据,例如 Redis。Redis 之所以这么快,主要因为数据存储在内存中,不需要读取磁盘,因为内存读取速度通常是磁盘的数百倍甚至更多;
然后在数据库侧,通常使用的是 MySQL,MySQL 的数据存储到磁盘上,但是 MySQL 为了提升读写性能,会利用 bufferpool 缓存数据页。MySQL 读取时会按照页的粒度将数据页读取到 bufferpool 中,bufferpool 中的数据页使用 LRU 算法淘汰长期没有用到的页面,缓存最近访问的数据页。
此外小到 CPU 的 l1、l2、l3 级 cache,大到浏览器缓存都是为了提高性能,缓存也是进行服务性能优化的重要手段,使用缓存时需要考虑以下几点。
使用缓存时可以使用 Redis 或者机器内存来缓存数据,使用 Redis 的好处可以保证不同机器读取数据的一致性,但是读取 Redis 会增加一次 I/O,使用内存缓存数据时可能会出现读取数据不一致,但是读取性能好。例如文章的阅读数数据,如果使用机器内存作为缓存,容易出现不同机器上缓存数据的不一致,用户不同刷次会请求到不同服务端机器,读取的阅读数不一致,可能会出现阅读数变小的情况,用户体验不好。对于阅读数这种经常变更的数据比较适合使用 Redis 来统一缓存。
也可以将两者结合提升服务的性能,例如在内容池服务,利用 Redis 跟机器内存缓存热点文章详情,优先读取机器内存中的数据,数据不存在的时候会读取 Redis 中的缓存数据,当 Redis 中的数据也不存在的时候,会读取下游持久化存储中的全量数据。其中内存级缓存过期时间为15s,在数据变更的时候不保证数据一致性,通过数据自然过期来保证最终一致性。Redis 中缓存数据需要保证与持久化存储中数据一致性,如何保证一致性在后续讲解。可以根据自己的业务场景可以选择合适的缓存方案。