谷粒商城实战笔记-151-缓存-缓存使用-本地缓存与分布式缓存

文章目录

前面的课程通过压测发现了很多问题,并进行了多次优化,包括一下方案:

  • 动静分离,把静态资源存储在nginx,缩短资源请求链路
  • 开启thymeleaf缓存
  • 调整jvm参数,扩大对内存及Eden区内存占比
  • 优化业务代码,减少查询数据库的次数

经过了这些优化措施之后,压测性能有了显著的提升,但距离压测通过标准还有不小差距。

对于三级分类数据,因为其改动较少,变化不大,数据一致性要求也不高,所以还可以通过缓存的方式尽量避免从数据库中读取数据,这会大幅提升性能。

缓存分为两种:

  • 本地缓存
  • 分布式缓存

一,本地缓存

1,定义

本地缓存(Local Cache)通常指的是在单个应用实例的内存中存储的缓存数据。这种缓存方式简单直接,通常使用编程语言内置的数据结构如哈希表(HashMap)来实现。

2,优点

  1. 访问速度快:由于数据存储在本地内存中,访问本地缓存几乎无网络延迟,可以快速响应数据请求。
  2. 简单易实现:大多数编程语言都提供了易于使用的集合类,如Java中的HashMap,Python中的dict,可以快速实现本地缓存。

3,代码示例(Java)

以下是一个简单的本地缓存实现示例,使用Java中的HashMap:

java 复制代码
import java.util.HashMap;
import java.util.Map;

public class LocalCacheExample {
    private Map<String, Object> cache = new HashMap<>();

    public Object getFromCache(String key) {
        // 尝试从本地缓存获取数据
        return cache.get(key);
    }

    public void addToCache(String key, Object value) {
        // 将数据放入本地缓存
        cache.put(key, value);
    }

    public static void main(String[] args) {
        LocalCacheExample localCache = new LocalCacheExample();
        
        // 假设我们缓存一个商品信息
        String productId = "123";
        Product product = getProductFromDatabase(productId); // 从数据库获取商品信息
        localCache.addToCache(productId, product);
        
        // 后续请求可以直接从缓存获取
        product = (Product) localCache.getFromCache(productId);
        if (product != null) {
            System.out.println("Product found in local cache.");
        } else {
            System.out.println("Product not found in local cache, fetching from DB.");
        }
    }
    
    private Product getProductFromDatabase(String id) {
        // 模拟数据库查询
        return new Product(id, "Sample Product");
    }
}

class Product {
    private String id;
    private String name;
    
    public Product(String id, String name) {
        this.id = id;
        this.name = name;
    }
    
    // Getters and Setters
}

4,缺点

  1. 数据不一致:在多实例部署的情况下,每个实例可能拥有不同的本地缓存副本,导致数据不一致。
  2. 容量有限:缓存容量受限于单台服务器的内存大小,不适合存储大量数据。
  3. 扩展性差 :本地缓存难以水平扩展,当系统负载增加时,可能需要更复杂的解决方案。
    ,

二,分布式缓存

在分布式系统中,数据的快速访问和一致性是至关重要的,这正是分布式缓存发挥作用的地方。以下是对分布式缓存的概述,包括其定义、优点、缺点以及代码示例。

1,定义

分布式缓存是一种将缓存数据分布在多个服务器或节点上的机制,这些服务器可以是物理机或虚拟机。它允许系统通过多个缓存节点共享数据,从而提高数据访问速度和系统扩展性。

2,优点

  1. 数据一致性:所有应用实例共享同一份缓存数据,确保了数据的一致性。
  2. 高可用性:通过冗余和故障转移机制,即使部分节点失败,缓存服务仍可继续提供服务。
  3. 扩展性强:可以通过增加更多的缓存节点来水平扩展,以应对不断增长的数据量和访问压力。
  4. 负载均衡:分布式缓存系统通常内置或支持负载均衡机制,可以均匀分配请求到各个节点。

3,缺点

  1. 访问速度相对较慢:与本地缓存相比,分布式缓存可能因为网络延迟而稍慢。
  2. 实现复杂:需要处理网络通信、数据分片、一致性协议等复杂问题。
  3. 成本较高:需要投资更多的硬件资源,以及维护分布式系统的复杂性。

4,代码示例

以下是使用Redis作为分布式缓存的一个简单示例。Redis是一个开源的内存数据结构存储系统,常用作分布式缓存解决方案。

java 复制代码
import redis.clients.jedis.Jedis;

public class RedisCacheExample {
    private static final String CACHE_HOST = "localhost";
    private static final int CACHE_PORT = 6379;

    public static void main(String[] args) {
        // 连接到Redis缓存服务器
        try (Jedis jedis = new Jedis(CACHE_HOST, CACHE_PORT)) {
            // 将数据放入缓存
            jedis.set("product:123", "Product Name");

            // 从缓存中获取数据
            String productName = jedis.get("product:123");
            System.out.println("Cached Product Name: " + productName);

            // 如果需要更新缓存中的数据
            jedis.set("product:123", "Updated Product Name");
        }
    }
}

在这个示例中,我使用Java的Jedis客户端连接到本地运行的Redis服务器,并将一个产品名称作为字符串存储在缓存中。之后,从缓存中检索并打印这个名称。如果产品信息更新了,也可以简单地更新缓存中的值。

三,本地缓存与分布式缓存的适用场景

  • 本地缓存:适用于单实例部署,或者对缓存数据一致性要求不高的场景。
  • 分布式缓存:适用于多实例部署,对数据一致性和高可用性有较高要求的场景。

四,缓存一致性的挑战与解决方案

  • 缓存穿透:通过设置合理的超时策略和使用布隆过滤器来防止。
  • 缓存雪崩:通过缓存数据的分布式过期策略来避免大量缓存同时过期。
  • 缓存击穿:对于热点数据,使用互斥锁或分布式锁来保证更新操作的原子性。
相关推荐
Oak Zhang1 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存
门牙咬脆骨2 小时前
【Redis】redis缓存击穿,缓存雪崩,缓存穿透
数据库·redis·缓存
门牙咬脆骨2 小时前
【Redis】GEO数据结构
数据库·redis·缓存
wusong9992 小时前
mongoDB回顾笔记(一)
数据库·笔记·mongodb
猫爪笔记2 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
Resurgence032 小时前
【计组笔记】习题
笔记
pq113_63 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio
谭震鸿3 小时前
Zookeeper集群搭建Centos环境下
分布式·zookeeper·centos
爱米的前端小笔记4 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
寒笙LED6 小时前
C++详细笔记(六)string库
开发语言·c++·笔记