go redigo执行lua脚本 实现原子操作

栏目: Lua · 发布时间: 7年前

内容简介:Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua可以在很多地方使用比如游戏开发、独立应用脚本、Web应用脚本、扩招和数据库插件等等。今天记录的是在redis中执行lua脚本实现原子操作。如果不是专业些lua脚本我们可以看下在redis中使用lua的场景很多,这次记录的使用场景是:开发需要用到redis记录一个有顺序的数据,但是又不能重复添加。所以准备先用一个set记录list存在的值用来判断是否重复(set

Lua

Lua 是一种轻量小巧的脚本语言,用标准 C语言 编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Lua可以在很多地方使用比如游戏开发、独立应用脚本、Web应用脚本、扩招和数据库插件等等。今天记录的是在 redis 中执行 lua 脚本实现原子操作。如果不是专业些lua脚本我们可以看下 菜鸟联盟 的简单教程,已经够我们平时简单使用了。

使用场景

在redis中使用lua的场景很多,这次记录的使用场景是:开发需要用到redis记录一个有顺序的数据,但是又不能重复添加。所以准备先用一个set记录list存在的值用来判断是否重复(set在redis中是不允许重复的),再用list数据类型进行保存。但是如果分开执行这些语句在高并发的情况下可能会遇到问题,在某种情况下可能会加入重复数据。这个时候就可以用到lua脚本来原子的执行这两条语句。

代码

package main

import (
    "fmt"
    "time"
    "github.com/gomodule/redigo/redis"
)

const(
    SCRIPT_INCR = `
local num = redis.call('sismember', KEYS[1], ARGV[1])
if num > 0
then
    return -1
else
    redis.call('sadd',KEYS[1],ARGV[1])
    return redis.call('lpush',KEYS[2],ARGV[1])
end
`
)

func init()(){
    initRedis()
}

var redisCoon redis.Conn

//初始化redis连接,redis在本地 docker 中运行
func initRedis()(){
    redisClient := &redis.Pool{
        // 最大空闲链接
        MaxIdle: 10,
        // 最大激活链接
        MaxActive: 10,
        // 最大空闲链接等待时间
        IdleTimeout: 5 * time.Second,
        Dial: func() (redis.Conn, error) {
            rc, err := redis.Dial("tcp", "127.0.0.1:6379")
            if err != nil {
                return nil, err
            }
            rc.Do("SELECT", 0)
            fmt.Println("USE DB", 0)

            return rc, nil
        },
    }
    redisCoon = redisClient.Get()
}

func AddCode(id,code string)(){
    lua := redis.NewScript(2, SCRIPT_INCR)
    in,err :=redis.Int(lua.Do(redisCoon, "u:"+id, "u:set:"+id, code))
    fmt.Println(in,"--",err)
}

func main() {
    AddCode("1","60001")
    AddCode("1","60001")
    AddCode("1","60002")
}

//执行结果
//1 -- <nil>
//-1 -- <nil>
//2 -- <nil>
//redis查询结果
//127.0.0.1:6379> lrange u:set:1 0 -1
//1) "60002"
//2) "60001"
//127.0.0.1:6379> smembers u:1
//1) "60001"
//2) "60002"

go 中使用的是redigo的包来操作redis。redigo自带redis连接池可以方便的定义做大连接数,最大空闲数,最大空闲连接等和超时时间等。我们可以很方便控制这些参数也可以很方便的执行lua脚本。执行步骤如下:

  1. 第一步需要新建一个脚本对象,第一个参数为keycount,标志你的lua脚本参数中key的个数 第二个参数为脚本字符串
  2. 第二步 执行这个脚本,把定义时候的2个key传递过去,之后的参数为脚本中的ARGV
  3. 第三部 使用redis.Int 获取返回值,如果没有返回值直接使用Do即可

脚本接受一个set的key和一个list的key 先判断set是否存在保证没有重复。之后再去往list中添加,避免高并发中加入重复数据。如果已经存在则返回-1表示。如果没有则往set,list中都添加值。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Foundations of PEAR

Foundations of PEAR

Good, Nathan A./ Kent, Allan / Springer-Verlag New York Inc / 2006-11 / $ 50.84

PEAR, the PHP Extension and Application Repository, is a bountiful resource for any PHP developer. Within its confines lie the tools that you need to do your job more quickly and efficiently. You need......一起来看看 《Foundations of PEAR》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具