Java+Redis+Lua

Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下:

1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。
2.原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。
3.复用:客户端发送的脚本会永久存储在Redis中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。

高并发 原子 交互
1 redis执行可以保证lua脚本的执行的原子性
2 减少网络延迟

/**
 * [times description]
 * @type {[type]}
   下标从1开始
 */
local times = redis.call('incr',KEYS[1])

if times == 1 then
    redis.call('expire',KEYS[1], ARGV[1])
end

if times > tonumber(ARGV[2]) then
    return 0
end
return 1

redis-cli --eval ratelimiting.lua rate.limitingl:127.0.0.1 , 10 3
                                        KEYS                 ARGV

--eval参数是告诉redis-cli读取并运行后面的Lua脚本,ratelimiting.lua是脚本的位置,
后面跟着是传给Lua脚本的参数。其中","前的rate.limiting:127.0.0.1是要操作的键,可以再脚本中用KEYS[1]获取,
","后面的10和3是参数,在脚本中能够使用ARGV[1]和ARGV[2]获得。注:","两边的空格不能省略,否则会出错。

*********************************分布式限流器*******************************************************

local tokens_key = KEYS[1]
local timestamp_key = KEYS[2]
local rate = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])
local fill_time = capacity/rate
local ttl = math.floor(fill_time*2)
local last_tokens = tonumber(redis.call("get", tokens_key))
if last_tokens == nil then
  last_tokens = capacity
end
local last_refreshed = tonumber(redis.call("get", timestamp_key))
if last_refreshed == nil then
  last_refreshed = 0
end
local delta = math.max(0, now-last_refreshed)
local filled_tokens = math.min(capacity, last_tokens+(delta*rate))
local allowed = filled_tokens >= requested
local new_tokens = filled_tokens
local allowed_num = 0
if allowed then
  new_tokens = filled_tokens - requested
  allowed_num = 1
end
redis.call("setex", tokens_key, ttl, new_tokens)
redis.call("setex", timestamp_key, ttl, now)
return { allowed_num, new_tokens }

String prefix = "rate_limiter.{" + key;
String tokenKey = prefix + "}.tokens";
String timestampKey = prefix + "}.timestamp";
return Arrays.asList(tokenKey, timestampKey);

int burstCapacity = replenishRate;
List<String> keys = getKeys(key);
List<String> scriptArgs = Arrays.asList(String.valueOf(replenishRate), String.valueOf(burstCapacity),
        String.valueOf(System.currentTimeMillis() / 1000L), "1");
Object reply = jedisCluster.eval(rateLimiterScript, keys, scriptArgs);
if (LOGGER.isDebugEnabled()) {
    LOGGER.debug("Redis Response=" + reply);
}
if (reply != null && List.class.isAssignableFrom(reply.getClass())) {
    List list = List.class.cast(reply);
    if (CollectionUtils.isNotEmpty(list)) {
        Object item;
        return NumberUtils.toInt((item = list.get(0)) != null ? item.toString() : null, -1) > 0;
    }
}

***********************************************************************************************************************************************

