大概敲了一遍基本命令,熟悉了redis的存储方式。现在开始进一步系统的学习。学习教程目前计划有三个,一个是github上的https://github.com/JasonLai256/the-little-redis-book/blob/master/cn/redis.md,一个是中文官方网站http://www.redis.cn/documentation.html,还有一个看起来像w3c风格的简单教程http://www.runoob.com/redis/redis-commands.html。

我一般喜欢看别人怎么学习的,然后再通过官方文档去学习。因此学习路线首先是github,然后runoob,最后看官方文档。

1.set存储好友案例

集合数据结构常常被用来存储只能唯一存在的值,并提供了许多的基于集合的操作,例如并集。集合数据结构没有对值进行排序,但是其提供了高效的基于值的操作。使用集合数据结构的典型用例是朋友名单的实现:

首先存储两个人leto,duncan的各自的好友set:

  1. sadd friends:leto ghanima paul chani jessica miao
  2. sadd frineds:duncan goku paul jessica alia rui

可以查看leto的好友:

  1. 127.0.0.1:> smembers friends:leto
  2. ) "jessica"
  3. ) "chani"
  4. ) "paul"
  5. ) "ghanima"

可以查看jessica是不是leto的好友O(1)

  1. 127.0.0.1:> sismember friends:leto jessica
  2. (integer)

可以查看leto和duncan的共同好友

  1. 127.0.0.1:> sinter friends:leto friends:duncan
  2. ) "jessica"
  3. ) "paul"

还可以将好友关系存储到新key

  1. 127.0.0.1:> sinterstore friends:leto_duncan friends:leto friends:duncan
  2. (integer)
  3. 127.0.0.1:> smembers friends:leto_duncan
  4. ) "jessica"
  5. ) "paul"

2.sorted set可以分类排序案例

Sorted Sets提供了排序(sorting)和秩划分(ranking)的功能。如果我们想要一个秩分类的朋友名单,可以这样做:

  1. 127.0.0.1:> zadd friends:duncan ghanima paul chani jessica vladimir

对于duncan的朋友,要怎样计算出标记(score)为90或更高的人数?

  1. 127.0.0.1:> zcount friends:duncan
  2. (integer)

如何获取chani在名单里的秩(rank即排名)?

  1. 127.0.0.1:> zrevrank friends:duncan chani
  2. (integer)

3.仿多关键字查询(Pseudo Multi Key Queries),根据id或email查询user案例

首先,存储user:

  1. 127.0.0.1:> set users: "{id:9001,email:leto@dune.gov,..}"
  2. OK

然后,根据id查询用户

  1. 127.0.0.1:> get users:
  2. "{id:9001,email:leto@dune.gov,..}"

如果想要根据email来查询该怎么办呢,这里就要用散列数据结构:

  1. 127.0.0.1:> hset users:lookup:email leto@dune.gov
  2. (integer)

这里,通过域来作为一个二级索引,然后通过id去引用单个用户对象。

  1. 127.0.0.1:> hget users:lookup:email leto@dune.gov
  2. ""
  3. 127.0.0.1:> get users:
  4. "{id:9001,email:leto@dune.gov,..}"

通俗的理解,用户是通过id标记的,即id相当于主键,然后email唯一,想通过email来实现该怎么办呢,那就把email链接到id。由于email的唯一性,可以把它当做field放入hset,id作为对应value。

4.使用散列数据结构的field来做查询索引

同上面的用法,用一个hash的field来存储关键字,根据field来取值。我们知道redis有keys的命令,可以扫描所有的keys找出匹配项,但太慢了。比如将每个用户的bug存储起来,假设用户id为1233的bug类型为bug:1233,每个bug有唯一id,即bug:1233:id。如果将这个当做key存储到redis中,当想要查询用户bug或删除用户bug时可以这样:

  1. keys bug::*

但是用散列数据结构更好一些。

  1. #记录1233的bug
    127.0.0.1:> hset bugs: "{id:1,account:1233,subject:'...'}"
  2. (integer)
  3. 127.0.0.1:> hset bugs: "{id:1,account:1233,subject:'...'}"
  4. (integer) 1
  5.  
  6. #查看1233的所有bug

  127.0.0.1:6379> hkeys bugs:1233
  1) "1"
  2) "2"

#删除id为2的bug

  127.0.0.1:6379> hdel bugs:1233 2
  (integer) 1
  127.0.0.1:6379> hkeys bugs:1233
  1) "1"

用户删除后删除对应的所有bug

  127.0.0.1:6379> del bugs:1233
  (integer) 1

5.发布和订阅

5.1 list的队列消息

redis对于list有lpop和rpop命令,是将list中的元素从一端取出并移除。还有另一个阻塞版本,即blpop、brpop。同样是取出并移除一端的元素,但如果list没有元素了就会阻塞,直到有元素为止。就是生产者-消费者模式。

  1. BLPOP list [list ...] timeout :从list中取出并移除元素,没有元素则阻塞,timeout为超时时间,=0表示永不超时。如果超时后没有元素则返回一组nil ,若有元素则返回keyvaluekeylist

