Redis中使用Lua脚本(续)- Lua-cjson开源库的安装和使用

在Redis的lua脚本编写中,我们可能会用到json的序列化和反序列化。

Json序列化:

-- RedisLuaCjsonEncode.lua文件
local userName = ARGV[1];

local userObject = {
            name = userName,
            age = 14,
            address = 'China'
        }

local userJson = cjson.encode(userObject);

if redis.call('set', KEYS[1], userJson) == 0
then
        return -1
else
        return userJson
end

Json反序列化:

-- RedisLuaCjsonDecode.lua文件
local userInfo = redis.call('get', KEYS[1])

local userJson = cjson.decode(userInfo)

return userJson.name;

上面这两段代码是笔者写出的两个Json序列化和反序列化的小例子,相信看过前两篇文章的读者都能读懂什么意思。有兴趣的话,可以自行执行以下命令看一下效果:

## 运行RedisLuaCjsonEncode.lua文件,向redis中插入一条序列化成json格式的字符串
[root@vm01 learn_lua]# redis-cli -a 123456 --eval RedisLuaCjsonEncode.lua userInfo , zhangsan

## 运行RedisLuaCjsonDecode.lua文件,从redis中一条json格式的字符串,并将其反序列化,并取出其中的name字段的值。
[root@vm01 learn_lua]# redis-cli -a 123456 --eval RedisLuaCjsonDecode.lua userInfo

问题

但如果有兴趣在读者想编写一段和Redis无关的使用 cjson 的纯 Lua 脚本,想要运行,会发现:我跳!运行不了。会报以下错误:

[root@vm01 lua_cjson]# lua cjson_demo.lua 
lua: cjson_demo.lua:1: module 'cjson' not found:
	no field package.preload['cjson']
	no file './cjson.lua'
	no file '/usr/share/lua/5.1/cjson.lua'
	no file '/usr/share/lua/5.1/cjson/init.lua'
	no file '/usr/lib64/lua/5.1/cjson.lua'
	no file '/usr/lib64/lua/5.1/cjson/init.lua'
	no file './cjson.so'
	no file '/usr/lib64/lua/5.1/cjson.so'
	no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
	[C]: in function 'require'
	cjson_demo.lua:1: in main chunk
	[C]: ?

原因

问题原因: lua-cjson 是一个简单小巧的开源动态库,可被 Lua 脚本 require 加载在 Lua 中通过一系列的 lua-cjson API 调用完成 Lua 值与 Json 值的相互转换(编码及解码)。 即:原生 Lua 并不支持 lua-cjson,需要我们手动将cjson编译到 Lua 环境方可使用。

Redis中使用cjson 的 lua脚本可以直接执行,而不报错。实际是Redis客户端将脚本传输到了Redis服务端,后期 Lua 的脚本都在服务端运行。而Redis服务端,已经在Redis编译安装的过程中,将 cjson开源库以及Lua环境 都已编译进去 不信,您在Redis服务端看:

## 看查询结果的后两行
[root@vm01 lua_cjson]# sudo find / -name lua
/usr/bin/lua
/usr/lib64/lua
/usr/local/lib/lua
/usr/local/share/lua
/usr/local/lua-cjson-2.1.0/lua
/usr/share/lua
/usr/share/locale/lua
/opt/soft/redis/redis-5.0.5/deps/lua
/opt/soft/redis/redis-5.0.5/deps/lua/src/lua

解决方案

那就想办法安装 lua-cjson 呗。在网上找了很多 lua-cjson 的安装方案,发现直接安装,在make编译时总会报错,就是 lua.hlauxlib.h两个文件找不到。

[root@vm01 lua-cjson-2.1.0]# make
cc -c -O3 -Wall -pedantic -DNDEBUG  -I/usr/local/include/luajit-2.0/include -fpic -o lua_cjson.o lua_cjson.c
lua_cjson.c:43:17: error: lua.h: No such file or directory
lua_cjson.c:44:21: error: lauxlib.h: No such file or directory

其实是因为 lua-cjson 还要依赖 lua 环境。我们需要安装 LuaJit这么一个Lua代码解析器,后面可以使用luajit命令执行 cjson 的脚本。

安装步骤:

  1. 准备lua-cjson-2.1.0.tar.gz 和 LuaJIT-2.0.5.zip 两个安装包
  2. 安装LuaJIT
## step1. 解压 LuaJIT-2.0.5.zip 到 /usr/local/ 目录
[root@vm11 ~]# unzip LuaJIT-2.0.5.zip -d /usr/local/
[root@vm11 ~]# cd /usr/local/LuaJIT-2.0.5/
[root@vm11 LuaJIT-2.0.5]# pwd
/usr/local/LuaJIT-2.0.5

