java操作lua脚本实例

前言

在上一篇文章 Redis中使用Lua脚本来实现并发下的原子操作 中我对Lua语言的一些简单的语法及其在Redis中的操作进行了介绍,但是在Java开发中我们还需要进一步的学习才能使这种技术落地。今天就结合Spring Data Redis这个我们经常使用的Redis开发组件来实际尝试一下Lua 脚本。

Lua 实现抽奖

模拟一个抽奖场景,从奖池中进行随机抽奖。规则如下:

中奖的人只能从奖池中抽取。

每个人只能中奖一次。

中奖总人数不能超过奖项的设置数。

生成中奖名单。

规则有了,我们先来分析如何使用Redis实现。Redis提供了SET集合,这种集合有点类似Java中的Set,放无重复的元素而且是无序的,可以满足随机性和奖池候选人的唯一性。同时它还提供了很多操作来满足抽奖的需要。接下来我们进行一一演示。

Redis SET 的一些操作。

基于篇幅我这里只演示一些抽奖可以用的上的Redis操作。

SET添加元素。

添加一个到多个元素,使用SADD命令往lottery中添加多个元素来模拟往奖池中加人。

127.0.0.1:6379> sadd lottery u1 u2 u3 u4 u5 u6 u7

(integer) 7

127.0.0.1:6379> sadd lottery u1

(integer) 0

如果没有lottey这个key就新建该key,有就直接添加并返回成功添加的元素个数。同时你会发现如果集合中存在了添加的元素是无法被再次添加的。

查询集合中的元素

查询所有元素通过SMEMBERS命令。

127.0.0.1:6379> smembers lottery

1) "u2"

2) "u7"

3) "u6"

4) "u4"

5) "u1"

6) "u3"

7) "u5"

随机抽取N个元素

SET集合有两个命令都能满足随机抽取N个元素,分别是SPOP和SRANDMEMBER,它们的区别在于SPOP会将选中的元素从原来的集合中剔除,而SRANDMEMBER不会。我们分别来使用这两个命令来随机从lottery中抽取2个元素来看看。

127.0.0.1:6379> srandmember lottery 2

1) "u2"

2) "u4"

127.0.0.1:6379> smembers lottery

1) "u2"

2) "u7"

3) "u6"

4) "u4"

5) "u1"

6) "u3"

7) "u5"

127.0.0.1:6379> spop lottery 2

1) "u3"

2) "u5"

127.0.0.1:6379> smembers lottery

1) "u2"

2) "u7"

3) "u6"

4) "u4"

5) "u1"

就lottery来说,如果你的奖池人数一次性添加的不再增加使用SPOP;如果动态添加,为了保证中奖的人不再次进入奖池应该使用SRANDMEMBER。

抽奖脚本

接下来就是抽奖脚本,我们从lottery中抽出特定的人放入中奖名单,另外一个集合chosen中。

按道理Redis抽奖脚本在Lua中应该是这样的:

function draw(KEYS,ARGV)

-- 抽奖逻辑 函数体

end

但是我们只需要编写抽奖逻辑的函数体,然后把函数体写入.lua文件中,在Maven项目中放入META-INF/scripts文件夹中,如图所示:

Redis结合Lua脚本实现抽奖逻辑

约定lua脚本所在的目录

draw.lua的逻辑为:

--- 简单抽奖脚本 return 结果最终传递给Java 应用

-- 奖池的key

local lottery_key = KEYS[1]

-- 中奖名单的key

local chosen_key = KEYS[2]

-- 预定抽奖的人数

local lottery_count = ARGV[1]

-- 如果预定抽奖的人数大于0才开始抽奖

if tonumber(lottery_count) > 0 then

-- 奖池中抽奖 返回的是 被抽中的人组成的数组

local chosen_list = redis.call('SRANDMEMBER', lottery_key, lottery_count);

-- 将抽中的人添加到中奖名单中 返回中奖的人数

if chosen_list then

return redis.call('SADD', chosen_key, unpack(chosen_list))

else

return 0

end

else

return 0

end

对应的 Java 代码

Spring Data Redis中的RedisTemplate提供了execute方法来执行Lua脚本,这里我选择使用下面的方法:@Override

public T execute(RedisScript script, List keys, Object... args) {

return scriptExecutor.execute(script, keys, args);

}

RedisScript Redis脚本的抽象,用来加载脚本。

keys对应Lua脚本中的KEYS,用来传入Redis的KEY,在Lua脚本中可以通过 KEYS[索引]来取值,例如取第一个值KEYS[1]。

args用来向Lua脚本传递其它的参数,在Lua脚本中可以通过ARGV[索引]来取值。

我们利用draw.lua脚本从Redis的lottery集合中抽取5名幸运者并把他们添加到中奖名单chosen集合中:

RedisScript redisScript = RedisScript.of(new ClassPathResource("META-INF/scripts/draw.lua"), Long.class);

Long chosenCount = stringRedisTemplate.execute(redisScript, Arrays.asList("lottery", "chosen"), Collections.singletonList("5"));

构造RedisScript对象时务必指定返回值对象以保证Lua脚本对象和Java的返回值能对应上,

否则将出现异常。参见org.springframework.data.redis.connection.ReturnType枚举。

总结

