redis学习实践
Redis 是一个高性能的key-value数据库。既可内存存储又可持久化,着实牛逼。它提供五种数据类型:string, hash, list, set及zset(sorted set)。
安装
好烦,每次学习一项新工具,总要先捣腾好一阵子安装和配置。其实我已经迫不及待地想要一窥其风骚的走位和操作了。可是稍安勿躁,该做的还是一步都不能省哪!
获取源码、解压、进入源码目录、编译安装:
1 | $ wget http://download.redis.io/releases/redis-3.0.6.tar.gz |
编译好后执行:
1 | $ src/redis-server & |
启动客户端shell:
1 | $ src/redis-cli |
我擦,我没有看错吧,已经可以进行存取了!简单到辱没智商哪!
数据结构
没想到,这么快就步入正题了,开头说过,redis是一种高性能key-value存储系统,有五种数据类型,跟mysql一样,redis中的操作指令并不区分大小写。
字符串(string)
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> set mynum "2"
OK
127.0.0.1:6379> get mynum
"2"
127.0.0.1:6379> incr mynum
(integer) 3
127.0.0.1:6379> get mynum
"3"
127.0.0.1:6379> incrby mynum 5
"8"set key value存储一个键值对,get key获取一个键值对。可知,在遇到数值操作时,redis会将字符串类型转成数值。
incr等指令本身具有原子操作的特性,我们可以利用redis的incr、incrby、decr、decrby等指令来实现原子计数的效果。字符串列表(list)
redis中的list在底层实现上不是数组而是链表,这说明了什么呢?说明了在list上插入一个新元素(无论行首行尾行中),其时间复杂度为O(1)。比如用
lpush在10个元素的list头部插入新元素,和在上千万元素的list头部插入新元素的速度是相同的。然而有利总有弊嘛,list取元素的速度就没数组那么快了,时间复杂度为O(n)。
list的常用操作包括
lpush、rpush、lrange等。我们可以用lpush在list的左侧插入一个新元素,用rpush在list的右侧插入一个新元素,用lrange命令从list中指定一个范围来提取元素。例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#新建一个list叫做mylist,并在列表头部插入元素"1"
127.0.0.1:6379> lpush mylist "1"
#返回当前mylist中的元素个数
(integer) 1
#在mylist右侧插入元素"2"
127.0.0.1:6379> rpush mylist "2"
(integer) 2
#在mylist左侧插入元素"0"
127.0.0.1:6379> lpush mylist "0"
(integer) 3
#列出mylist中从编号0到编号1的元素
127.0.0.1:6379> lrange mylist 0 1
1) "0"
2) "1"
#列出mylist中从编号0到倒数第一个元素
127.0.0.1:6379> lrange mylist 0 -1
1) "0"
2) "1"
3) "2"list的应用相当广泛,例如:
- 可以利用list来实现一个消息队列,而且可以确保先后顺序,不必像mysql那样还需要通过
order by来进行排序。 - 利用lrange可以很方便的实现分页功能。
- 在博客系统中,每篇博文的评论也可以存入一个单独的list中。
- 可以利用list来实现一个消息队列,而且可以确保先后顺序,不必像mysql那样还需要通过
字符串集合(set)
redis的集合,是一种无序的集合,集合中的元素没有先后顺序,集合中没有重复元素。
集合相关的操作也很丰富,如添加新元素(sadd)、删除已有元素(srem)、取交集(sinter)、取并集(sunion)、取差集(sdiff)、返回集合大小(scard)等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#向集合myset中加入一个新元素"one",返回1存储成功,返回0表示元素已存在不能再存储
127.0.0.1:6379> sadd myset "one"
(integer) 1
127.0.0.1:6379> sadd myset "two"
(integer) 1
127.0.0.1:6379> sadd myset "two"
(integer) 0
#列出集合myset中的所有元素
127.0.0.1:6379> smembers myset
1) "one"
2) "two"
#判断元素'one'是否在集合myset中,返回1表示存在
127.0.0.1:6379> sismember myset "one"
(integer) 1
#判断元素'three'是否在集合myset中,返回0表示不存在
127.0.0.1:6379> sismember myset "three"
(integer) 0
#新建一个新的集合yourset
127.0.0.1:6379> sadd yourset "1"
(integer) 1
127.0.0.1:6379> sadd yourset "2"
(integer) 1
127.0.0.1:6379> smembers yourset
1) "1"
2) "2"
#对两个集合求并集
127.0.0.1:6379> sunion myset yourset
1) "1"
2) "one"
3) "2"
4) "two"
#求集合大小
127.0.0.1:6379> scard yourset
(integer) 2常见的投票功能可以使用集合来实现,比如有个投票功能,每个用户只能投一次,将投过票的用户的id存在集合里,获取集合的大小可以获取投票数。
有序字符串集合(sorted set)
redis体贴地提供了有序集合,其中的每个元素都关联一个序号(score),这是排序的依据。
通常,我们将有序集合叫做zset,是因为在redis中,有序集合相关的操作指令都是以z开头的,如zrange、zadd、zrevrange、zrangebyscore等。
话不多说,看栗子吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#向myzset中新增一个元素'java',赋予序号1
127.0.0.1:6379> zadd myzset 1 java
(integer) 1
#向myzset中新增一个元素'python',赋予序号3
127.0.0.1:6379> zadd myzset 3 python
(integer) 1
#向myzset中新增一个元素'php',赋予序号2
127.0.0.1:6379> zadd myzset 2 php
(integer) 1
#列出myzset的所有元素,同时列出其序号,可以看出myzset是有序的。
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "java"
2) "1"
3) "php"
4) "2"
5) "python"
6) "3"
#只列出myzset的元素
127.0.0.1:6379> zrange myzset 0 -1
1) "java"
2) "php"
3) "python"说个使用场景吧。比如你的博客文章,以发布时的时间戳为score,以文章id为值存入zset中,就可以按时间顺序进行正序或倒序(zrevrange)的排列了,还可以获取指定时间区间的博客文章(使用zrangebyscore)。
哈希(hash)
hash存的是字符串和字符串值之间的映射,比如一个用户要存储其全名、姓氏、年龄等,就特别适合使用哈希。举个栗子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#建立hash,并赋值
127.0.0.1:6379> hmset user:001 username iwhynot password memeda age 25
OK
#列出hash的内容
127.0.0.1:6379> hgetall user:001
1) "username"
2) "iwhynot"
3) "password"
4) "memeda"
5) "age"
6) "25"
#更改hash的某一个值
127.0.0.1:6379> hset user:001 password 12345
(integer) 0
#再次列出hash的内容
127.0.0.1:6379> hgetall user:001
1) "username"
2) "iwhynot"
3) "password"
4) "12345"
5) "age"
6) "25"
#获取hash的某一个键的值
127.0.0.1:6379> hget user:001 password
"12345"
另外,说一下一些常用的命令:
TYPE key— 用来获取某key的类型KEYS pattern— 匹配所有符合模式的key,比如KEYS * 就列出所有的key了,当然,复杂度O(n)RANDOMKEY- 返回随机的一个keyRENAME oldkey newkey— key也可以改名
列表操作,精华
RPUSH key string— 将某个值加入到一个key列表末尾LPUSH key string— 将某个值加入到一个key列表头部LLEN key— 列表长度LRANGE key start end— 返回列表中某个范围的值,相当于mysql里面的分页查询那样LTRIM key start end— 只保留列表中某个范围的值LINDEX key index— 获取列表中特定索引号的值,要注意是O(n)复杂度LSET key index value— 设置列表中某个位置的值LPOP keyRPOP key— 和上面的LPOP一样,就是类似栈或队列的那种取头取尾指令,可以当成消息队列来使用了
集合操作
SADD key member— 增加元素SREM key member— 删除元素SCARD key— 返回集合大小SISMEMBER key member— 判断某个值是否在集合中SINTER key1 key2 ... keyN— 获取多个集合的交集元素SMEMBERS key— 列出集合的所有元素
详尽的指令介绍可以在这里尽情查看。http://redis.io/commands。
redis配置
当然,配置是一个很核心的部分。然而,我并不想多说。
默认安装的redis.conf配置文件,里面的英文注释已经非常详细了,就不需要我翻译了(其实是我英文不好)。
redis在nodejs中的使用
安装node_redis模块:
1 | $ npm install redis |
使用:
1 | var redis = require("redis"), |
更多风骚的用法,查看这里吧https://github.com/NodeRedis/node_redis。
- 本文链接:https://vhtml.github.io/2016/01/19/redis-study/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!