面试题答案
一键面试Redis协助MySQL实现并发控制的原理
- 利用Redis的原子性操作:Redis的很多操作(如SETNX、INCR等)具有原子性。在MySQL批量数据处理场景下,可借助这些原子操作来实现并发控制。例如,当多个客户端同时尝试插入数据时,可通过Redis的原子操作来判断数据是否已存在,避免重复插入。
- 分布式锁机制:Redis可以实现分布式锁。多个进程或服务器在处理批量数据时,通过获取Redis的锁来保证同一时间只有一个进程能进行关键操作(如插入数据),从而避免并发冲突。
具体使用方式举例 - 避免重复插入
- 使用SETNX命令
- 原理:SETNX(SET if Not eXists)命令在键不存在时,为键设置指定的值。如果键已经存在,SETNX命令不做任何动作。
- 示例代码(以Python为例):
import redis
import mysql.connector
r = redis.Redis(host='localhost', port=6379, db = 0)
mydb = mysql.connector.connect(
host="localhost",
user="your_user",
password="your_password",
database="your_database"
)
mycursor = mydb.cursor()
data_to_insert = "example_data"
redis_key = "insert_lock:" + data_to_insert
if r.setnx(redis_key, 1):
try:
sql = "INSERT INTO your_table (column_name) VALUES (%s)"
val = (data_to_insert,)
mycursor.execute(sql, val)
mydb.commit()
finally:
r.delete(redis_key)
else:
print("数据已存在,不重复插入")
- 使用分布式锁(基于SET操作实现)
- 原理:通过SET命令设置一个带有过期时间的键值对来模拟锁。当一个客户端成功设置该键值对时,就相当于获取到了锁。其他客户端在尝试获取锁时,如果设置失败,说明锁已被占用。
- 示例代码(以Python为例):
import redis
import mysql.connector
import time
r = redis.Redis(host='localhost', port=6379, db = 0)
mydb = mysql.connector.connect(
host="localhost",
user="your_user",
password="your_password",
database="your_database"
)
mycursor = mydb.cursor()
lock_key = "batch_insert_lock"
lock_value = str(int(time.time() * 1000))
expire_time = 10 # 锁的过期时间,单位秒
while True:
if r.set(lock_key, lock_value, nx=True, ex = expire_time):
try:
# 批量插入数据的逻辑
data_list = ["data1", "data2", "data3"]
for data in data_list:
sql = "INSERT INTO your_table (column_name) VALUES (%s)"
val = (data,)
mycursor.execute(sql, val)
mydb.commit()
break
finally:
if r.get(lock_key).decode('utf-8') == lock_value:
r.delete(lock_key)
else:
time.sleep(0.1)
在上述代码中,通过SET命令设置锁,成功获取锁后进行批量数据插入,操作完成后释放锁。如果获取锁失败,则等待一段时间后重试。