本地缓存与分布式缓存

4,392 阅读4分钟

简介

在高并发场景下,数据库IO往往会成为服务性能瓶颈,而且高并发写入争用同一数据资源时很容易将数据库打挂掉。服务器编程中,通过引入缓存将数据的读写操作都放到内存中,一方面由于减少了数据库访问,解决了高并发场景下的数据库瓶颈问题,另一方面由于内存数据访问速度远远高于磁盘IO,可以大幅提高数据的访问速度和服务性能。

从广泛的角度来说,可以将驻留在“内存”中的数据都视作缓存,而根据缓存与应用进程是否属于同一实例,又可将缓存分成本地缓存和分布式缓存。

本地缓存:在服务进程的内存空间中缓存数据,数据读写都在同一个进程内。

分布式缓存:独立于服务进程部署,需要通过网络来完成分布式缓存数据传输。

本地缓存

优缺点

访问速度快,但无法进行大数据存储 本地缓存占用的是应用进程内的空间,相对于分布式缓存它不需要跨网络传输,性能会更好;但同时由于进程空间大小的限制,注定了本地缓存不支持大数据量的数据存储。 数据会随应用进程重启而丢失 实例重启时,应用进程内存空间本地缓存的数据会丢失,所以对于本地缓存数据使用时要注意不能随应用进程的重启而丢失。 可能存在数据不一致 本地缓存只支持被该应用进程访问,无法被其他应用进程访问。如果在应用进程的集群部署当中,当数据更新需要同步不同部署节点的本地缓存数据来保证数据一致性时,复杂度高且很容易出问题。

实现

ConcurrentHashMap或HashMap:由于HashMap不是线程安全的,而本地缓存需要被不同的服务端线程并发读写,因此一般会使用ConcurrentHashMap作为Java编程中的本地缓存实现。但如果缓存的是常量,也可以使用HashMap作为存储。 Cache工具:使用谷歌guava工具包中的Cache实现,除了缓存功能外,还具备定时失效、重新加载等特性。

适用场景

本地缓存一般适用于数据量较小且频率可见的访问场景尤其适用于缓存只读数据,如果数据在不同的实例机器上需要共享和保持一致,就需使用分布式缓存而非本地缓存来统一存储,所有实例都在分布式缓存中进行统一数据读取和管理。

分布式缓存

优缺点

支持大数据量存储,不受应用进程重启影响 分布式缓存是独立部署的进程,拥有自身独立的内存空间,不会受到应用服务进程重启的影响。分布式缓存支持以集群的方式扩展,因此可以进行大数据量的缓存。 数据集中存储,保证数据一致 应用进程实例部署时,每一个部署节点都是从分布式缓存中进行数据存取,不存在像本地缓存那样数据更新时多实例数据不一致问题。 数据读写分离,高性能、高可用 分布式缓存可以实现读写分离,可以解决高并发场景下中的数据读写性能问题。由于多个缓存节点冗余存储数据,能够提高缓存数据的可用性,避免某个缓存节点宕机导致的数据不可用问题。 数据需要跨网络传输,性能低于本地缓存 分布式缓存独立于服务应用进程,需要通过网络进行数据传输,相对于本地缓存进程内部的数据读取操作,性能会较低。

实现

目前一般是使用Redis作为分布式缓存,能够存储更丰富的k-v数据结构,而且由于Redis是单线程的,不存在并发数据读写的线程安全问题,能够保证数据读写操作的顺序性。

适用场景

在高并发场景或对于较大其不可预见的用户访问时,采用分布式缓存,如在某些短时热门活动中可以将Redis当做数据库来用。