在日常开发中,系统都会使用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进行投诉反馈,一经查实,立即删除!