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结合,可以构建无比强大的时时计算应用。

results matching ""

    No results matching ""