Redis+Lua+Java相关推荐

  1. Java并发:分布式应用限流 Redis + Lua 实践

    任何限流都不是漫无目的的,也不是一个开关就可以解决的问题,常用的限流算法有:令牌桶,漏桶.在之前的文章中,也讲到过,但是那是基于单机场景来写. 之前文章:接口限流算法:漏桶算法&令牌桶算法 然 ...

  2. 高并发-【抢红包案例】之四:使用Redis+Lua脚本实现抢红包并异步持久化到数据库

    文章目录 导读 概述 实现步骤 注解方式配置 Redis lua脚本和异步持久化功能的开发 Service层添加Redis抢红包的逻辑 Controller层新增路由方法 构造模拟数据,测试 代码 总 ...

  3. redis+lua实现分布式限流

    前言 之前我们谈到的限流解决方案中提到了在分布式环境下,可以使用redis结合lua进行限流,与网关层限流不同的是,基于Redis+Lua的分布式限流属于服务端限流 使用redis做限流原因 在前面的 ...

  4. Redis实现计数器---接口防刷---升级版(Redis+Lua)

    [前言] Cash Loan(一):Redis实现计数器---接口防刷  中介绍了项目中应用redis来做计数器的实现过程,最近自己看了些关于Redis实现分布式锁的代码后,发现在Redis分布式锁中 ...

  5. redis+lua脚本

    1.lua+java 第一种形式直接在代码中 @Autowiredprivate RedisTemplate<String,String> redisTemplate;@PostMappi ...

  6. 【干货】Redis在Java开发中的基本使用和巧妙用法

    Redis是一款高性能的内存数据结构存储系统,能够支持多种数据结构类型,如字符串.哈希.列表.集合.有序集合等,也能够支持高级功能,如事务.发布/订阅.Lua脚本等,具有高可用性.高并发性和可扩展性的 ...

  7. ratelimit+redis+lua对接口限流

    背景:为防止接口QPS太大而造成系统运行卡顿的现象,在这儿以ratelimit+redis+lua对系统接口做了个限流.当时也考虑过使用其他的限流方法,比如微服务生态中使用的sentinel中间件,但 ...

  8. 一网打尽Redis Lua脚本并发原子组合操作

    1. 前言 Redis 是高性能的 KV 内存数据库,除了做缓存中间件的基本作用外还有很多用途,比如胖哥以前分享的Redis GEO 地理位置信息计算.Redis 提供了丰富的命令来供我们使用以实现一 ...

  9. Redis Lua脚本的详细介绍以及使用入门

    Redis Lua脚本的详细介绍以及使用入门. 文章目录 Redis Lua脚本的引入 开源软件的可扩展性 Redis的扩展性脚本 Redis Lua脚本的基本使用 通过EVAL命令执行Lua脚本 通 ...

最新文章

  1. named 客户端无法解析_解析天联高级版客户端无法访问用友U8问题
  2. 【MATLAB】符号数学计算(六):符号函数的操作
  3. 图卷积和消息传递理论的可视化详解
  4. React.js 小书 Lesson14 - 实战分析:评论功能(一)
  5. Centos7升级最新git
  6. NSOperation队列实实现多线程
  7. 为传递函数自动设定PID参数——pidtune学习笔记
  8. 莫烦nlp-GPT 单向语言模型
  9. 【算法与数据结构】—— 大数运算
  10. html5读取运动传感器,一种基于六轴传感器的脚步运动识别方法与流程
  11. MATLAB编写m函数理解 y=f(g(x))*h(x)
  12. 用python对股票期货做时序分析
  13. java long初始化_java中long类型的变量想要初始化其值为空,要怎么实现?
  14. net::ERR_INCOMPLETE_CHUNKED_ENCODING 200
  15. 两个主要问题将决定微信支付成败
  16. 景联文智能标注平台将数据处理效率提升十倍以上!数据精准度最高可达99%
  17. 使用ARCHPR明文攻击爆破压缩包
  18. python123一元二次方程_python练习题1-一元二次方程解
  19. 百度 谷歌分页_利用SEO来提高Google收录PR值和百度网站权重
  20. 受疫情影响,突遭上交所中止发行上市审核!亏损持续扩大的极飞科技,还能让农业智慧起来么?...

热门文章

  1. 【沉浸式腾讯云服务器部署安装docker】
  2. android蓝牙打印机打印图片,如何使用打印机(通过蓝牙打印)从Android设备打印图像和一些数据?...
  3. 主数据管理(MDM)的一些概念
  4. 一个好用的 txt 小说阅读器(自用好用,目前没发现替代款)
  5. 统计学与计算机考研学校排名,2018统计学考研院校排名
  6. VLDB 2022最佳研究论文:克服通信挑战,新框架SANCUS实现GNN高效训练
  7. prism 计算 Spearman相关
  8. 微信废品回收小程序开发上门回收废品小程序开发
  9. Mathematica解一个精巧的差分方程
  10. python中的抽象类