面试题答案
一键面试- 获取Redis分布式锁:
- 使用
SETNX
(SET if Not eXists
)命令尝试获取锁。例如在Python中使用redis - py
库:
import redis r = redis.Redis(host='localhost', port = 6379, db = 0) lock_key = 'your_lock_key' lock_value = 'unique_value' if r.setnx(lock_key, lock_value): # 获取锁成功 pass else: # 获取锁失败,处理重试或返回错误 pass
- 为锁设置一个合理的过期时间,防止死锁。可以在
SETNX
成功后使用EXPIRE
命令,或者在SET
时直接设置过期时间,如在Redis 2.6.12及以上版本可以使用SET key value NX EX seconds
语法。
- 使用
- 开启MySQL事务:
- 在获取到Redis锁后,立即开启MySQL事务。以Python的
pymysql
库为例:
import pymysql conn = pymysql.connect(host='localhost', user='user', password='password', database='your_database') cursor = conn.cursor() try: conn.begin() # 执行MySQL操作,如插入、更新等 sql = "UPDATE your_table SET some_column = %s WHERE some_condition = %s" cursor.execute(sql, ('new_value', 'condition_value')) except Exception as e: # 事务回滚 conn.rollback() raise e
- 在获取到Redis锁后,立即开启MySQL事务。以Python的
- 释放Redis分布式锁:
- 无论MySQL事务执行成功还是失败,都需要确保释放Redis锁。在Python中:
if r.get(lock_key) == lock_value: r.delete(lock_key)
- 为了保证删除操作的原子性,也可以使用Lua脚本来执行删除操作。例如:
if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end
- 在Python中调用Lua脚本删除锁:
script = """ if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end """ r.eval(script, 1, lock_key, lock_value)
- 提交MySQL事务:
- 在成功释放Redis锁后,如果MySQL事务没有因为异常回滚,则提交事务。
conn.commit()
- 最后关闭数据库连接。
cursor.close() conn.close()
总结起来,设计流程就是先获取Redis分布式锁,接着开启MySQL事务进行数据操作,操作完成后先释放Redis锁,再提交MySQL事务,确保锁的释放和MySQL事务的原子性。