到此Redis利用Lua脚本进行抽奖的整套逻辑就完成了。Lua脚本在Redis中通常是为了保证高并发下的原子性,当你考虑是否需要使用它时应该充分考虑你的业务和架构是否适合使用它。

来源:oschina

链接:https://my.oschina.net/randomobject/blog/4685552

lua脚本java_java操作lua脚本相关推荐

  1. wincc按钮控制的vb脚本_VB操作wincc脚本心得.docx

    VB操作wincc脚本心得 Vbs 操作wincc画面脚本总结 一: 不使用变量单纯的操作界面 1.操作某个画面中控件的属性 如 Home1.Pdl(总窗体) 下的 画面窗口2(画面窗口) Sub O ...

  2. wincc按钮控制的vb脚本_VB操作wincc脚本心得

    1.Vbs 操作wincc画面脚本总结一: 不使用变量单纯的操作界面1.操作某个画面中控件的属性 如 Home1.Pdl(总窗体) 下的 画面窗口2(画面窗口)Sub OnClick(ByVal It ...

  3. Redis Lua 脚本常用操作总结及实现 CAS 操作

    一.什么是 Lua ?   Lua 是一个小巧的脚本语言.它是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个由 R ...

  4. lua脚本之lua语言简介以及lua的安装

    本博主不擅于进行文字创作,所以,相当一部分文字皆复制于其他博文.还希望能够得到谅解.  一.Lua语言简介 Lua是一个免费的开源软件,可以免费用于科研及商业.Lua具有一个专家团队在维护和升级,其设 ...

  5. JavaScript、Lua语言基础、电脑脚本、手机免ROOT免越狱脚本开发免费视频教程

    JavaScript基础教程:https://www.bilibili.com/video/BV1YW411T7GX Lua基础教程:https://www.bilibili.com/video/BV ...

  6. Lua脚本编程:Lua语言入门

    Lua是一门简单而强大的语言,其本身强大的扩展性使得这门语言在游戏设计等领域发挥着重要的作用.博主曾在Unity3D中使用过这门语言,并且针对Lua和Unity.C++等方面的内容进行了学习和讨论.最 ...

  7. lua怎么嵌入php,Lua教程(一):在C++中嵌入Lua脚本

    本系列教程主要介绍如何在C/C++程序里面嵌入Lua脚本,我打算从以下几个方面来介绍: 1.如何在C/C++里面嵌入Lua脚本 2.Lua访问C/C++数据结构(这里面要介绍类,结构体,函数,变量,枚 ...

  8. 【Lua编程基础】Lua环境安装及lua脚本编写

    欢迎加入Unity业内qq交流群:956187480 qq扫描二维码加群 Github 下载地址:https://github.com/rjpcomputing/luaforwindows/relea ...

  9. php io操作,lua 的io操作,非常详细

    Lua 标准库 - 输入输出处理(input and output facilities) I/O库提供两种不同的方式进行文件处理 1.io表调用方式:使用io表,io.open将返回指定文件的描述, ...

  10. Lua教程-1:C/C++操作Lua数组和字符串

    Lua教程-1:C/C++操作Lua数组和字符串 C/C++操作Lua数组 Lua数组Overview 通用Table操作方法 专门的数组操作方法 C/C++操作Lua字符串 基本字符串操作 格式化输 ...

最新文章

  1. java dump分析工具_java性能分析与常用工具
  2. 2017北京云栖大会:云效企业级协同研发专场议题揭秘!
  3. php zend框架入门,Zend Framework 入门——快速上手
  4. [转]十天学习PHP之第一天(PHP)----基础知识
  5. 图神经网络代码_第一篇:图神经网络(GNN)计算框架绪论
  6. presto-server-0.198集群安装
  7. 进程间关系和守护进程
  8. [css] 为什么float会导致父元素塌陷
  9. 软件开发丨关于软件重构的灵魂四问
  10. idea+SpringBoot+Mybatis+Mysql环境搭建
  11. 燕山大学计算机考研专硕专业课,燕山大学(专业学位)计算机技术研究生考试科目和考研参考书目...
  12. http和webservice接口区别
  13. linux服务器 授权命令,linux的Sudo/su授权命令详解
  14. 浅谈人工智能搜索技术论文
  15. Win8 MSDN 简中/繁中/英文正式版下载(微软官方原版)
  16. 电子电路设计——multisum中快捷设置555定时器
  17. acwing-2240. 餐饮(最大流+拆点)
  18. 使用MODBUS转PROFINET智能网关实现与多个温控器数据读写
  19. 购物页面点叉号二维码隐藏的做法
  20. SYSML语言OMG认证考试经验分享

热门文章

  1. 生物医学传感器实验装置
  2. CCS 8.00 软件中视窗的应用
  3. Neo4j 下载安装
  4. 代码开源为黑客敞开了大门
  5. linux udp数据包发送间隔,如何每1 ms发送一次UDP数据包?
  6. 软件测试方法——黑盒测试
  7. Java游戏项目之推箱子
  8. JavaWeb和WebGIS学习笔记(七)——MapGuide Open Source安装、配置以及MapGuide Maestro发布地图——超详细!目前最保姆级的MapGuide上手教程!
  9. c语言题库打不开软件,编写题库程序_想把一个老师编的做题练习的软件里面的题库弄出来貌似是用VB60编写的要怎么做啊_淘题吧...
  10. 查看宽带虚拟拨号PPPoE的上网口令密码