构建高性能服务器 -- 缓存篇

2018-09-17 11:55:17 浏览数 (1)

引子


说到缓存,相信大家都不陌生。缓存的目的都在于避免重复的慢速计算,比如数据库访问。相对于慢速计算,缓存将会大大提高数据存取的速率,当然同时将会缩短用户每次请求处理的时间,从而提升服务器单位时间内的请求处理数,即吞吐率。

操作系统中的缓存


事实上,我们使用的操作系统中都存在着大量的缓存机制,比如文件系统存在内核缓冲区。它位于物理内存的内核地址空间,除了使用O_DIRECT标记打开的文件以外,所有对磁盘文件的读写操作都要经过它,所以它相当于磁盘的缓存区域。

这块内核缓冲区也称为页高速缓存,实际上它包括以下两部分组成:

  • 读缓存区
  • 写缓存区

读缓存区保存着最近从磁盘上读取的数据,当下次读取相同数据时,可以直接从读缓存区直接读取数据,避免了从磁盘上进行慢速操作。

写缓存区则保存着将要写入磁盘的数据,从而避免用户进程直接进行磁盘数据的写入而产生慢速操作等待。

所以无论是读缓存区还是写缓存区,都有效避免用户进程直接进行慢速操作,即直接与磁盘进行数据交互 ---- 读或者写。

服务器中的缓存


与操作系统中的缓存类似,我们构建高性能服务器时,也可以在服务器的业务逻辑层与数据层(数据一般存入数据库进行持久化)之间再加设一层缓存层。当然,缓存层的作用也就是避免业务逻辑层与数据层直接交互,从而产生慢速操作,进而影响到服务器的性能。

当业务逻辑层需要读取数据层的相关数据时,向缓存层请求相应数据,若数据存在于缓存层,则直接从缓存层读取,若不存在,则向后端数据层读取,并同时向缓存层保存一份。当下次请求相同数据时,则无需向数据层请求,因为缓存层中已有相应数据。

当业务逻辑层需要向数据层写入数据时,首先向缓存层请求数据写入,并快速响应写入成功,而缓存层再异步向数据层真正写入数据。如此做法可以减少用户请求等待时间,提高服务器并发性能。

分步式缓存系统


开源社区已有非常成熟的分布式缓存系统,比如说memcached, redis等。它们都是属于NoSQL范畴,都是以Key-Value形式进行存储的。

我们以memcached为例。

首先,memcached高效的最大原因就是其基于Key的Hash算法来存储数据结构,并且使用了非常高效的内存分配器(事先向操作系统请求了大片内存,再进行自我管理,避免大量内存申请与释放操作),所以使数据项的查询时间复杂度达到O(1)。

其次,memcached采用libevent作为其底层的网络事件库。而libevent又是业界较好的同类型开源库,所以从底层I/O网络模型上保障其可以进行高并发数据存取操作。

再次,memcached是一种分步式缓存系统,所以在理论上可以无限扩容,即扩展服务器数量,提高服务器集群并发处理能力。而且,它采用一致性Hash方法,从而减少因缓存服务器扩容或者下线造成的数据缓存失效问题。

BTW,memcached采用LRU(Least Recently Used)及时淘汰非热点数据,从而保障所缓存数据均为热点数据,最大效率使用机器内存。

0 人点赞