## step2. 在/usr/local/LuaJIT-2.0.5/目录下执行 make && make install 命令
##        看到最后一行成功安装即可
[root@vm11 LuaJIT-2.0.5]# make && make install
==== Building LuaJIT 2.0.5 ====
make -C src
make[1]: Entering directory `/usr/local/LuaJIT-2.0.5/src'
make[1]: Nothing to be done for `default'.
make[1]: Leaving directory `/usr/local/LuaJIT-2.0.5/src'
==== Successfully built LuaJIT 2.0.5 ====
==== Installing LuaJIT 2.0.5 to /usr/local ====
mkdir -p /usr/local/bin /usr/local/lib /usr/local/include/luajit-2.0 /usr/local/share/man/man1 /usr/local/lib/pkgconfig /usr/local/share/luajit-2.0.5/jit /usr/local/share/lua/5.1 /usr/local/lib/lua/5.1
cd src && install -m 0755 luajit /usr/local/bin/luajit-2.0.5
cd src && test -f libluajit.a && install -m 0644 libluajit.a /usr/local/lib/libluajit-5.1.a || :
rm -f /usr/local/bin/luajit /usr/local/lib/libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so /usr/local/lib/libluajit-5.1.so.2
cd src && test -f libluajit.so && \
	  install -m 0755 libluajit.so /usr/local/lib/libluajit-5.1.so.2.0.5 && \
	  ldconfig -n /usr/local/lib && \
	  ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so && \
	  ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so.2 || :
cd etc && install -m 0644 luajit.1 /usr/local/share/man/man1
cd etc && sed -e "s|^prefix=.*|prefix=/usr/local|" -e "s|^multilib=.*|multilib=lib|" luajit.pc > luajit.pc.tmp && \
	  install -m 0644 luajit.pc.tmp /usr/local/lib/pkgconfig/luajit.pc && \
	  rm -f luajit.pc.tmp
cd src && install -m 0644 lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h /usr/local/include/luajit-2.0
cd src/jit && install -m 0644 bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua dis_arm.lua dis_ppc.lua dis_mips.lua dis_mipsel.lua bcsave.lua vmdef.lua /usr/local/share/luajit-2.0.5/jit
ln -sf luajit-2.0.5 /usr/local/bin/luajit
==== Successfully installed LuaJIT 2.0.5 to /usr/local ====

  1. 安装lua-cjson
  • 步骤1: 解压 lua-cjson-2.1.0.tar.gz 到 /usr/local/ 目录
[root@vm11 ~]# tar -xzf lua-cjson-2.1.0.tar.gz -C /usr/local/
[root@vm11 ~]# cd /usr/local/lua-cjson-2.1.0
[root@vm11 lua-cjson-2.1.0]# pwd
/usr/local/lua-cjson-2.1.0
  • 步骤2:修改 /usr/local/lua-cjson-2.1.0/Makefile 文件

    将 LUA_INCLUDE_DIR = $(PREFIX)/include

    修改为:LUA_INCLUDE_DIR = /usr/local/include/luajit-2.0

    Makefile文件的修改

  • 步骤3:执行 make && make install 命令,看到如下提示,则证明安装成功

[root@vm11 lua-cjson-2.1.0]# make && make install
cc -c -O3 -Wall -pedantic -DNDEBUG  -I/usr/local/include/luajit-2.0 -fpic -o lua_cjson.o lua_cjson.c
cc -c -O3 -Wall -pedantic -DNDEBUG  -I/usr/local/include/luajit-2.0 -fpic -o strbuf.o strbuf.c
cc -c -O3 -Wall -pedantic -DNDEBUG  -I/usr/local/include/luajit-2.0 -fpic -o fpconv.o fpconv.c
cc  -shared -o cjson.so lua_cjson.o strbuf.o fpconv.o
mkdir -p //usr/local/lib/lua/5.1
cp cjson.so //usr/local/lib/lua/5.1
chmod 755 //usr/local/lib/lua/5.1/cjson.so

  • 步骤4:使用 luajit 命令执行相关lua脚本
[root@vm11 ~]# luajit cjson_demo.lua 
true
[1,2,3,4,5,6]
6.66
"I am test1280"
{"addr":"BeiJing","tel":"1569989xxxx","age":24,"name":"Jiang","email":"1569989xxxx@126.com"}

cjson_demo.lua脚本如下:

local cjson = require "cjson"

-- 创建实例
local cjson2 = cjson.new()

-- 布尔类型
local lua_bool = true
print(cjson2.encode(lua_bool))

-- 数组类型
local lua_array = {1, 2, 3, 4, 5, 6}
print(cjson2.encode(lua_array))

-- 数值类型
local lua_number = 6.66
print(cjson2.encode(lua_number))

-- 字符串类型
local lua_string = "I am test1280"
print(cjson2.encode(lua_string))

-- 对象类型
local lua_object = {
    ["name"] = "Jiang",
    ["age"] = 24,
    ["addr"] = "BeiJing",
    ["email"] = "1569989xxxx@126.com",
    ["tel"] = "1569989xxxx"
}
print(cjson2.encode(lua_object))

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