- 双写模式
- 操作流程:
- 当MySQL数据发生更新时,同时对Redis中的预计算数据进行更新。例如,在一个电商系统中,如果商品的价格在MySQL中被修改,那么根据价格参与计算的Redis预计算数据(如某类商品的平均价格等)也要同步修改。
- 代码示例(以Python的Flask框架结合SQLAlchemy和Redis - Py为例):
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import redis
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='mysql://user:password@localhost/mydb'
db = SQLAlchemy(app)
r = redis.Redis(host='localhost', port = 6379, db = 0)
class Product(db.Model):
id = db.Column(db.Integer, primary_key = True)
price = db.Column(db.Float)
@app.route('/update_product_price/<int:product_id>/<float:new_price>', methods=['POST'])
def update_product_price(product_id, new_price):
product = Product.query.get(product_id)
product.price = new_price
db.session.commit()
# 更新Redis预计算数据,假设Redis中存储了所有商品的平均价格
all_products = Product.query.all()
total_price = sum([p.price for p in all_products])
average_price = total_price / len(all_products) if all_products else 0
r.set('average_product_price', average_price)
return 'Product price updated successfully'
- 优缺点:
- 优点:实现相对简单,能够快速保证数据一致性。
- 缺点:在高并发场景下,可能会因为网络等原因导致MySQL更新成功但Redis更新失败,造成数据不一致。而且每次更新都需要操作两个存储,增加了系统的开销。
- 消息队列模式
- 操作流程:
- 当MySQL数据更新时,向消息队列(如Kafka、RabbitMQ等)发送一条消息,消息内容包含更新的数据及相关操作信息(如新增、修改、删除)。
- 一个独立的消费者服务监听这个消息队列,当收到消息时,根据消息内容对Redis中的预计算数据进行相应的更新。例如,在一个社交平台中,用户的点赞数在MySQL中更新后,发送消息到消息队列,消费者服务收到消息后重新计算该用户相关的热度值(Redis预计算数据)。
- 代码示例(以Python结合RabbitMQ和Redis - Py为例):
import pika
import redis
# 连接RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='mysql_updates')
# 连接Redis
r = redis.Redis(host='localhost', port = 6379, db = 0)
def callback(ch, method, properties, body):
# 假设消息体格式为:user_id:new_like_count
parts = body.decode('utf - 8').split(':')
user_id = parts[0]
new_like_count = int(parts[1])
# 重新计算用户热度值并更新到Redis
# 这里假设热度值计算方式为点赞数的平方
popularity = new_like_count * new_like_count
r.set(f'user_{user_id}_popularity', popularity)
channel.basic_consume(queue='mysql_updates', on_message_callback = callback, auto_ack = True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
- 优缺点:
- 优点:解耦了MySQL和Redis的更新操作,提高了系统的可扩展性和稳定性。消息队列可以保证消息不丢失,即使消费者服务出现故障,重启后可以继续处理未处理的消息。
- 缺点:引入了额外的组件(消息队列),增加了系统的复杂性和维护成本。消息处理可能存在一定的延迟,无法做到绝对实时的一致性。
- 数据库触发器模式(仅适用于支持触发器的数据库,如MySQL)
- 操作流程:
- 在MySQL数据库中创建触发器。例如,当对某张表进行INSERT、UPDATE或DELETE操作时,触发器会被触发。触发器可以向一个特定的表(如
redis_update_log
)中插入一条记录,记录包含需要更新Redis预计算数据的相关信息(如涉及的表名、主键值等)。
- 一个后台任务(如定时任务或常驻进程)定期检查
redis_update_log
表,根据记录的信息更新Redis中的预计算数据。例如,在一个博客系统中,当文章的评论数在MySQL中更新时,触发器记录更新信息到redis_update_log
表,后台任务根据这些信息重新计算文章的热度值(Redis预计算数据)。
- 优缺点:
- 优点:利用数据库自身的功能实现数据的关联操作,对应用层代码侵入性小。可以精确控制在数据库操作的同时记录相关更新信息。
- 缺点:不同数据库的触发器语法可能不同,可移植性较差。后台任务定期检查存在一定延迟,而且如果触发器逻辑复杂,可能会影响数据库的性能。