1. 数据写入缓存的策略
- 直写式(Write-Through):
- 原理:在写入MySQL数据库的同时,将数据写入Redis缓存。这样能保证缓存和数据库的数据一致性。
- 示例代码(Python + Flask + SQLAlchemy + Redis):
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 User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
@app.route('/create_user/<name>')
def create_user(name):
new_user = User(name = name)
db.session.add(new_user)
db.session.commit()
r.set(f'user:{new_user.id}', new_user.name)
return 'User created successfully'
- 延迟写(Write-Behind):
- 原理:先将数据写入Redis缓存,然后由专门的异步任务或线程将数据批量写入MySQL数据库。这种方式可以提高写入性能,但可能会在异步写入前丢失数据。
- 示例代码(Python + Celery + Redis + SQLAlchemy):
from celery import Celery
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)
celery = Celery('tasks', broker='redis://localhost:6379/0')
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
@celery.task
def write_to_db(user_id, name):
new_user = User(id = user_id, name = name)
db.session.add(new_user)
db.session.commit()
@app.route('/create_user/<name>')
def create_user(name):
user_id = r.incr('user_counter')
r.set(f'user:{user_id}', name)
write_to_db.delay(user_id, name)
return 'User creation in progress'
2. 缓存更新的方式
- 主动更新:
- 原理:当MySQL数据库中的数据发生变化(如插入、更新、删除操作)时,主动去更新Redis缓存中的相应数据。
- 示例代码(以更新为例,Python + Flask + SQLAlchemy + Redis):
@app.route('/update_user/<int:user_id>/<name>')
def update_user(user_id, name):
user = User.query.get(user_id)
if user:
user.name = name
db.session.commit()
r.set(f'user:{user_id}', name)
return 'User updated successfully'
return 'User not found'
- 失效模式:
- 原理:为Redis缓存中的数据设置一个过期时间。当数据过期后,下次查询时发现缓存中没有数据,就从MySQL数据库中查询并重新写入缓存。
- 示例代码(Python + Flask + SQLAlchemy + Redis):
@app.route('/get_user/<int:user_id>')
def get_user(user_id):
user_name = r.get(f'user:{user_id}')
if user_name:
return user_name.decode('utf-8')
user = User.query.get(user_id)
if user:
r.setex(f'user:{user_id}', 3600, user.name) # 设置过期时间为1小时
return user.name
return 'User not found'
- 读写锁(Read - Write Lock):
- 原理:使用读写锁来控制对缓存和数据库的读写操作。读操作可以并发进行,而写操作时需要先获取写锁,阻止其他读写操作,确保数据一致性。在Redis中可以通过一些脚本或第三方库来模拟读写锁。例如,使用
redlock - py
库实现分布式读写锁来保护缓存和数据库的读写操作。
- 示例代码(使用
redlock - py
库简化示例):
from redlock import Redlock
import redis
r = redis.Redis(host='localhost', port=6379, db = 0)
redlock = Redlock([{
"host": "localhost",
"port": 6379,
"db": 0
}])
# 读操作
def read_data(key):
lock = redlock.lock('read - lock', 1000)
if lock:
data = r.get(key)
redlock.unlock(lock)
return data
return None
# 写操作
def write_data(key, value):
lock = redlock.lock('write - lock', 1000)
if lock:
r.set(key, value)
# 同时更新数据库操作(这里省略具体数据库操作代码)
redlock.unlock(lock)
return True
return False
3. 通过Redis缓存提升MySQL数据查询响应速度的整体流程
- 查询请求到达:应用程序接收到查询请求。
- 检查缓存:首先检查Redis缓存中是否有所需数据。如果有,直接返回缓存中的数据,大大提高响应速度。
- 缓存未命中:如果Redis缓存中没有所需数据,则从MySQL数据库中查询数据。
- 数据写入缓存:从MySQL查询到数据后,将数据写入Redis缓存,以便后续查询可以直接从缓存获取。
- 返回数据:将从缓存或数据库获取的数据返回给应用程序。