打开多个redis-cli,第一个:

  1. 127.0.0.1:> lpush list1
  2. (integer)
  3. 127.0.0.1:> lpush list1
  4. (integer)
  5. 127.0.0.1:> lpush list1
  6. (integer)
  7. 127.0.0.1:> lpush list2
  8. (integer)

第二个:

  1. 127.0.0.1:> blpop list list1 list2
  2. ) "list1"
  3. ) ""
  4. 127.0.0.1:> blpop list list1 list2
  5. ) "list1"
  6. ) ""
  7. 127.0.0.1:> blpop list list1 list2
  8. ) "list1"
  9. ) ""
  10. 127.0.0.1:> blpop list list1 list2
  11. ) "list2"
  12. ) ""
  13. 127.0.0.1:> blpop list list1 list2

发现当list都没有值的时候,线程阻塞。这时候在第一个客户端追加:

  1. 127.0.0.1:> lpush list
  2. (integer)

然后另一个阻塞的客户端会立即响应:

  1. 127.0.0.1:> blpop list list1 list2
  2. ) "list"
  3. ) ""
  4. (.85s)

5.2此外,Redis对于消息发布和频道订阅有着一流的支持。

打开第一个客户端和第二个客户端,都输入subscribe warnings。意思是订阅一个叫做warnings的管道。

然后打开第三个客户端输入:publish warnings "there is something new!!!",下面的2表示两个客户端收到通知。

这时会,前两个客户端都会受到消息:

6.排序sort

sort命令是Redis最强大的命令之一。它让你可以在一个列表、集合或者分类集合里对值进行排序(分类集合是通过标记来进行排序,而不是集合里的成员)

SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]
summary: Sort the elements in a list, set or sorted set

6.1简单例子

  1. 127.0.0.1:> rpush users:leto:guesses
  2. (integer)
  3. 127.0.0.1:> sort users:leto:guesses
  4. ) ""
  5. ) ""
  6. ) ""
  7. ) ""
  8. ) ""
  9. ) ""
  10. ) ""
  11. ) ""

6.2高级一点

  1. 127.0.0.1:> sadd friends:ghanima leto paul chani jessica alia duncan
  2. (integer)
  3. 127.0.0.1:> sort friends:ghanima limit desc alpha
  4. ) "paul"
  5. ) "leto"
  6. ) "jessica"

6.3sort命令的真正力量是其基于引用对象来进行排序的能力

例如,假设我们有一个Bug追踪器能让用户看到各类已存在问题。我们可能使用一个集合数据结构去追踪正在被监视的问题:

  1. 127.0.0.1:> sadd watch:leto
  2. (integer) 4
  3.  
  4. #set bug编号 bug_level

127.0.0.1:6379> set serverity:12339 3
OK
127.0.0.1:6379> set serverity:1282 2
OK
127.0.0.1:6379> set serverity:228 5
OK
127.0.0.1:6379> ser serverity:9388 4
(error) ERR unknown command 'ser'
127.0.0.1:6379> set serverity:9388 4
OK

要通过问题的严重性来降序排序这些Bug,你可以这样做:

  1. 127.0.0.1:> sort watch:leto by serverity:* desc
  2. ) ""
  3. ) ""
  4. ) ""
  5. ) ""

Redis将会用存储在列表(集合或分类集合)中的值去替代模式中的*(通过by)。这会创建出关键字名字,Redis将通过查询其实际值来排序。

6.4根据散列的field的值排序:相当于order by 字段

先插入散列:

  1. 127.0.0.1:> hset bug: severity
  2. (integer)
  3. 127.0.0.1:> hset bug: priority
  4. (integer)
  5. 127.0.0.1:> hset bug: detail "{id:12339,...}"
  6. (integer)
  7. 127.0.0.1:> hmset bug: severity priority detail "{id:1382,...}"
  8. OK
  9. 127.0.0.1:> hmset bug: severity priority detail "{id:338,...}"
  10. OK
  11. 127.0.0.1:> hmset bug: severity priority detail "{id:9338}"
  12. OK

再插入bug set

  1. 127.0.0.1:> del watch:leto
  2. (integer)
  3. 127.0.0.1:> sadd watch:leto
  4. (integer) 3

现在知道bug集合watch:leto,知道bug的详细信息bug:*,要求将bug集合的bug信息打印出来,并根据priority排序:

  1. 127.0.0.1:> sort watch:leto by bug:*->priority get bug:*->detail
  2. ) "{id:12339,...}"
  3. ) "{id:1382,...}"
  4. ) "{id:338,...}"

当然,还可以获取多个参数:

  1. 127.0.0.1:> sort watch:leto by bug:*->priority get bug:*->detail get bug:*->priority get bug:*->severity
  2. ) "{id:12339,...}"
  3. ) ""
  4. ) ""
  5. ) "{id:1382,...}"
  6. ) ""
  7. ) ""
  8. ) "{id:338,...}"
  9. ) ""
  10. ) ""

