最近学习了下lua,主要想在redis或者nginx做一些拓展,redis的数据类型很多,能帮助我们处理业务中的很多场景,从 Redis 2.6.0 版本开始,通过内置的 Lua 解释器,可以使用 EVAL 命令对 Lua 脚本进行求值。
redis对lua脚本的调用是原子性的,所以一些特殊场景,比如像实现分布式锁,我们可以放在lua中实现
本篇主要记录一下使用redistemplate调用lua脚本的简单应用场景,编写一段lua脚本来实现ip限速
- 编写用到的lua脚本
local count = redis.call('incr',KEYS[1])
if count == 1 then
redis.call('expire',KEYS[1],ARGV[1])
end
if count > tonumber(ARGV[2]) then
return 0
end
return 1
把ip作为key传入,然后对其计数+1,当超过我们传入的限制次数(ARGV[2])时,返回0,否则返回1
2.使用redistemplate调用该脚本
@Service("ipAccessService")
public class IpAccessService {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
private DefaultRedisScript<Long> script;
private static final String IPACCESS_KEY_PREX = "ipaccess_";
@PostConstruct
private void init(){
script = new DefaultRedisScript<Long>();
script.setResultType(Long.class);
script.setScriptSource(new ResourceScriptSource(new
ClassPathResource("ipaccess.lua")));
}
public boolean exec(String ip) {
List<String> keys = new ArrayList<>();
keys.add(IPACCESS_KEY_PREX + ip);
return redisTemplate.execute(script, keys, 10, 20) == 1 ? true : false;
}
}
主要使用redistempalte封装的execute来实现调用,其中第二个参数为lua脚本中的KEYS[1],后面为可变参数,可变参数即传入我们需要的值,分别对应ARGV[1],ARGV[2]
3.编写拦截器,获取ip,注入该service传入ip完成调用,剩下可以编写一些自己需要的逻辑。