面试题答案
一键面试- 复用Lua脚本
- 说明:在高并发场景下,避免重复加载Lua脚本。Redis提供了
SCRIPT LOAD
命令来将Lua脚本加载到脚本缓存中,并返回一个脚本的SHA1摘要。后续使用EVALSHA
命令通过这个SHA1摘要来执行脚本,而不是每次都使用EVAL
命令重新加载脚本内容。这样可以减少网络开销和脚本解析时间。 - 示例:
-- 加载脚本 local script = "local stock = redis.call('GET', KEYS[1]) if tonumber(stock) > 0 then redis.call('DECR', KEYS[1]) return 1 else return 0 end" local sha1 = redis.call('SCRIPT LOAD', script) -- 执行脚本 local result = redis.call('EVALSHA', sha1, 1, "product:stock:123")
- 说明:在高并发场景下,避免重复加载Lua脚本。Redis提供了
- 减少Redis交互次数
- 说明:尽量将多个相关的Redis操作合并到一个Lua脚本中执行。因为每次Redis交互都存在网络延迟,在高并发下这会严重影响性能。例如,库存扣减和用户排队可以在同一个Lua脚本中完成,而不是分开进行多个Redis操作。
- 示例:
-- 库存扣减和用户排队逻辑 local stock = redis.call('GET', KEYS[1]) if tonumber(stock) > 0 then redis.call('DECR', KEYS[1]) redis.call('RPUSH', KEYS[2], ARGV[1]) return 1 else return 0 end
- 合理使用Redis数据结构
- 库存管理:
- 说明:对于库存数据,可以使用Redis的字符串类型来存储库存数量。如果需要更复杂的库存管理,如库存预警等,可以考虑使用哈希类型,将库存相关的各种属性存储在哈希表中。但在高并发扣减库存场景下,字符串类型的简单加减操作性能更高。
- 示例:
SET product:stock:123 100
来初始化库存为100。
- 用户排队:
- 说明:使用Redis的列表(List)数据结构来处理用户排队。列表的
RPUSH
命令可以高效地将用户ID加入队列,LPOP
命令可以从队列头部取出用户ID进行后续处理。 - 示例:
RPUSH秒杀排队:123 用户ID1
将用户ID1加入到指定商品的排队队列中。
- 说明:使用Redis的列表(List)数据结构来处理用户排队。列表的
- 库存管理:
- 优化内存使用
- 说明:在Lua脚本中避免创建不必要的大对象或无限循环。对局部变量及时释放,避免内存泄漏。例如,不要在Lua脚本中创建一个很大的数组用于临时存储数据,除非必要。如果需要临时存储数据,可以考虑使用Redis的数据结构,因为Redis的内存管理机制相对更高效。
- 示例:
-- 避免创建大数组 -- local largeArray = {} -- for i = 1, 10000 do -- table.insert(largeArray, i) -- end
- 脚本性能测试与优化
- 说明:使用性能测试工具(如Redis自带的
redis-benchmark
工具结合Lua脚本测试功能,或者自定义的压测脚本)对Lua脚本进行性能测试。分析脚本执行时间、资源占用等指标,针对性能瓶颈进行优化。例如,通过优化Lua脚本中的逻辑判断、循环等操作来提高执行效率。 - 示例:
- 使用
redis - benchmark
测试Lua脚本性能:
其中redis - benchmark - script script.lua - n 10000 - c 100
script.lua
是Lua脚本文件,-n
指定执行次数,-c
指定并发数。根据测试结果,调整脚本逻辑。
- 使用
- 说明:使用性能测试工具(如Redis自带的