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 key
RPOP 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 许可协议。转载请注明出处!