java多线程    Java入门    vsftp    ftp    linux配置    centos    FRP教程    HBase    Html5缓存    webp    zabbix    分布式    neo4j图数据库    

redis基本数据结构及命令

redis commands命令组合如下
Keys Strings Hashes Lists Sets Sorted Sets Pub/Sub Transactions Scripting Connection Server

1 Redis 键 keys

Redis key值是二进制安全的,这意味着可以用任何二进制序列作为key值,从形如”foo”的简单字符串到一个JPEG文件的内容都可以。空字符串也是有效key值。

关于key的几条规则:

1) 太长的键值不是个好主意,例如1024字节的键值就不是个好主意,不仅因为消耗内存,而且在数据中查找这类键值的计算成本很高。
2)太短的键值通常也不是好主意,如果你要用”u:1000:pwd”来代替”user:1000:password”,这没有什么问题,但后者更易阅读,并且由此增加的空间消耗相对于key object和value object本身来说很小。当然,没人阻止您一定要用更短的键值节省一丁点儿空间。

3)最好坚持一种模式。例如:”object-type:id:field”就是个不错的主意,像这样”user:1000:password”。我喜欢对多单词的字段名中加上一个点,就像这样:”comment:1234:reply.to”。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

2 列表类型 Lists

LPUSH 命令可向list的左边(头部)添加一个新元素,而RPUSH命令可向list的右边(尾部)添加一个新元素。最后LRANGE 命令可从list中取出一定范围的元素

redis 127.0.0.1:6379> rpush mes "how are you"
(integer) 1
redis 127.0.0.1:6379> rpush mes "I am fine"
(integer) 2
redis 127.0.0.1:6379> rpush mes "what's about you"
(integer) 3
redis 127.0.0.1:6379> lrange mes 0 2
1) "how are you"
2) "I am fine"
3) "what's about you"
redis 127.0.0.1:6379>

注意LRANGE 带有两个索引,一定范围的第一个和最后一个元素。这两个索引都可以为负来告知Redis从尾部开始计数,因此-1表示最后一个元素,-2表示list中的倒数第二个元素,以此类推。

列表应用说明

正如你可以从上面的例子中猜到的,list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是,你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作,将会非常快,也会很容易扩展到百万级别元素的规模。

例如在评级系统中,比如社会化新闻网站 reddit.com,你可以把每个新提交的链接添加到一个list,用LRANGE可简单的对结果分页。

在博客引擎实现中,你可为每篇日志设置一个list,在该list中推入进博客评论,等等。

更方便的应用策略
向Redis list压入ID而不是实际的数据
在上面的例子里 ,我们将“对象”(此例中是简单消息)直接压入Redis list,但通常不应这么做,由于对象可能被多次引用:例如在一个list中维护其时间顺序,在一个集合中保存它的类别,只要有必要,它还会出现在其他list中,等等。

让我们回到reddit.com的例子,将用户提交的链接(新闻)添加到list中,有更可靠的方法如下所示:

$ redis-cli incr next.news.id
(integer) 1
$ redis-cli set news:1:title "Redis is simple"
OK
$ redis-cli set news:1:url "http://code.google.com/p/redis"
OK
$ redis-cli lpush submitted.news 1
OK
我们自增一个key,很容易得到一个独一无二的自增ID,然后通过此ID创建对象–为对象的每个字段设置一个key。最后将新对象的ID压入submitted.news list。

这只是牛刀小试。在命令参考文档中可以读到所有和list有关的命令。你可以删除元素,旋转list,根据索引获取和设置元素,当然也可以用LLEN得到list的长度。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3 Redis 集合 Sets

Redis集合是未排序的集合,其元素是二进制安全的字符串。SADD命令可以向集合添加一个新元素。和sets相关的操作也有许多,比如检测某个元素是否存在,以及实现交集,并集,差集等等。一例胜千言:

redis 127.0.0.1:6379> sadd aset 1
(integer) 1
redis 127.0.0.1:6379> sadd aset 2
(integer) 1
redis 127.0.0.1:6379> sadd aset 3
(integer) 1
redis 127.0.0.1:6379> smembers aset
1) "3"
2) "1"
3) "3"

我向集合中添加了三个元素,并让Redis返回所有元素。如你所见它们是无序的。

现在让我们检查某个元素是否存在:

redis 127.0.0.1:6379> sismember aset 3
(integer) 1
redis 127.0.0.1:6379> sismember aset 30
(integer) 0

“3″是这个集合的成员,而“30”不是。集合特别适合表现对象之间的关系。例如用Redis集合可以很容易实现标签功能。

下面是一个简单的方案:对每个想加标签的对象,用一个标签ID集合与之关联,并且对每个已有的标签,一组对象ID与之关联。

例如假设我们的新闻ID 1000被加了三个标签tag 1,2,5和77,就可以设置下面两个集合:

$ redis-cli sadd news:1000:tags 1
(integer) 1
$ redis-cli sadd news:1000:tags 2
(integer) 1
$ redis-cli sadd news:1000:tags 5
(integer) 1
$ redis-cli sadd news:1000:tags 77
(integer) 1
$ redis-cli sadd tag:1:objects 1000
(integer) 1
$ redis-cli sadd tag:2:objects 1000
(integer) 1
$ redis-cli sadd tag:5:objects 1000
(integer) 1
$ redis-cli sadd tag:77:objects 1000
(integer) 1
要获取一个对象的所有标签,如此简单:

