使用Redis的脚本功能实现Redis中数据简单查询
2014-03-02 17:49
956 查看
Redis不仅仅是一个简单的key-value内存数据库,Redis官网对自身的定义是“数据结构服务器”。通过用心设计各种数据结构类型的数据存储,可以实现部分的数据查询功能。因为在Redis的设计中,key是一切,对于Redis是可见的,而value对于Redis来说就是一个字节数组,Redis并不知道你的value中存储的是什么,所以要想实现比如
‘select * from users where user.location="shanghai"’
这样的查询,在Redis是没办法通过value进行比较得出结果的。但是可以通过不同的数据结构类型来做到这一点。比如如下的数据定义
其中users:1 users:2 分别定义了两个用户信息,通过Redis中的hash数据结构,而users:location:shanghai 记录了所有上海的用户id,通过集合数据结构实现。这样通过两次简单的Redis命令调用就可以实现我们上面的查询。
通过诸如以上的设计,可以实现简单的条件查询。但是这样的问题也很多,首先需要多维护一个ID索引的集合,其次对于一些复杂查询无能为力(当然也不能期望Redis实现像关系数据库那样的查询,Redis不是干这的)。
但是Redis2.6集成了Lua脚本,可以通过eval命令,直接在RedisServer环境中执行Lua脚本,并且可以在Lua脚本中调用Redis命令。其实,就是说可以让你用Lua这种脚本语言,对Redis中存储的key value进行操作,这个意义就大了,甚至可以将你们系统所需的各种业务写成一个个lua脚本,提前加载进入Redis,然后对于请求的响应,只需要调用一个个lua脚本就行。当然这样说有点夸张,但是意思就是这样的。
比如,现在我们要实现一个‘所有age大于28岁的user’这样一个查询,那么通过以下的Lua脚本就可以实现
执行脚本代码
注意,以上的代码中使用的是evalsha命令,该命令参数的不是直接Lua脚本字符串,而是提前已经加载到Redis中的函数的一个SHA索引,通过以下的代码将系统中所有需要执行的函数提前加载到Redis中,我们的系统维护一个函数哈希表,后续需要实现什么功能,就从函数表中获取对应功能的SHA索引,通过evalsha调用就行。
通过以上的方法,便可以使较为复杂的查询放到Redis中去执行,提高效率。
‘select * from users where user.location="shanghai"’
这样的查询,在Redis是没办法通过value进行比较得出结果的。但是可以通过不同的数据结构类型来做到这一点。比如如下的数据定义
users:1 {name:Jack,age:28,location:shanghai} users:2 {name:Frank,age:30,location:beijing} users:location:shanghai [1]
其中users:1 users:2 分别定义了两个用户信息,通过Redis中的hash数据结构,而users:location:shanghai 记录了所有上海的用户id,通过集合数据结构实现。这样通过两次简单的Redis命令调用就可以实现我们上面的查询。
Jedis jedis = jedisPool.getResource(); Set<String> shanghaiIDs = jedis.smembers("users:location:shanghai"); //遍历该set //... //通过hgetall获取对应的user信息 jedis.hgetAll("users:" + shanghaiIDs[0]);
通过诸如以上的设计,可以实现简单的条件查询。但是这样的问题也很多,首先需要多维护一个ID索引的集合,其次对于一些复杂查询无能为力(当然也不能期望Redis实现像关系数据库那样的查询,Redis不是干这的)。
但是Redis2.6集成了Lua脚本,可以通过eval命令,直接在RedisServer环境中执行Lua脚本,并且可以在Lua脚本中调用Redis命令。其实,就是说可以让你用Lua这种脚本语言,对Redis中存储的key value进行操作,这个意义就大了,甚至可以将你们系统所需的各种业务写成一个个lua脚本,提前加载进入Redis,然后对于请求的响应,只需要调用一个个lua脚本就行。当然这样说有点夸张,但是意思就是这样的。
比如,现在我们要实现一个‘所有age大于28岁的user’这样一个查询,那么通过以下的Lua脚本就可以实现
public static final String SCRIPT = "local resultKeys={};" + "for k,v in ipairs(KEYS) do " + " local tmp = redis.call('hget', v, 'age');" + " if tmp > ARGV[1] then " + " table.insert(resultKeys,v);" + " end;" + "end;" + "return resultKeys;";
执行脚本代码
Jedis jedis = jedisPool.getResource(); jedis.auth(auth); List<String> keys = Arrays.asList(allUserKeys); List<String> args = new ArrayList<>(); args.add("28"); List<String> resultKeys = (List<String>)jedis.evalsha(funcKey, keys, args); return resultKeys;
注意,以上的代码中使用的是evalsha命令,该命令参数的不是直接Lua脚本字符串,而是提前已经加载到Redis中的函数的一个SHA索引,通过以下的代码将系统中所有需要执行的函数提前加载到Redis中,我们的系统维护一个函数哈希表,后续需要实现什么功能,就从函数表中获取对应功能的SHA索引,通过evalsha调用就行。
String shaFuncKey = jedis.scriptLoad(SCRIPT);//加载脚本,获取sha索引 funcTable.put(funcName_age, shaFuncKey);//添加到函数表中
通过以上的方法,便可以使较为复杂的查询放到Redis中去执行,提高效率。
相关文章推荐
- 使用Redis的脚本功能实现Redis中数据简单查询
- EXTJS4 Grid Filter 插件的使用 与后台数据解析------Extjs 查询筛选功能的实现
- redis实现简单的条件查询功能
- 微信小程序实现快递查询功能(界面传值、JSON数据请求和解析、radio-group的使用...)
- redis实现简单的条件查询功能
- 使用delegate实现简单的查询功能
- 使用simple_flow 10行代码简单实现redis的复制功能
- 使用SQLite存储和查询数据的简单实现(源代码+注释)
- 用最简单的函数实现功能:判断一个int数据是否是2的x次幂(不能使用循环)。
- 使用lua脚本和jedis实现redis的hmsetnx命令,操作hash表时不覆盖原有数据
- 用C# 简单实现带查询功能的ComboBox组件
- 脚本、视图-最简单的查询表空间的使用量、剩余量的方法-by小雨
- 使用SQL Server Analysis Services数据挖掘的关联规则实现商品推荐功能(四)
- FusionCharts简单教程(七)-----使用FusionCharts实现下钻功能
- 使用json实现查询条件传回Action进行hql语句拼接查询实现在结果中查询功能在datagrid中显示查询结果
- 简单的使用Socket实现数据通信
- Redis 2.6 Lua脚本功能实现分析
- Union all的使用实现一条sql把不同表里面的数据查出来,或者按照不同的查询条件查出来的sql累加起来
- 使用avalon实现SKU组合查询功能
- unity实现简单的加密使用次数限制时间限制功能