高并发场景分析之redis+lua防重校验

 更新时间:2023年07月10日 10:13:34   作者:想养一只萨摩耶~  
这篇文章主要介绍了高并发场景分析之redis+lua防重校验,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

高并发场景:redis+lua防重校验

大家平时在做有并发量下单的项目时,代码层面基本上就分为这么几个步骤:参数校验--->防重校验--->库存校验扣减--->下单成功--->支付

最近公司有个商城项目说要30分钟达到1亿的并发量。当时听到突然猛了一下。真是牛逼克拉斯呀。

不过该说不说还是得开搞,所谓的并发无非就是要想办法减少io的操作,尽量少查表,其余配置方面的问题就看公司舍不舍得花钱了。

其中防重校验这一部分选用了redis集合lua来做,来防止多次提交。

注意:真实下单操作是分为了订单前置操作 (前置校验和生成防重令牌)和提交订单两个接口来写的,这里为了测试简单合并了

@RestController
@RequestMapping("/lua")
public class TestLuaController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    private static final String ORDER_CHECK_TOKEN = "order_check_token";
    private static final String ORDER_TOKEN_DEFAULT_VALUE = "value";
    /**
     * 场景:最近公司有高并发场景,涉及到用令牌防重(防止有人多次提交订单)
     *     可以使用redis执行lua脚本 比较key值令牌是否存在,如果存在即删除
     */
    @RequestMapping("/checkTempToken")
    public Long luaExecute(String checkToken){
        //模拟提交订单生成的防重令牌
        redisTemplate.opsForValue().set(ORDER_CHECK_TOKEN + checkToken,ORDER_TOKEN_DEFAULT_VALUE,60, TimeUnit.SECONDS);
        String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
//执行redis脚本操作的函数
        Long execute = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(ORDER_CHECK_TOKEN + checkToken), ORDER_TOKEN_DEFAULT_VALUE);
        System.out.println(execute);
        return execute;
    }
}

结果:

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中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。

到此这篇关于高并发场景分析之redis+lua防重校验的文章就介绍到这了,更多相关redis+lua防重内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Redis 数据类型的详解

    Redis 数据类型的详解

    这篇文章主要介绍了Redis 数据类型的详解的相关资料,支持五种数据类型,字符串,哈希,列表,集合及zset,需要的朋友可以参考下
    2017-08-08
  • 关于redis的延迟双删策略总结

    关于redis的延迟双删策略总结

    这篇文章主要介绍了关于redis的延迟双删策略总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Redis+aop实现接口防刷(幂等)的解决方案

    Redis+aop实现接口防刷(幂等)的解决方案

    在高并发场景下,可能会因为网络或者服务器原因,造成延迟,同时就是有可能会有人用脚本大量访问你的接口,造成资源崩溃,所以本文给大家介绍了Redis+aop实现接口防刷(幂等)的解决方案,需要的朋友可以参考下
    2024-03-03
  • 浅谈Redis 缓存的三大问题及其解决方案

    浅谈Redis 缓存的三大问题及其解决方案

    Redis 经常用于系统中的缓存,这样可以解决目前 IO 设备无法满足互联网应用海量的读写请求的问题。本文主要介绍了浅谈Redis 缓存的三大问题及其解决方案,感兴趣的可以了解一下
    2021-07-07
  • Redis 执行性能测试

    Redis 执行性能测试

    这篇文章主要介绍了Redis 执行性能测试的方法,文中讲解非常细致,帮助大家更好的理解和学习redis,感兴趣的朋友可以了解下
    2020-08-08
  • 从源码解读redis持久化

    从源码解读redis持久化

    redis的持久化也就是数据落地,对于任何一个数据系统都要考虑是不是需要数据落地。在系统崩溃或是机房掉电等的情况下,将有用的数据记录在非易失性存储器上面,防止数据丢失,以及用来系统重启时的数据恢复。
    2018-08-08
  • Redis实现分布式锁的示例代码

    Redis实现分布式锁的示例代码

    日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁,本文主要介绍了Redis实现分布式锁的示例代码,感兴趣的可以了解一下
    2023-10-10
  • Redis发布订阅和实现.NET客户端详解

    Redis发布订阅和实现.NET客户端详解

    发布订阅在应用级其作用是为了减少依赖关系,通常也叫观察者模式。主要是把耦合点单独抽离出来作为第三方,隔离易变化的发送方和接收方。下面这篇文章主要给大家介绍了关于Redis发布订阅和实现.NET客户端的相关资料,需要的朋友可以参考下
    2017-03-03
  • redis哨兵模式分布式锁实现与实践方式(redisson)

    redis哨兵模式分布式锁实现与实践方式(redisson)

    这篇文章主要介绍了redis哨兵模式分布式锁实现与实践方式(redisson),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Redis Cluster 字段模糊匹配及删除

    Redis Cluster 字段模糊匹配及删除

    在数据库内我们可以通过like关键字、%、*或者REGEX关键字进行模糊匹配。而在Redis内我们如何进行模糊匹配呢?本文就来介绍一下
    2021-05-05

最新评论