Redis 和 MySQL 结合使用

Redis 和 MySQL 结合使用的场景非常常见,通常是利用 Redis 作为缓存层来提升 MySQL 数据库的性能,减少数据库的压力,同时提高系统的响应速度。下面是它们结合使用的几种常见方法:

1. 缓存数据库(Cache-Aside)模式

在这种模式下,应用程序首先从 Redis 缓存中查找数据,如果没有找到(缓存未命中),则从 MySQL 数据库中查询数据,并将查询结果缓存到 Redis 中,以便下次查询时能直接从缓存获取。

过程:
  • 应用程序首先查询 Redis,如果 Redis 中有数据(缓存命中),直接返回。
  • 如果 Redis 中没有数据(缓存未命中),则查询 MySQL 数据库。
  • 从 MySQL 查询到的数据存入 Redis 缓存中,并设置缓存的过期时间。
  • 下一次查询时,直接从 Redis 中获取数据。
示例代码:
python 复制代码
import redis
import mysql.connector

# 连接 Redis 和 MySQL
r = redis.Redis(host='localhost', port=6379, db=0)
db = mysql.connector.connect(user='root', password='password', host='localhost', database='test')

def get_user_info(user_id):
    # 先从缓存查询
    cached_data = r.get(f"user:{user_id}")
    if cached_data:
        return cached_data.decode('utf-8')  # 缓存命中,直接返回

    # 缓存未命中,从 MySQL 查询
    cursor = db.cursor()
    cursor.execute("SELECT name FROM users WHERE id = %s", (user_id,))
    result = cursor.fetchone()

    if result:
        # 查询到数据后存入缓存
        name = result[0]
        r.setex(f"user:{user_id}", 3600, name)  # 设置过期时间为1小时
        return name
    return None

2. 缓存穿透防护

缓存穿透是指查询的数据既不在缓存中也不在数据库中,导致每次请求都直接访问数据库。为防止这种情况,可以使用布隆过滤器或者缓存空值。

方案:
  • 使用布隆过滤器:在 Redis 中设置一个布隆过滤器,记录所有合法的键值。如果查询的数据不在布隆过滤器中,说明该数据不可能存在,直接返回空。
  • 缓存空值:当查询的数据不存在时,将空值存入 Redis,以避免重复查询数据库。
示例:
python 复制代码
from pybloom_live import BloomFilter

# 初始化布隆过滤器
bloom = BloomFilter(capacity=1000000, error_rate=0.001)

def get_user_info_with_bloom(user_id):
    if user_id not in bloom:
        return None  # 如果布隆过滤器没有该数据,直接返回 None

    cached_data = r.get(f"user:{user_id}")
    if cached_data:
        return cached_data.decode('utf-8')  # 缓存命中

    cursor = db.cursor()
    cursor.execute("SELECT name FROM users WHERE id = %s", (user_id,))
    result = cursor.fetchone()

    if result:
        name = result[0]
        r.setex(f"user:{user_id}", 3600, name)  # 缓存数据
        return name
    else:
        # 数据库没有此数据,缓存空值
        r.setex(f"user:{user_id}", 60, "none")  # 设置过期时间为1分钟
        return None

3. 数据同步策略

由于 Redis 是内存数据库,当缓存中的数据发生变化时,必须确保 Redis 中的缓存和 MySQL 数据库中的数据保持一致。常见的同步方式有以下几种:

方案:
  • 定时更新缓存:定时任务检查数据库的更新,并更新 Redis 缓存。
  • 主动更新缓存:在数据更新时,应用程序在更新 MySQL 后,立即同步更新缓存。
  • 延时双删策略:当缓存数据失效时,数据库查询结果被更新到 Redis 中,为了避免数据不一致,可以在删除缓存后稍作延迟,再删除一次缓存。
示例:
python 复制代码
def update_user_info(user_id, new_name):
    # 更新 MySQL 数据库中的数据
    cursor = db.cursor()
    cursor.execute("UPDATE users SET name = %s WHERE id = %s", (new_name, user_id))
    db.commit()

    # 删除 Redis 中的缓存
    r.delete(f"user:{user_id}")

    # 更新 Redis 缓存
    r.setex(f"user:{user_id}", 3600, new_name)

4. Redis 作为 MySQL 的主从架构加速

对于一些高并发的应用,MySQL 可能面临较大的读写压力,使用 Redis 可以在 MySQL 的读写分离架构中,帮助缓存热点数据,减轻主数据库的压力。

5. Redis 发布/订阅模式(Pub/Sub)

在一些需要实时通知的场景中,可以结合 Redis 的发布/订阅功能来实时同步 MySQL 数据库的变动。例如,MySQL 数据库中的某些数据发生变化时,使用 Redis 进行通知,让其他系统或服务进行响应。

总结

Redis 和 MySQL 结合使用的方式,主要是利用 Redis 的高速缓存和 MySQL 的持久化存储各自的优点:

  • Redis 用于缓存热点数据,提升查询速度。
  • MySQL 用于持久化存储,处理复杂查询。 结合使用时,通常需要处理缓存一致性、缓存失效、缓存穿透等问题。通过合理的策略(如缓存更新、布隆过滤器、延时双删等),可以提高系统的性能、可靠性和扩展性。
相关推荐
技术宝哥2 小时前
Redis(2):Redis + Lua为什么可以实现原子性
数据库·redis·lua
学地理的小胖砸3 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
dddaidai1234 小时前
Redis解析
数据库·redis·缓存
数据库幼崽4 小时前
MySQL 8.0 OCP 1Z0-908 121-130题
数据库·mysql·ocp
Amctwd4 小时前
【SQL】如何在 SQL 中统计结构化字符串的特征频率
数据库·sql
工一木子4 小时前
【Java项目脚手架系列】第七篇:Spring Boot + Redis项目脚手架
java·spring boot·redis
betazhou5 小时前
基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL
linux·数据库·mysql·oracle·ogg
lyrhhhhhhhh5 小时前
Spring 框架 JDBC 模板技术详解
java·数据库·spring
喝醉的小喵6 小时前
【mysql】并发 Insert 的死锁问题 第二弹
数据库·后端·mysql·死锁
付出不多7 小时前
Linux——mysql主从复制与读写分离
数据库·mysql