面试题答案
一键面试Redis事务基本特性
- 单独的隔离操作:Redis事务中的所有命令会被序列化、按顺序执行。事务在执行过程中,不会被其他客户端发送来的命令请求所打断。
- 没有隔离级别的概念:队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行,也就不存在“事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题。
- 不保证原子性:Redis单个命令的执行是原子性的,但Redis没有在事务上增加任何维持原子性的机制,所以事务中的命令如果在执行期间出现错误,下一个命令依然会执行。
Lua脚本在Redis事务中的作用
- 简化复杂操作:通过Lua脚本可以将多个Redis命令组合在一起,减少网络开销,提升执行效率。在脚本执行期间,Redis会阻塞其他客户端的请求,保证脚本执行的原子性。
- 实现复杂逻辑:可以实现一些在Redis原生命令中难以实现的复杂业务逻辑,例如根据不同条件执行不同的Redis命令组合。
在Redis中使用Lua脚本配合事务实现简单原子操作示例
以下是使用Lua脚本配合Redis事务实现对计数器先加1再判断是否大于10,若大于10则重置为0的示例。假设计数器的键名为counter_key
:
-- 获取计数器当前值
local current_value = redis.call('GET', 'counter_key')
if current_value == nil then
current_value = 0
else
current_value = tonumber(current_value)
end
-- 计数器加1
current_value = current_value + 1
-- 将新值写回
redis.call('SET', 'counter_key', current_value)
-- 判断是否大于10
if current_value > 10 then
redis.call('SET', 'counter_key', 0)
end
return current_value
在客户端中执行该Lua脚本,例如在Python中使用redis - py
库:
import redis
r = redis.Redis(host='localhost', port=6379, db = 0)
script = """
local current_value = redis.call('GET', 'counter_key')
if current_value == nil then
current_value = 0
else
current_value = tonumber(current_value)
end
current_value = current_value + 1
redis.call('SET', 'counter_key', current_value)
if current_value > 10 then
redis.call('SET', 'counter_key', 0)
end
return current_value
"""
result = r.eval(script, 0)
print(result)
这样就通过Lua脚本在Redis中实现了所需的原子操作。