Chinaunix首页 | 论坛 | 博客
  • 博客访问: 371285
  • 博文数量: 166
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1640
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-05 11:44
个人简介

文章不在长,坚持不懈记录下努力前行的脚步

文章分类

全部博文(166)

文章存档

2017年(19)

2016年(59)

2015年(88)

我的朋友

分类: NOSQL

2015-07-23 17:17:49

在这一章,我们来看下如何扩展Redis的数据结构,迅速而且灵活的创建复杂的系统,典型的做法是用来加速我们的关系型数据库系统,我们先从存储一些简单的数据集合开始,逐步建立较为复杂而有趣的东西。
用Redis作为键值存储
很多应用需要存储类似usage,配置,或者其他相关信息等等这样的一些临时的数据,传统的关系型数据库可能不太适合这种固定式的结构,以往开发者们都会拆分表结构使得数据能存储在MySQL或者其他的关系型数据库中。在此,我们将会看到我们如何用Redis及其内置的数据类型来以一种更轻、更快更松散的方式来存储应用数据。

问题解决
Redis本身的定位就是他不单是键值存储,还有丰富的数据类型结构。这意味着在典型的键值存储功能之上,还有更加丰富的、多样的方式来存储和操作数据。我们将会用到这些结构来存储应用数据,比如:用key存储用户计数,用hash存储用户对象,用集合来实现好友圈。

细节研究
1.存储点击数据
让我们从存储基本数据开始:计数器。假设在我们运行的一个社交网络的商业网站上统计用户访问页面的数据,在关系型数据库中,我们可以在任何一张表中增加一列来存储我们的页数据,but hopefully our traffic is high enough that updates to this column have trouble keeping up. We need something much faster to update and to query. So we’ll use Redis for this instead.
好在Redis提供了原生的命令,我们知道如果我们一个计数器,我们能用INCR或者DECR命令来改变他的值,因此通过为我们的数据设计一个恰当的命名空间来维护我们的计数器变得简单。