也可以获取到*当前所代表的值,即set中取出的值:用get #

  1. 127.0.0.1:> sort watch:leto by bug:*->priority get bug:*->detail get bug:*->priority get bug:*->severity get #
  2. ) "{id:12339,...}"
  3. ) ""
  4. ) ""
  5. ) ""
  6. ) "{id:1382,...}"
  7. ) ""
  8. ) ""
  9. ) ""
  10. ) "{id:338,...}"
  11. ) ""
  12. ) ""
  13. ) ""

使用我们已经看过的expiration命令,再结合sort命令的store能力,这是一个美妙的组合。

redis学习之二from github的更多相关文章

  1. Redis学习笔记二 (BitMap算法分析与BitCount语法)

    Redis学习笔记二 一.BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省 ...

  2. redis 学习(二)-- 通用命令

    redis 学习(二)-- 通用命令 1. keys pattern 含义:查找所有符合给定模式(pattern)的key 命令 含义 keys * 遍历所有 key keys he[h-l]* 遍历 ...

  3. redis学习教程二《四大数据类型》

    redis学习教程二<四大数据类型>  四大数据类型包括:字符串    哈希    列表   集合一 : Redis字符串         Redis字符串命令用于管理Redis中的字符串 ...

  4. C# Redis学习系列二:Redis基本设置

    上一篇:C# Redis学习系列一:Redis的认识.下载.安装.使用 一.redis 设置密码 使用下载好的 redis-cli.exe 指令: 1.设置密码: config set require ...

  5. 【Redis】Redis学习(二) master/slave、sentinel、Cluster简单总结

    项目中用到Redis,所以准备学习一下,感觉Redis的概念还是很多的,什么主从模式.sentinel模式.集群模式的,一下子都晕了,我觉得还是有必要先理清这些基本概念再说. 一.单节点实例 单节点实 ...

  6. Redis学习笔记二

    学习Redis添加Object时,由于Redis只能存取字符串String,对于其它数据类型形容:Int,long,double,Date等不提供支持,因而需要设计到对象的序列化和反序列化.java序 ...

  7. 分布式缓存技术redis学习(二)——详细讲解redis数据结构(内存模型)以及常用命令

    Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sor ...

  8. redis 学习笔记二 (简单动态字符串)

    redis的基本数据结构是动态数组 一.c语言动态数组 先看下一般的动态数组结构 struct MyData { int nLen; char data[0]; }; 这是个广泛使用的常见技巧,常用来 ...

  9. Redis学习之二 数据类型和相关命令

    原文:https://www.cnblogs.com/lonelyxmas/p/9073928.html 如果还不懂安装的,请看 Windows环境下安装Redis Redis一共支持五种数据类型 1 ...

随机推荐

  1. JAVA缓存技术

    介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI技术,让Java代码可以实时的监控制定文件夹内文件的变动信息,支持Linux/Windows/MacOS ...

  2. Hasor-Core v0.0.4 & Web v0.0.3 发布

    “Hasor是一款开源的 Java 应用开发框架.它是围绕 Guice 为核心创建的一系列模块组合而成.使用Hasor 会加快软件软件开发效率并降低开发成本.目前 Hasor包含了 Hasor-Cor ...

  3. Lucene 查询工具 LQT

    Lucene Query Tool (lqt) 是一个命令行工具用来执行 Lucene 查询并对结果进行格式化输出. 使用方法: 01 $ ./lqt 02 usage: LuceneQueryToo ...

  4. 浅谈 facebook .net sdk 应用

    今天看了一篇非常好的文章,就放在这里与大家分享一下,顺便也给自己留一份.这段时间一直在学习MVC,另外如果大家有什么好的建议或者学习的地方,也请告知一下,谢谢. 这篇主要介绍如何应用facebook ...

  5. 当匿名类型遇上Distinct

    首先定义一个简单类,并重写ToString方法. public class CommidityFilter { public string Property { get; set; } public ...

  6. 用 C 扩展 python

    本文介绍如何用 C 语言来扩展 python.所举的例子是,为 python 添加一个设置字符串到 windows 的剪切板(Clipboard)的功能.我在写以下代码的时候用到的环境是:window ...

  7. Java Socket Server的演进 (一)

    最近在看一些网络服务器的设计, 本文就从起源的角度介绍一下现代网络服务器处理并发连接的思路, 例子就用java提供的API. 1.单线程同步阻塞式服务器及操作系统API 此种是最简单的socket服务 ...

  8. flex Vector

    Error: 找不到类型,或者它不是编译时常数: Vector.   或者Type was not found or was not a compile-time constant: Vector. ...

  9. sql基础知识:分页+排序

    Oracle的分页还真是挺恶心地,不像mysql直接Limit就搞定 select name from student limit 0,20; Oracle需要借助rownum实现: select * ...

  10. lua以xpcall实现try/catch功能

    -- 打印错误信息 local function __TRACKBACK__(errmsg) ); print("-------------------------------------- ...