通过lua脚本在redis中处理json数据

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。通过lua脚本在redis中处理json数据,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

在日常开发中,系统都会使用redis作为缓存来加快服务的响应,我们通常会将一个对象数据存储在redis中,对象存储通常有两种方案:一种是存储为hash结构,对象的键是属性名,值为属性值;另一种是序列化为字符串,然后存储成键值对。存储为hash结构在序列化和反序列化的时候稍微麻烦一些,涉及到键值映射关系转换,但是对于字段更新比较方便,通过redis提供的命令就可以完成。而存储为键值对,可以通过相关的类库进行序列化和反序列化操作,有时候就一行代码就能完成,但是这种方式对于更新字段比较麻烦:需要把数据取出来反序列为对象,更新属性值,再将数据反序列为字符串存储回去。整个过程虽然不是很麻烦,但是涉及到数据取存和序列化反序列化过程,在性能上还是有点损耗的,下面介绍使用lua脚本实现数据更新的方案,先看整个数据处理过程,后面在讲解

127.0.0.1:6380[1]> set test_json '{"address":"guangdong-shenzhen-nanshan","id":123,"name":"xingo"}'
OK
127.0.0.1:6380[1]> 
127.0.0.1:6380[1]> get test_json
"{\"address\":\"guangdong-shenzhen-nanshan\",\"id\":123,\"name\":\"xingo\"}"
127.0.0.1:6380[1]> 
127.0.0.1:6380[1]> eval "local json_str = redis.call('get', 'test_json'); if json_str then local json_obj = cjson.decode(json_str); json_obj.id=234; redis.call('set', 'test_json', cjson.encode(json_obj)) return 'ok' else return 'fail'; end;" 0
"ok"
127.0.0.1:6380[1]> 
127.0.0.1:6380[1]> get test_json
"{\"id\":234,\"name\":\"xingo\",\"address\":\"guangdong-shenzhen-nanshan\"}"
127.0.0.1:6380[1]> 
127.0.0.1:6380[1]> eval "local json_str = redis.call('get', 'test_json'); if json_str then local json_obj = cjson.decode(json_str); json_obj.id=tonumber(ARGV[1]); redis.call('set', 'test_json', cjson.encode(json_obj)) return 'ok' else return 'fail'; end;" 0 333
"ok"
127.0.0.1:6380[1]> 
127.0.0.1:6380[1]> get test_json
"{\"id\":333,\"name\":\"xingo\",\"address\":\"guangdong-shenzhen-nanshan\"}"
127.0.0.1:6380[1]> 

首先,我们向redis中存入一个键值对数据,值为一个json字符串。

{
    "address": "guangdong-shenzhen-nanshan",
    "id": 123,
    "name": "xingo"
}

在这个对象中,我们要更新id字段值,将字段值从123修改为234,这里使用了lua脚本:

eval "local json_str = redis.call('get', 'test_json'); if json_str then local json_obj = cjson.decode(json_str); json_obj.id=234; redis.call('set', 'test_json', cjson.encode(json_obj)) return 'ok' else return 'fail'; end;" 0

格式化后代码如下:

local json_str = redis.call('get', 'test_json'); 
if json_str then 
  local json_obj = cjson.decode(json_str); 
  json_obj.id=234; 
  redis.call('set', 'test_json', cjson.encode(json_obj)); 
  return 'ok';
else 
  return 'fail'; 
end;

处理过程是:先获取到redis中存储的数据,然后使用cjson将字符串序列化为json对象,调整对象的属性值,再将对象序列化为字符串存储回去,整个过程都是在redis服务中完成,没有了redis和应用服务器之间来回的数据传输。
第二种方式是将修改的值通过外部传过去:

eval "local json_str = redis.call('get', 'test_json'); if json_str then local json_obj = cjson.decode(json_str); json_obj.id=tonumber(ARGV[1]); redis.call('set', 'test_json', cjson.encode(json_obj)) return 'ok' else return 'fail'; end;" 0 333

运行脚本后面跟了两个参数:第一个参数表示键数量,这里没有键传递过去,所以置数为0,第二个参数是要修改的值,注意在lua中使用了tonumber()函数,它是将参数转换为数值类型,否则更新后的字段类型为字符串。
redis中使用lua脚本非常棒,可以完成一些简单的处理逻辑,不必将数据在redis服务器和应用服务之间来回传递。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181826.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!