更新数据是先更新缓存(redis),还是先更新数据库(mysql)

本文探讨了缓存与数据库一致性的问题,分析了先更新数据库再删除缓存和先更新缓存再更新数据库两种策略的优缺点。指出在无法保证绝对一致性的前提下,推荐先更新数据库再删除缓存的方法,并讨论了异常处理机制。

1:缓存的目的是为了减少数据库的压力,而且redis支持事务处理机制,请求优先命中redis,缓存中没有在命中数据库,所以优先删除缓存,然后更新数据库,即使删除缓存成功,但是更新数据库失败,但是数据依然存在。
2:如果在更新数据库的时候报错,或者服务宕dang机,
最后只能采用补偿机制,保证最后达到最终的数据的一致性。

提问:
老师,上次面试我的回答是先更新数据库,在更新缓存。
但是面试官给我的回答是,先更新缓存,再更新数据库。
后来我也上网查了下,先更新缓存,再异步将缓存中的数据同步到数据库。
但是我并没有查到相关的代码逻辑。总结两种方式入戏
1:先更新数据库 - 删缓存 - 再次访问 - 查询数据库 - 存入缓存
2:更新redis(新key覆盖旧key) - 查询 - redis异步将数据同步mysql

解答:
(1)只要用了缓存,就肯定会有不一致,2个数据源之间是没有事务的,没法保证绝对的一致。
(2)如果想绝对一致,那就别用缓存
(3)如果能接受一定程度上的不一致,可以先更新数据库,再删除缓存。
(4)如果事先更新缓存再更新数据库,如果数据库回滚,缓存怎么处理?这种方式不推荐。如果能接受这种不一致,也可以用。

提问:
如果事先更新缓存再更新数据库,如果数据库回滚,缓存怎么处理?
数据发生了回滚,即出现异常,这里做一个异常回调,删除对应的缓存。
老师,这种思路可行吗?

解答:
不推荐 代码的侵入性太大 首先你要记下来redis之前的值 回滚的时候再写回去,如果是insert 你得做一次delete,如果是update 你需要update回去,如果delete你得jinsert,再者 如果回调中发生了异常怎么办

在使用 Redis 缓存 MySQL 数据的过程中,通常采用读写分离缓存策略来提升系统性能响应速度。以下是对 Redis 缓存 MySQL 数据的实现方式、数据更新策略以及数据格式转换方法的详细说明。 ### 缓存 MySQL 数据的基本流程 Redis 作为缓存层,通常存储 MySQL 中热点数据,以减少数据库访问压力。基本流程如下: 1. 应用层访问 Redis,查询数据; 2. 如果 Redis 中存在所需数据,则直接返回; 3. 如果 Redis 中不存在所需数据,则访问 MySQL 查询; 4. 查询结果写入 Redis,并返回给应用层。 缓存结构通常采用字符串、哈希、JSON 等形式,例如: ```python # 示例:将 MySQL 查询结果以 JSON 格式存入 Redis import json import redis import mysql.connector # 连接 MySQL mysql_conn = mysql.connector.connect( host="localhost", user="root", password="password", database="testdb" ) cursor = mysql_conn.cursor(dictionary=True) # 连接 Redis redis_client = redis.StrictRedis(host='localhost', port=6379, db=0) # 查询数据缓存 def cache_user_data(user_id): cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) result = cursor.fetchone() if result: redis_client.setex(f"user:{user_id}", 3600, json.dumps(result)) # 设置缓存并设置过期时间 ``` ### 数据更新策略 当 MySQL 数据发生变化时,需要同步更新或删除 Redis 缓存中的数据。常见的策略如下: - **缓存穿透处理**:通过布隆过滤器过滤无效请求,防止恶意攻击导致缓存失效。若布隆过滤器判断数据不存在,则直接返回空值,避免穿透到数据库[^2]。 - **缓存更新策略**: - **主动更新**:当 MySQL 数据更新后,主动更新 Redis 缓存中的数据。 - **惰性删除**:更新 MySQL 数据后,删除 Redis 缓存,下次请求时自动重新加载。 - **过期机制**:为缓存设置合理的过期时间,作为最终一致性保障手段[^2]。 ### 数据同步与转换方法 为了实现 MySQLRedis数据同步,可以采用以下方法: 1. **异步队列同步**:MySQL 数据更新后,将变更记录写入消息队列(如 Kafka、RabbitMQ 或 Redis 自身的 List 结构),由消费者异步更新 Redis 缓存[^3]。 2. **Redis Pipeline 批量操作**:对于大量数据更新,使用 Redis Pipeline 提升性能,减少网络往返次数。 3. **数据合并更新**:对于短时间内对同一数据的多次更新,可以合并为一次操作,避免频繁更新 Redis。 4. **JSON 或 Protobuf 序列化**:将 MySQL 查询结果转换为 JSON 或 Protobuf 格式后存入 Redis,便于应用层解析传输。例如: ```python # 将 MySQL 查询结果转换为 JSON 并存储 import json data = {"id": 1, "name": "Alice", "email": "alice@example.com"} redis_client.set("user:1", json.dumps(data)) ``` ### 分布式环境下的缓存一致性 在分布式系统中,为保证 RedisMySQL 数据一致性,可使用分布式锁(如 Redlock 算法)控制并发访问,防止多个服务同时修改同一份数据导致不一致。 ```python # 使用 Redis 分布式锁更新缓存 import redis import time def acquire_lock(redis_client, lock_key, expire_time): return redis_client.set(lock_key, "locked", ex=expire_time, nx=True) def release_lock(redis_client, lock_key): redis_client.delete(lock_key) def update_cache_with_lock(user_id): lock_key = f"lock:user:{user_id}" if acquire_lock(redis_client, lock_key, 10): # 获取锁,10秒过期 try: # 更新 MySQL Redis pass finally: release_lock(redis_client, lock_key) # 释放锁 ``` ###
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值