$ redis-cli smembers news:1000:tags
1. 5
2. 1
3. 77
4. 2
而有些看上去并不简单的操作仍然能使用相应的Redis命令轻松实现。例如我们也许想获得一份同时拥有标签1, 2, 10和27的对象列表。这可以用SINTER命令来做,他可以在不同集合之间取出交集。因此为达目的我们只需:

$ redis-cli sinter tag:1:objects tag:2:objects tag:10:objects tag:27:objects
... no result in our dataset composed of just one object ;) ...
在命令参考文档中可以找到和集合相关的其他命令,令人感兴趣的一抓一大把。一定要留意SORT命令,Redis集合和list都是可排序的。

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

4.有序集合 Sorted Sets

集合是使用频率很高的数据类型,但是…对许多问题来说他们也有点儿太不讲顺序了;)因此Redis1.2引入了有序集合。他和集合非常相似,也是二进制安全的字符串集合,但是这次带有关联的score,以及一个类似LRANGE的操作可以返回有序元素,此操作只能作用于有序集合,它就是,ZRANGE 命令。

从某种程度上说,有序集合是SQL世界的索引在Redis中的等价物。例如在刚才的reddit.com例子中,并没有提到如何根据用户投票和时间因素将新闻组合生成首页。下面我们会用有序集合解决这个问题,我们先从最简单的事情开始,阐明这个高级数据类型是如何工作的。让我们添加几个黑客,并将他们的生日作为“score”。

redis 127.0.0.1:6379> zadd hackers 1982 "tom"
(integer) 1
redis 127.0.0.1:6379> zadd hackers 1976 "jack"
(integer) 1
redis 127.0.0.1:6379> zadd hackers 1985 "jam"
(integer) 1

对有序集合来说,按生日排序返回这些黑客易如反掌,因为他们已经是有序的。有序集合是通过一个dual-ported 数据结构实现的,它包含一个精简的有序列表和一个hash table,因此添加一个元素的时间复杂度是O(log(N))。这还行,但当我们需要访问有序的元素时,Redis不必再做任何事情,它已经是有序的了:

redis 127.0.0.1:6379> zrange hackers 0 -1
1) "jack"
2) "tom"
3) "jam"

你知道tom比jack年轻吗 ;)

无论如何,我想反向对这些元素排序,这次就用 ZREVRANGE 代替 ZRANGE 吧:

redis 127.0.0.1:6379> zrevrange hackers 0 -1
1) "jam"
2) "tom"
3) "jack"

一个非常重要的小贴士,ZSets只是有一个“默认的”顺序,但你仍然可以用 SORT 命令对有序集合做不同的排序(但这次服务器要耗费CPU了)。要想得到多种排序,一种可选方案是同时将每个元素加入多个有序集合。

/////////////////////////////////////////////////////////////////////////////////////////

区间操作
有序集合之能不止于此,他能在区间上操作。例如获取所有1980年之前出生的人。我们用 ZRANGEBYSCORE 命令来做:

redis 127.0.0.1:6379> zrangebyscore hackers -inf 1980
1) "jack"

我们请求Redis返回score介于负无穷到1980年之间的元素(两个极值也包含了)。

也可以删除区间内的元素。例如从有序集合中删除生日介于1981到1983年之间的黑客。

redis 127.0.0.1:6379> zremrangebyscore hackers 1981 1983
(integer) 1

ZREMRANGEBYSCORE 这个名字虽然不算好,但他却非常有用,还会返回已删除的元素数量。

回到Reddit的例子
最后,回到 Reddit的例子。现在我们有个基于有序集合的像样方案来生成首页。用一个有序集合来包含最近几天的新闻(用 ZREMRANGEBYSCORE 不时的删除旧新闻)。用一个后台任务从有序集合中获取所有元素,根据用户投票和新闻时间计算score,然后用新闻IDs和scores关联生成 reddit.home.page 有序集合。要显示首页,我们只需闪电般的调用 ZRANGE。

不时的从 reddit.home.page 有序集合中删除过旧的新闻也是为了让我们的系统总是工作在有限的新闻集合之上。

更新有序集合的scores

结束这篇指南之前还有最后一个小贴士。有序集合scores可以在任何时候更新。只要用 ZADD 对有序集合内的元素操作就会更新它的score(和位置),时间复杂度是O(log(N)),因此即使大量更新,有序集合也是合适的。

这篇指南远未尽言,这只是从Redis开始的基础,欲深入之请读命令参考文档。http://redis.io/commands

参考文档

http://blog.1001i.com/computer/redis/introduce-redis#Redis_lists


This entry was posted in 数据库, 高并发与大数据 and tagged . Bookmark the permalink.
月小升QQ 2651044202, 技术交流QQ群 178491360
首发地址:月小升博客https://java-er.com/blog/redis-basic-data/
无特殊说明,文章均为月小升原创,欢迎转载,转载请注明本文地址,谢谢
您的评论是我写作的动力.

One Response to redis基本数据结构及命令

  1. Teach your dog says:

    在你博客很多都是没见过的东西啊!收藏了

Leave a Reply