一级二级缓存设计

为什么需要多级缓存 在互联网系统中,随着业务规模不断增长,数据库往往会成为系统的性能瓶颈。大量请求如果直接访问数据库,不仅会带来高延迟,还会导致数据库压力过大,甚至出现连接耗尽、查询变慢等问题。因此,几乎所有高并发系统都会引入 缓存(Cache) 来提升系统性能。 最常见的缓存方式是使用 Redis 作为统一缓存层。客户端请求首先访问 Redis,如果缓存命中,就直接返回数据;如果缓存未命中,再访问数据库并将结果写入缓存。这种方式已经能够显著降低数据库压力。 但随着系统规模继续扩大,仅仅依赖 Redis 仍然可能出现新的问题。例如在高 QPS 场景下,大量请求同时访问 Redis,会产生网络开销和 Redis CPU 压力。同时,某些热点数据可能会被频繁读取,每次都经过网络访问 Redis,也会带来额外延迟。 为了解决这些问题,很多大型系统会引入 多级缓存架构(Multi-Level Cache),其中最常见的一种模式就是 一级缓存 + 二级缓存设计。
6 min read

Redis分布式锁

很多人在刚接触分布式系统的时候,都会遇到一个问题: 多个服务实例同时处理同一件事情,如何避免数据被重复处理? 例如: * 用户抢优惠券 * 定时任务执行 * 库存扣减 * 订单状态更新 如果系统只有一个进程,其实很简单,用 本地锁(mutex) 就能解决。 但在微服务架构或者集群部署之后,问题就变了。 系统可能有: * 10个服务实例 * 100个Worker * 甚至多个数据中心 这时候,本地锁就完全失效了,因为不同进程之间根本不知道彼此的锁状态。 于是就出现了一个概念: 分布式锁(Distributed Lock) 分布式锁的目标很简单: 在分布式环境下,保证某一时刻只有一个节点能执行某段逻辑。 为什么 Redis 可以做分布式锁? 在实现分布式锁的时候,很多人第一反应是数据库。 例如: select ... for update 但数据库锁的问题是: * 性能差 * 锁粒度大 * 并发高时压力很大 于是大家开始寻找一个更适合做锁的系统。 Redis就非常合适。 原因很简单:
5 min read

Redis 线程模型

Redis 以高性能著称,其核心原因之一就是其独特的 线程模型设计。很多人听说 Redis 是“单线程”,但实际上 Redis 的线程模型在不同版本中已经发生了演进。理解 Redis 的线程模型,对于理解其高性能原理、以及在高并发场景中的使用方式非常重要。 本文将从 Redis 单线程设计、事件驱动模型、IO 多路复用以及 Redis 6 之后的多线程改进几个方面进行介绍。 Redis 为什么选择单线程 Redis 早期版本(Redis 6 之前)的核心执行模型是 单线程处理命令。 也就是说: * 所有客户端请求 * 所有命令执行 * 数据读写 都由 一个主线程完成。 但需要注意的是: Redis 的单线程 只指命令执行单线程,并不是整个 Redis 进程只有一个线程。例如: * RDB 持久化
3 min read

Redis 常用UI工具

Redis虽然可以通过客户端执行命令查看数据信息,但并没有图形化界面来的高效,故此记录几款常用的Redis UI工具。 Redis Desktop Manager 收费,可以试用半个月,也可以在网上找到破解版,只是版本可能并不是最新版本。 RESP.app (formerly Redis Desktop Manager) - GUI for Redis ® available on Windows, macOS, iPad and Linux.Cross-platform GUI for Redis ® : download for macOS, iPad, Windows and Linux.RESP.appIgor Malinovskiy AnotherRedisDesktopManager 开源免费,好用,UI简洁好看。 GitHub - qishibo/AnotherRedisDesktopManager:
2 min read

Redis 缓存一致性

缓存一致性 首先我们先说说什么是缓存一致性问题,为什么要解决,以及方案是什么。 缓存一致性问题是指在使用缓存时,由于缓存数据与数据库数据的不一致性,可能会导致数据错误或者数据丢失等问题。这种问题在高并发场景下尤为常见,因为多个线程同时读写同一份数据时,很难保证数据的一致性。如何保证和Redis内存中的数据与DB数据库中的数据保持一致,并且不能出现数据不一致的情况(高并发场景中),如果出现数据不一致对于某些情况来说可能会出现大麻烦,缓存一致性的解决方案也很重要。 以下是我列出常见的几种方案,以及它们在高并发场景下各自的问题。 直接写入缓存 (不推荐) 在3,4步执行时高并发场景下无法保证写入Redis数据的Java线程会进行顺序执行(因为CPU时间分片问题,并且加上分布式、微服务情况更加明显)。才会导致最新数据可能被其他线程中的旧数据覆盖,如果发生了之后后续没有其他线程执行,可能缓存数据一直会保持旧数据情况。 这里可能有人会直接使用分布式锁(单应用加JVM锁即可),加锁需要控制整个DB写入到Redis写入的流程,并且每个Key操作的函数范围需要自己把控,且效率肯定下降得厉害
4 min read

Redis 缓存穿透,击穿,雪崩

缓存穿透 缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍,然后返回空。 如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间大量请求落在数据库上,造成数据库压力过大,甚至击垮数据库系统。 解决方案: (1)布隆过滤器 布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。 如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过可以使用散列表(又叫哈希表,Hash table)数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。 (2)返回空 当缓存未命中,查询
5 min read

Redis 主从,哨兵,集群搭建

前言 记录一下自己对 redis 主从,哨兵,集群三种模式搭建流程,redis的所有部署模式都不复杂,主要是对配置文件的书写,以及各个模式的优缺点分析。 RedisRedis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message brokerRedis 部署环境 操作系统 CentOS7 Redis版本:Redis7.0.5 主从模式 优点:配置简单,快速,读写分离,完全分担了主节点的读压力,并且从节点还可套娃继续配置多层从节点。 缺点:非高可用,主节点宕机,则失去写能力,数据冗余量大,每个从节点100%复制主节点数据。 非高可用架构,
16 min read

随心笔记

技术无止境 创新不停驻