Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,他可以用作数据库、缓存和消息中间件MQ。它支持多种类型的数据结构,如 字符串(strings),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets)与范围查询,bitmaps,hyperloglogs和地理空间(geospatial)索引半径查询。Redis内置了 复制(replication),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事物(transactions)和不同级别的 磁盘持久化(persistence),并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)。
Redis-Key
expire设置过期时间,可以用来做单点登录,热点数据设置
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
35
36
37
38
39
40
41
| 127.0.0.1:6379> set name qimington
OK
127.0.0.1:6379> set age 21
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists namess
(integer) 0
127.0.0.1:6379> move name 1 # 1 为当前数据库
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> get age
"21"
127.0.0.1:6379> set name qimington
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> expire name 10 # 设置过期时间(秒)
(integer) 1
127.0.0.1:6379> ttl name # 查看该key的剩余有效时间
(integer) 7
127.0.0.1:6379> ttl name
(integer) 6
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> type age # type查看当前key的类型
string
|
可以在中文官网(http://www.redis.cn/)查看命令使用方法
String
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 127.0.0.1:6379> set key1 v1 # 设置值
OK
127.0.0.1:6379> get key1 # 获得值
"v1"
127.0.0.1:6379> exists key1 # 判断某个key是否存在
(integer) 1
127.0.0.1:6379> append key1 "hello" # 追加字符串,若该key不存在,则等价于set一个key
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> append key1 lkj4
(integer) 11
127.0.0.1:6379> get key1
"v1hellolkj4"
127.0.0.1:6379> strlen key1 # 获取字符串长度
(integer) 11
|
自增自减可用于浏览量的记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| 127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 自增1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> decr views # 自减1
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> decr views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> incrby views 10 # 自增步长数
(integer) 9
127.0.0.1:6379> incrby views 10
(integer) 19
127.0.0.1:6379> decrby views 5 #自减步长数
(integer) 14
|
getrange截取字符串
1
2
3
4
5
6
7
8
9
10
11
12
| 127.0.0.1:6379> set info "hello,qimington welcome to the world"
OK
127.0.0.1:6379> get info
"hello,qimington welcome to the world"
127.0.0.1:6379> getrange info 0 3 # 截取字符串[0,3]
"hell"
127.0.0.1:6379> getrange info 0 -1 # 获取字符串
"hello,qimington welcome to the world"
127.0.0.1:6379> setrange info 1 "xx" # 替换指定位置开始的字符串
(integer) 36
127.0.0.1:6379> get info
"hxxlo,qimington welcome to the world"
|
setex(set with expire)设置值并设置过期时间
setnx(set if not exist)不存在时才设置(在分布式锁中常常会使用,如乐观锁)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 127.0.0.1:6379> setex key1 30 "qimington" # 设置key1的值为"qimington",30秒后过期
OK
127.0.0.1:6379> ttl key1
(integer) 25
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> setnx key2 "redis" # 如果key2不存在则创建
(integer) 1
127.0.0.1:6379> keys *
1) "key2"
127.0.0.1:6379> setnx key2 "redis"
(integer) 0
127.0.0.1:6379> keys *
1) "key2"
127.0.0.1:6379> setnx key2 "redisss"
(integer) 0
127.0.0.1:6379> keys *
1) "key2"
|
批量设置与批量获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v11 k4 v4 # 一个失败则全失败,要么一起成功要么一起失败,msetnx是一个原子性的操作
(integer) 0
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
|
对象
1
2
3
4
5
6
7
8
9
| 127.0.0.1:6379> set user:1 {name:zhangsan,age:2} # 设置一个"user:1"对象,值为json字符串来保存一个对象
OK
# 这里的key是一个巧妙的设计:user:{id}:{field}
127.0.0.1:6379> mset user:2:name lisi user:2:age 3
OK
127.0.0.1:6379> get user:1 # key为"user:1"
"{name:zhangsan,age:2}"
127.0.0.1:6379> get user:2:name # key为"user:2:name"
"lisi"
|
getset 先get再set
1
2
3
4
5
6
7
8
| 127.0.0.1:6379> getset db redis # 无值则返回nil
(nil)
127.0.0.1:6379> getset db redis
"redis"
127.0.0.1:6379> getset db mongodb
"redis"
127.0.0.1:6379> getset db mongodb
"mongodb"
|
小结
String类似的使用场景,value可以是字符串还可以是数字
- 计数器
- 统计多单位的数量 uid:923456:follow 0
- 粉丝数
- 对象缓存存储
List
可以实现队列、阻塞队列与栈的功能
所有的list命令都是以l开头的
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
35
36
37
38
39
40
| 127.0.0.1:6379> lpush list1 "one" # 将一个或者多个值插入到列表头部,即左边
(integer) 1
127.0.0.1:6379> lpush list1 "two"
(integer) 2
127.0.0.1:6379> lpush list1 "two"
(integer) 3
127.0.0.1:6379> keys *
1) "list1"
127.0.0.1:6379> lrange list1 0 -1 # 获取所有值
1) "two"
2) "two"
3) "one"
127.0.0.1:6379> lrange list1 0 1 # 获取指定区间的值
1) "two"
2) "two"
127.0.0.1:6379> rpush list1 "from right" #将一个或者多个值插入到列表尾部,即右边
(integer) 4
127.0.0.1:6379> lrange list1 0 -1
1) "two"
2) "two"
3) "one"
4) "from right"
127.0.0.1:6379> LRANGE list1 0 -1
1) "two"
2) "two"
3) "one"
4) "from right"
127.0.0.1:6379> lpop list1 2 # 从头部移除列表两个值
1) "two"
2) "two"
127.0.0.1:6379> rpop list1 # 从尾部移除列表值,默认一个
"from right"
127.0.0.1:6379> LRANGE list1 0 -1
1) "one"
127.0.0.1:6379> lindex list1 0 # 根据列表索引下标取值
"one"
127.0.0.1:6379> llen list1 # 获取列表长度
(integer) 1
|
1
2
3
4
5
6
7
8
| 127.0.0.1:6379> lrange list1 0 -1
1) "four"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list1 2 four # 移除指定个数的指定key的值
(integer) 2
|
1
2
3
4
5
6
7
8
9
10
| 127.0.0.1:6379> LRANGE list1 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
4) "hello"
127.0.0.1:6379> ltrim list1 1 2 # 通过下标截取指定的长度,并对自身做出修改
OK
127.0.0.1:6379> LRANGE list1 0 -1
1) "hello2"
2) "hello1"
|
rpoplpush 移除列表最后一个元素,将其添加到新列表中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 127.0.0.1:6379> lpush list "hello"
(integer) 1
127.0.0.1:6379> lpush list "hello1"
(integer) 2
127.0.0.1:6379> lpush list "hello2"
(integer) 3
127.0.0.1:6379> lpush list "hello3"
(integer) 4
127.0.0.1:6379> lpush list "hello4"
(integer) 5
127.0.0.1:6379> rpoplpush list list1
"hello"
127.0.0.1:6379> lrange list 0 -1
1) "hello4"
2) "hello3"
3) "hello2"
4) "hello1"
127.0.0.1:6379> lrange list1 0 -1
1) "hello"
|
lset将列表中指定下标的值替换为另外一个值,相当于更新操作
1
2
3
4
5
6
7
8
9
10
11
12
| 127.0.0.1:6379> exists list
(integer) 0
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 newvalue
OK
127.0.0.1:6379> lrange list 0 0
1) "newvalue"
127.0.0.1:6379> lset list 1 newvalue
(error) ERR index out of range
|
linsert将某个具体的value插入列表中某个具体的元素的前面或者后面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| 127.0.0.1:6379> lpush list value
(integer) 1
127.0.0.1:6379> lpush list value1
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value"
127.0.0.1:6379> linsert list before "value1" "before"
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "before"
2) "value1"
3) "value"
127.0.0.1:6379> linsert list after "value1" "after"
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "before"
2) "value1"
3) "after"
4) "value"
|
小结
- list实际上是一个链表,before,after,left,right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在!
- 在两边插入值或者改动值,效率最高,如果是中间元素,相对来说效率会低一些
Set
set中的值是不能重复的,且是无序的
sadd, smembers, sismember, scard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 127.0.0.1:6379> sadd myset "hello" # set集合中添加值
(integer) 1
127.0.0.1:6379> sadd myset "world" "qimignton"
(integer) 2
127.0.0.1:6379> smembers myset # 查看指定set中的现有值
1) "world"
2) "qimignton"
3) "hello"
127.0.0.1:6379> sismember myset "hi" # 判断某一个值是不是在set集合中
(integer) 0
127.0.0.1:6379> sismember myset "hello"
(integer) 1
127.0.0.1:6379> scard myset # 查看set集合中内容元素的个数
(integer) 3
|
srem移除set集合中的指定元素
1
2
3
4
5
6
7
8
9
| 127.0.0.1:6379> smembers myset
1) "world"
2) "qimignton"
3) "hello"
127.0.0.1:6379> srem myset "hello"
(integer) 1
127.0.0.1:6379> smembers myset
1) "world"
2) "qimignton"
|
spop随机删除set中的若干个值,默认1个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 127.0.0.1:6379> smembers myset
1) "welcome"
2) "hello"
3) "the"
4) "place"
5) "world"
6) "qimington"
7) "to"
127.0.0.1:6379> spop myset 2
1) "world"
2) "welcome"
127.0.0.1:6379> smembers myset
1) "the"
2) "place"
3) "qimington"
4) "to"
5) "hello"
|
srandmember随机获取set集合中的若干个值(默认为1)
1
2
3
4
5
| 127.0.0.1:6379> srandmember myset
"world"
127.0.0.1:6379> srandmember myset 2
1) "world"
2) "hello"
|
smove实现集合间元素移动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 127.0.0.1:6379> smembers myset
1) "the"
2) "place"
3) "qimington"
4) "to"
5) "hello"
127.0.0.1:6379> smembers myset2
1) "set2"
127.0.0.1:6379> smove myset myset2 "the" # 将一个指定的值移动到另外一个set集合
(integer) 1
127.0.0.1:6379> smembers myset
1) "place"
2) "qimington"
3) "to"
4) "hello"
127.0.0.1:6379> smembers myset2
1) "the"
2) "set2"
|
集合的sinter(交)、sunion(并)、sdiff(差)操作
sinter(交)可以实现共同用户的查找,或者二度好友(即好友推荐)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 127.0.0.1:6379> smembers set1
1) "world"
2) "qimington"
3) "hello"
127.0.0.1:6379> smembers set2
1) "moto"
2) "qimington"
3) "hello"
127.0.0.1:6379> sdiff set1 set2 # 差集
1) "world"
127.0.0.1:6379> sinter set1 set2 # 交集
1) "qimington"
2) "hello"
127.0.0.1:6379> sunion set1 set2 # 并集
1) "moto"
2) "qimington"
3) "hello"
4) "world"
|
Hash
Map集合,即key–。本质和String类型没有太大区别,还是简单的key-value
hset, hget, hmget, hgetall, hdel, hlen, hexists, hkeys, hvals
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
| 127.0.0.1:6379> hset myhash field1 "qimington"
(integer) 1
127.0.0.1:6379> hget myhash field1
"qimington"
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
127.0.0.1:6379> hmget myhash field1 field2 # 获取多个字段
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash # 获取所有数据
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1 # 删除hash指定的key字段,对应的value值也就消失了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
127.0.0.1:6379> hlen myhash # 查询hash表的字段数量,这里只有一个键值对
(integer) 1
127.0.0.1:6379> hexists myhash field1 # 判断hash中指定字段是否存在
(integer) 0
127.0.0.1:6379> hexists myhash field2
(integer) 1
127.0.0.1:6379> hkeys myhash # 只获取所有的field
1) "field2"
127.0.0.1:6379> hvals myhash # 只获取所有的value
1) "world"
|
hincrby
1
2
3
4
5
6
| 127.0.0.1:6379> hset myhash field 5
(integer) 1
127.0.0.1:6379> hincrby myhash field 1
(integer) 6
127.0.0.1:6379> hincrby myhash field -1
(integer) 5
|
hsetnx
1
2
3
4
| 127.0.0.1:6379> hsetnx myhash field1 hello # 如果不存在则可以设置,否则不可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field1 hello
(integer) 0
|
小结
Zset(有序集合)
在set的基础上,增加了一个值,sadd k1 v1
=> zadd k1 score1 v1
zadd, zrange
1
2
3
4
5
6
7
8
| 127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 1 two 3 three
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
|
zrangebyscore 升序排序 zrevrangebyscore降序排列
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
35
36
37
38
39
| 127.0.0.1:6379> zadd salary 2500 xiaohong # 添加三个
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 lisi
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "xiaohong"
3) "zhangsan"
# ZRANGEBYSCORE key min max [withscores]
127.0.0.1:6379> ZRANGEBYSCORE salary -inf inf # 显示全部用户 从小到大
1) "lisi"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf inf withscores # 显示全部用户,并显示详细信息
1) "lisi"
2) "500"
3) "xiaohong"
4) "2500"
5) "zhangsan"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores # 显示小于等于2500的升序
1) "lisi"
2) "500"
3) "xiaohong"
4) "2500"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf (2500 withscores # 显示小于2500的升序
1) "lisi"
2) "500"
# ZREVRANGEBYSCORE key max min [withscores]
127.0.0.1:6379> ZREVRANGEBYSCORE salary inf -inf withscores # 显示全部用户 从大到小
1) "zhangsan"
2) "5000"
3) "xiaohong"
4) "2500"
5) "lisi"
6) "500"
|
rem移除指定元素 zcard获取个数 zcount计数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaohong
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "lisi"
2) "zhangsan"
127.0.0.1:6379> zcard salary
(integer) 2
127.0.0.1:6379> zrangebyscore salary -inf inf withscores
1) "lisi"
2) "500"
3) "zhangsan"
4) "5000"
127.0.0.1:6379> zcount salary 0 2000 # 查询再0与2000之间的值的个数
(integer) 1
|
小结
set排序,存储班级成绩表,工资表排序
- 重要消息
- 带权重的判断
- 排行榜,Top N测试