redis+lua语言去重
1)redis
redis是一种键值对的单线程架构模型,所以它是线程安全的,也是分布式缓存常用的解决方案。
2)lua
lua是基于c语言的一种脚本语言,它可以很轻便地被使用在嵌入式方面。我们不会去重写redis,但是我们可以去使用lua来扩展redis的功能。而redis也内置了对lua支持的模块。
3)redis+lua是我司基于分布式告警去重的一种解决方案,要达到的目的:堵住10是s内的重复告警,主要应用的场景是同一个告警,在不通的客户端同时推送了一条告警数据,此时要堵住
一条数据。
直接上代码吧
@Component public class RedisLua { @Autowired private RedisTemplate<String,Object> redisTemplate; private DefaultRedisScript<Boolean> script; private static final String KEY_PREX = "alertInfo_"; @PostConstruct private void init(){ script = new DefaultRedisScript<Boolean>(); script.setResultType(Boolean.class); script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/alert.lua")));//lua脚本文件 }public Boolean blockRepetition(String ruleId,String status,String ip,Object...args){ List<String> keys = new ArrayList<>(); keys.add(KEY_PREX + ip+ruleId+status);//key包括前缀+客户端ip+告警规则id+状态 return redisTemplate.execute(script, keys, args); } }
下面是lua脚本
--[[ ARGV1表示redis生效时间,key表示存储redis的key值]] local alert = redis.call('exists',KEYS[1]); if alert then return false else redis.call('set',KEYS[1],ngx.time()) redis.call('expire',KEYS[1],ARGV[1]) return true end
该方案主要用于微服务集群中,采用分布式锁防和redis集群确保数据唯一。
使用脚本的好处如下:
1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。
2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。
3.复用:客户端发送的脚本会永久存储在Redis中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。