在Redis中,没有既定的对key的命名规则,但是包括笔者在内大多数人在定义key的时候总喜欢用分号来分隔keywords,因此我们也有必要这么做,为了存储我们的社交网络页面的访问情况的数据,我们能够采用形如visits:pageid:totals这样的命名空间,类似pageID为635的可以定义为visits:635:totals。如果我们已经把数据存储在了某个地方,那么我们可以将这个值赋给我们的key。
SET visits:1:totals 21389
SET visits:2:totals 1367894
当客户端再次访问这个页面是,一个简单的INCR命令就能更新这个计数器的值:
INCR visits:635:totals
然后我们能够抓取任何页面的访问情况,可以随时通过一个简单的命令来抓取:
GET visits:635:totals
但是更聪明一点的做法是:比如你正在把访问者访问这个页面的计数返回给访问者自己。很自然地,他本次的访问你也会统计进去,因此你不得不做最后一次get操作,你可以获取INCR命令执行后的这个返回值,因为他返回的是增长之后的值。下面是一段简单的访问计数的伪代码:
1. The visitor requests the page.
2. We INCR the visits counter related to the page (INCR visits:635:totals, for instance).
3. We capture the return value of the INCR command.
4. We show the user the page with the return value.
这种方式使得当用户浏览页面的时候我就能实时的把访问计数返回给用户,着只需要一个简单的redis命令。
2.在hash表中存储用户对象信息
As discussed in “Using Redis Data Types” on page 7,Redis的hash表的实现使得对对象数据存储的典型用法更趋完美。下面的例子中我们将来研究在既定系统中如何用哈希表来存储用户对象信息。
我们先要设计一个key的命名空间来存储我们的用户对象,跟之前一样,我们用分号来分离keywords来获得更具可读性的key,For the sake of this recipe, we’ll go with something simple like keys in the form of
users:alias, where alias is a binary-safe string. So to store information about a user
called John Doe, we might build a hash called users:jdoe.
假定我们要存储关于用户的多个属性,比如名字、email、电话号码、应用访问量。我们将用到Redis的hash表的管理命令——像HSET,HGET还有HINCRBY——来存储这些信息。
redis> hset users:jdoe name "John Doe"
(integer) 1
redis> hset users:jdoe email "jdoe@test.com"
(integer) 1
redis> hset users:jdoe phone "+1555313940"
(integer) 1
redis> hincrby users:jdoe visits 1
(integer) 1
With our hash built and in place,我们可以用HGET命令来获取单个字段的值或者用HGETALL命令来获取所有的hash值,下面给出例子:
redis> hget users:jdoe email
"jdoe@test.com"
redis> hgetall users:jdoe
1) "name"
2) "John Doe"
3) "email"
4) "jdoe@test.com"
5) "phone"
6) "+1555313940"
7) "visits"
8) "1"
通过辅助命令HKEYS可以返回存储在具体hash表中的keys,HVALS可以返回键值。按照你想检索的数据,你可以用HGETALL找到你需要的,或者把检索到的其中之一返回给你的应用。
redis> hkeys users:jdoe
1) "name"
2) "email"
3) "phone"
4) "visits"
redis> hvals users:jdoe
1) "John Doe"
2) "jdoe@test.com"
3) "+1555313940"
4) "1"
额外的管理hash表的命令可以参考官方文档,文档中有关于用hash表管理数据的一些例子。
用集合保存社交网站圈子数据
To complete our look at some typical ways to store data in Redis,下面来看看如何用集合来构建一些功能,比如像google最近发布的社交圈子。集合天生就适合社交圈子,因为集合代表做数据的整合,他天生的就能很好的实现交并等集合操作。
我们就来定义一下这类key,我们想为我们的每一个用户保存他们各自的社交圈子,感觉上我们的key应该包括user以及他们的圈子类别。比如:John Doe的家庭圈子可以定义这样一个key:circle:jdoe:family,类似它的soccer战队可能是circle:jdoe:soccer的这样一个key,为key的设计没有特定规则,因此用对你的应用有意义的方式来设计是一贯的做法。
既然我们知道把集合保存到key里面,那我们就来定义一下John Doe的家庭成员和soccer成员,在这个集合中,我们能通过user ids列出一些参照其他键的条目,so we’ll do the latter because it makes sense for us。那么如果我们想获得John的家庭成员的表单并展现出来,用集合操作的结果我们能得到每个成员在hash表的实际信息(可能存储在hash表中)
redis> sadd circle:jdoe:family users:anna
(integer) 1
redis> sadd circle:jdoe:family users:richard
(integer) 1
redis> sadd circle:jdoe:family users:mike
(integer) 1
redis> sadd circle:jdoe:soccer users:mike
(integer) 1
redis> sadd circle:jdoe:soccer users:adam
(integer) 1
redis> sadd circle:jdoe:soccer users:toby
(integer) 1
redis> sadd circle:jdoe:soccer users:apollo
(integer) 1
记住上面的例子,我们应该用ids来初始化成员而不是user:name.为了使上面的例子能更好的运行,为了速度和内存效益牺牲一点可读性来提高性能是一个不错的选择。
现在我们有一个叫circle:jdoe:family的集合有三个值--users:anna, users:richard, and users:mike,第二个叫circle:jdoe:soccer有四个值(users:mike, users:adam, users:toby, and users:apollo)。这些值本身就是字符串,对我们来说,字符串是有意义的(他们和我们设计的hash表的key很相似),我们能间接地通过SMEMBERS的结果来获取明确的用户信息,下面是一个恰当的例子:
redis> smembers circle:jdoe:family
1) "users:richard"
2) "users:mike"
3) "users:anna"
redis> hgetall users:mike
(...)
既然我们已经了解如何的用集合来保存信息,我们不妨在延伸一下用集合来做一些有趣的事情,比如,取得同时属于John Doe的两个集合的成员(family与soccer两个集合的交集),或者取得所有属于John Doe的两个圈子的成员(通过集合并操作):
redis> sinter circle:jdoe:family circle:jdoe:soccer
1) "users:mike"
redis> sunion circle:jdoe:family circle:jdoe:soccer
1) "users:anna"
2) "users:mike"
3) "users:apollo"
4) "users:adam"
5) "users:richard"
6) "users:toby"
从我们得到的结果可以看出,Mike同时属于John Doe的family和soccer两个集合的成员,通过联合这两个集合,我们也得到John好友圈的一个完整列表。
正如我们看到的,在传统关系型数据库中的一些查询用Redis的集合来做更容易,也更快,这使得他成为实现很多诸如集合管理应用的理想候选,社交网络只是一个例子,但是像推荐系统或者文本搜索这些用集合来做也很适合,我们期待这些例子的一些更深远的应用。
快速查阅key命令
SET key value
保存key值,如果存在则覆盖(即使类型不同)
GET key
返回key保存的内容,只返回字符串
INCR key
key加1
INCRBY key value
key的值(value)加1
DECR key
key减1
DECRBY key value
key的值(value)减1
检查数据
问题
用Redis开发的时候,你可能需要看一下数据,尽管不像mysql的show tables那么简单,and SELECT * FROM table WHERE conditions,在Redis里面有几种方式查看数据。
解决办法
在Redis里面可以通过KEYS命令来获取数据,这个命令支持通配符,看下面的命令:
KEYS *
这将会返回数据库中所有的keys,但是,仅仅取得这些信息是不够的,你可能还是不知道这key的类型是什么?用TYPE命令可以做到这一点:
TYPE keyname
这样你就可以知道这key是一个字符串、hash表、链表、集合还是排序集合类型。
问题讨论
key的通配符命令很有限却很有用,他支持下面这种查询:
KEYS h*llo
返回所有以h开头llo结尾的key;
KEYS h?llo
返回所有以h开头llo结尾中间只有一个字符的key;
KEYS h[ae]llo
如果存在,返回hallo和hello;
记住当你用keys命令的时候,Redis会扫描数据库中所有的key,因此,这样做真的会拖慢你的数据库服务,所以作为你个常规操作你应该恰当的使用它。如果你想要数据库中所有的或者部分的key,你可能想把它加到一个集合里来查询他。
如果你想调试一个正在运行的应用程序,那么用monitor命令非常有用,他能把执行结果实时地发送到server。
keys pattern
找到与给定结构相匹配的数据库中的所有key
type key-name
返回key类型,可能的类型是:字符创,链表,hash表,集合,排序集合,说着无返回结果
monitor
接受Redis服务器实时返回的值。



























阅读(585) | 评论(0) | 转发(0) |
0

上一篇:Redis客户端

下一篇:虚拟机网络设置

给主人留下些什么吧!~~