6.3 R利剑NoSQL 之 Redis
问题
R如何连接Redis?
引言
Redis是常用的基于内存的Key-Value数据库,比Memcache更先进,支持多种数据结构,高效,快速。用Redis可以很轻松地解决高并发的数据访问问题,作为时时监控信号处理也非常不错。本节将介绍rredis,让R程序轻松连接Redis。
6.3.1 Redis环境准备
首先环境准备,这里我选择了Linux Ubuntu操作系统,大家可以根据自己的使用习惯选择顺手的Linux。
- Linux: Ubuntu 12.04.2 LTS 64bit server
- MongoDB: 2.2.12
- IP: 192.168.1.101
关于Redis的安装和配置,请参考附录C。查看Redis服务器环境。使用/etc/init.d/redis-server命令,启动redis-server, 默认端口:port=6379
~ /etc/init.d/redis-server start # 启动redis
Starting redis-server: redis-server.
~ ps -aux|grep redis # 查看系统进程
redis 20128 0.0 0.0 10676 1428 ? Ss 16:39 0:00 /usr/bin/redis-server /etc/redis/redis.conf
~ cat /var/log/redis/redis-server.log # 查看启动日志
[20128] 14 Apr 16:39:43 * Server started, Redis version 2.2.12
[20128] 14 Apr 16:39:43 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
[20128] 14 Apr 16:39:43 * The server is now ready to accept connections on port 6379
使用Redis的命令行客户端程序redis-cli,打开Redis Shell。Redis Shell的简单操作有插入一条记录和查询记录。
~ redis-cli # 打开Redis Shell
redis 127.0.0.1:6379> help set # 查看set命令的用法
SET key value
summary: Set the string value of a key
since: 0.07
group: string
redis 127.0.0.1:6379> set a 178 # 插入一条记录 key = a, value = 178
OK
redis 127.0.0.1:6379> get a # 查看记录
"178"
接下来,我们使用R语言的Redis客户端rredis远程访问Redis服务器进行测试。
6.3.2 rredis函数库
rredis是R语言访问Redis数据库的客户端通信接口程序,提供了100个函数,对应Redis的各种操作。虽然rredis的函数很多,但是用法都是比较简单的,对R语言支持足够灵活,代码也比较简洁。我们不一一列出100个rredis函数的,仅挑选一些常用的函数介绍。感兴趣的读者可以从rredis的官方文档中,找到所有的函数。
redisConnect() , redisClose() #建立连接,关闭连接
清空当前/所有数据库数据
redisFlushDB() , redisFlushAll() #清空当前/所有数据库数据
redisKeys(), redisDBSize() #列出所有KEY值,KEY的数量
redisSelect(0) # 选择切换数据库:0是默认数据库
redisSet('x',runif(5)), redisMSet(list(x=pi,y=runif(5),z=sqrt(2))) #插入string对象,批量插入
redisGet('x'), redisMGet(c('x','y','z')) #读取string对象,批量读取
redisDelete('x') #删除对象
redisLPush('a',1), redisRPush('a','A') #左边插入数组对象,右边插入数组对象
redisLPop('a'), redisRPop('a') #左边弹出一个数组对象, 右边弹出一个数组对象,
redisLRange('a',0,-1) # 从左边显示数组对象列表
redisSAdd('A',runif(2)) #插入set类型对象
redisSCard('A'), redisSMembers('A') #显示set对象有几个元素,列表显示set对象元素
# 显示两个set对象的差集、交集、和并集
redisSDiff(c('A','B')),redisSInter(c('A','B')),redisSUnion(c('A','B'))
6.3.3 rredis基本使用操作
R语言的客户端环境是:
- Win7 64bit
- R: 3.0.1 x86_64-w64-mingw32/x64 b4bit
我将按照下面的5个操作类别进行介绍
- redis的基本操作:建立连接,切换数据库,列表显示所有KEY值,清空当前数据库数据,清空所有数据库数据,关闭链接
- string类型操作:插入,读取,删除,插入并设置过期时间,批量操作
- list类型操作:插入,读取,弹出
- set类型操作:插入,读取,交集,差集,并集
- rredis与redis-cli的交互操作
1. redis的基本操作:
首先,要安装rredis类库,并加载类库。
> install.packages("rredis") # 安装rredis
> library(rredis) # 加载rredis类库
通过redisConnect()函数,建立与Redis服务器的连接。如果是本地连接redisConnect()不要参数,下面例子使用远程连接,增加host参数配置IP地址。redisConnect(host=“192.168.1.101”,port=6379)
> redisConnect(host="192.168.1.101",port=6379) # 远程连接redis server
> redisKeys() # 列出所有的keys
[1] "x" "data"
> redisDBSize() # 显示有多少个key
[1] 2
> redisSelect(1) # 切换数据库1
[1] "OK"
> redisKeys()
NULL
> redisSelect(0) # 切换数据库0
[1] "OK"
> redisKeys()
[1] "x" "data"
> redisFlushDB() # 清空当前数据库数据
[1] "OK"
> redisFlushAll() # 清空所有数据库数据
[1] "OK"
> redisClose() # 关闭链接
2. string类型操作:
> redisSet('x',runif(5)) # 插入对象
[1] "OK"
> redisGet('x') # 读取对象
[1] 0.67616159 0.06358643 0.07478021 0.32129140 0.16264615
> redisExpire('x',1) # 设置数据过期时间
Sys.sleep(1)
> redisGet('x')
NULL
> redisMSet(list(x=pi,y=runif(5),z=sqrt(2))) # 批量插入
[1] TRUE
> redisMGet(c('x','y','z')) # 批量读取
$x
[1] 3.141593
$y
[1] 0.9249501 0.3444994 0.6477250 0.1681421 0.2646853
$z
[1] 1.414214
> redisDelete('x') # 删除数据
[1] 1
> redisGet('x')
NULL
3. list类型操作
> redisLPush('a',1) # 从数组左边插入数据
> redisLPush('a',2)
> redisLPush('a',3)
> redisLRange('a',0,2) # 显示从数组左边0-2的数据
[[1]]
[1] 3
[[2]]
[1] 2
[[3]]
[1] 1
> redisLPop('a') # 从数据左边弹出一个数据
[1] 3
> redisLRange('a',0,-1) # 显示从数组左边0-(-1)的数据
[[1]]
[1] 2
[[2]]
[1] 1
> redisRPush('a','A') # 从数组右边插入数据
> redisRPush('a','B')
> redisLRange('a',0,-1) #显示从数组左边0-(-1)的数据
[[1]]
[1] 2
[[2]]
[1] 1
[[3]]
[1] "A"
[[4]]
[1] "B"
> redisRPop('a') #从数据右边弹出一个数据
4. set类型操作
> redisSAdd('A',runif(2))
> redisSAdd('A',55)
> redisSCard('A') #显示对象有几个元素
[1] 2
> redisSMembers('A') #列表显示set对象元素
[[1]]
[1] 55
[[2]]
[1] 0.6494041 0.3181108
> redisSAdd('B',55)
> redisSAdd('B',rnorm(3))
> redisSCard('B') #显示对象有几个元素
[1] 2
> redisSMembers('B') #列表显示set对象元素
[[1]]
[1] 55
[[2]]
[1] 0.1074787 1.3111006 0.8223434
> redisSDiff(c('A','B')) #差集
[[1]]
[1] 0.6494041 0.3181108
> redisSInter(c('A','B')) #交集
[[1]]
[1] 55
> redisSUnion(c('A','B')) #并集
[[1]]
[1] 55
[[2]]
[1] 0.1074787 1.3111006 0.8223434
[[3]]
[1] 0.6494041 0.3181108
5. rredis与redis-cli交互
从Redis客户端插入数据,再用rredis读取数据。
~ redis-cli # 打开redis客户端
redis 127.0.0.1:6379> set shell "Greetings, R client!"
OK
> redisGet('shell') # 读取数据
[1] "Greetings, R client!"
用rredis插入数据,再用Redis客户端读取数据
> redisSet('R', 'Greetings, shell client!') # 插入数据
[1] "OK"
redis 127.0.0.1:6379> get R # 读取数据(有乱码)
"X\\x00\x00\x00\x02\x00\x02\x0f\x00\x00\x02\x03\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x04\x00\\x00\x00\x00\x18Greetings, shell client!"
转型以Raw的数组方式存储(charToRaw),就可以解决乱码的问题。
> redisSet('R', charToRaw('Greetings, shell client!'))
[1] TRUE
redis 127.0.0.1:6379> get R #正常读取数据
"Greetings, shell client!"
6.3.4 rredis测试案例
我们已经清楚了rredis的使用,接下来,我们做一个测试案例。读入一个数据文件,从左到右分别是用户id、口令、邮箱,在Redis里建立合适的数据模型,方便存储和查询。首先,定义数据模型。 KEY:
- users:用户id
VALUE:
- id:用户id
- pw:口令
- email:邮箱
数据文件:data5.txt。
wolys # wolysopen111 # wolys@21cn.com
coralshanshan # 601601601 # zss1984@126.com
pengfeihuchao # woaidami # 294522652@qq.com
simulategirl # @#$9608125 # simulateboy@163.com
daisypp # 12345678 # zhoushigang_123@163.com
sirenxing424 # tfiloveyou # sirenxing424@126.com
raininglxy # 1901061139 # lixinyu23@qq.com
leochenlei # leichenlei # chenlei1201@gmail.com
z370433835 # lkp145566 # 370433835@qq.com
cxx0409 # 12345678 # cxx0409@126.com
xldq_l # 061222ll # viv093@sina.com
接下来,读入数据文件到内存。然后建立Redis连接,以循环方式把数据插入到Redis,最后以users:wolys为KEY,输出对应的VALVE值。
> data<-scan(file="data5.txt",what=character(),sep=" ") #读入数据
> data<-data[which(data!='#')]
> data
[1] "wolys" "wolysopen111" "wolys@21cn.com"
[4] "coralshanshan" "601601601" "zss1984@126.com"
[7] "pengfeihuchao" "woaidami" "294522652@qq.com"
[10] "simulategirl" "@#$9608125" "simulateboy@163.com"
[13] "daisypp" "12345678" "zhoushigang_123@163.com"
[16] "sirenxing424" "tfiloveyou" "sirenxing424@126.com"
[19] "raininglxy" "1901061139" "lixinyu23@qq.com"
[22] "leochenlei" "leichenlei" "chenlei1201@gmail.com"
[25] "z370433835" "lkp145566" "370433835@qq.com"
[28] "cxx0409" "12345678" "cxx0409@126.com"
[31] "xldq_l" "061222ll" "viv093@sina.com"
> redisConnect(host="192.168.1.101",port=6379) #连接redis连接
> redisFlushAll()
> redisKeys()
> id<-NULL #循环插入数据
> for(i in 1:length(data)){
+ if(i %% 3 == 1) {
+ id<-data[i]
+ redisSAdd(paste("users:",id,sep=""),paste("id:",id,sep=""))
+ } else if(i %% 3 == 2) {
+ redisSAdd(paste("users:",id,sep=""),paste("pw:",data[i],sep=""))
+ } else {
+ redisSAdd(paste("users:",id,sep=""),paste("email:",data[i],sep=""))
+ }
+}
> redisKeys() #列出所有的KEY
[1] "users:cxx0409" "users:sirenxing424" "users:simulategirl" "users:xldq_l"
[5] "users:coralshanshan" "users:raininglxy" "users:pengfeihuchao" "users:leochenlei"
[9] "users:daisypp" "users:wolys" "users:z370433835"
> redisSMembers("users:wolys") #通过KEY查询VALUE
[[1]]
[1] "pw:wolysopen111"
[[2]]
[1] "email:wolys@21cn.com"
[[3]]
[1] "id:wolys"
> redisClose() #关闭redis连接
这样我们就完成了整个的测试案例。Redis是一种非常高效的内存数据库,用R和Redis结合,可以构建无比强大的时时计算应用。