日常开发中,系统都会使用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://blog.csdn.net/dream_xin2013/article/details/134719323

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_22606.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注