数据库引擎网址https://db-engines.com/en/,有不同类型的数据库对比,架构师有个很重要的能力就是技术选型和技术对比。
Redis英文网址:https://redis.io/
Redis中文网址:http://redis.cn/

Redis的数据模型以Key、value的形式存储的。支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets)bitmaps。支持的类型指的是value。
Redis - 图1

对比Memcache

Memcache也是key、value的形式存放数据,最重要的不同是Memcache的value没有类型,而Redis有类型。这就导致Memcache传输数据的带宽和IO销毁非常大,怎么理解这句话?比如Memcache和Redis中存储的是如下JSON数据

  1. {
  2. "hobby":["打篮球","踢足球","羽毛球"]
  3. }

我们需要拿出hobby里面的第一个元素”打篮球”返回给调用者(客户端)
Redis - 图2
这种思想就是:计算向数据移动。

使用

Redis像MYSQL一样是有库的概念的,默认从0开始编号到16。库与库之间是隔离的互相看不到对方的数据。
Redis - 图3

String相关操作

面向字符串的操作

  1. 127.0.0.1:6379> set keyxx:1 hahaha //在1号库里面存放数据key为keyxx value为:hahaha
  2. OK
  3. 127.0.0.1:6379> get keyxx //默认从0号库获取数据,库与库之间是隔离的所以获取不到
  4. (nil)
  5. 127.0.0.1:6379> get keyxx:1 //从1号库里面获取数据
  6. "hahaha"

切换9号库

  1. 127.0.0.1:6379> select 9
  2. OK
  3. 127.0.0.1:6379[9]>

nx(not exisit)表示不存在k1的时候才会设置(相当于新建)

  1. 127.0.0.1:6379[9]> set k1 v1 nx
  2. OK
  3. 127.0.0.1:6379[9]> get k1
  4. "v1"

xx表示只有存在的时候才会设置(相当于更新)

  1. 127.0.0.1:6379> set k2 v2 xx
  2. (nil)
  3. 127.0.0.1:6379> get k2
  4. (nil)

mset、mget

  1. 127.0.0.1:6379> mset k3 v3 k4 v4
  2. OK
  3. 127.0.0.1:6379> get k3
  4. "v3"
  5. 127.0.0.1:6379> get k4
  6. "v4"
  1. 127.0.0.1:6379> mget k3 k4
  2. 1) "v3"
  3. 2) "v4"

append

  1. 127.0.0.1:6379> get k3
  2. "v3"
  3. 127.0.0.1:6379> append k3 haha
  4. (integer) 6
  5. 127.0.0.1:6379> get k3
  6. "v3haha"

getrange、setrange

  1. 127.0.0.1:6379> get k3
  2. "v3haha"
  3. 127.0.0.1:6379>
  4. 127.0.0.1:6379> getrange k3 2 6
  5. "haha"
  6. 127.0.0.1:6379> getrange k3 2 5
  7. "haha"

正向索引和反向索引,以字符串abcdef为例
Redis - 图4

  1. 127.0.0.1:6379> get k3
  2. "v3haha"
  3. 127.0.0.1:6379> getrange k3 -6 -5
  4. "v3"
  5. 127.0.0.1:6379> getrange k3 0 1
  6. "v3"
  7. 127.0.0.1:6379> getrange k3 0 -5
  8. "v3"
  9. 127.0.0.1:6379> setrange k3 2 xxx
  10. (integer) 6
  11. 127.0.0.1:6379> get k3
  12. "v3xxxa"

strlen

  1. 127.0.0.1:6379> get k3
  2. "v3xxxa"
  3. 127.0.0.1:6379> strlen k3
  4. (integer) 6

type命令查看key对应的value类型

  1. 127.0.0.1:6379> help set
  2. SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
  3. summary: Set the string value of a key
  4. since: 1.0.0
  5. group: string

set命令属于String组里面,那边通过set设置key的value的时候,应该也是string类型

  1. 127.0.0.1:6379> get k1
  2. "100"
  3. 127.0.0.1:6379> type k1
  4. string
  5. 127.0.0.1:6379> object encoding k1
  6. "int"

面向数值的操作

可以对int这种编码类型的数据进行计算操作,比如incr、incrby、decr、decrby、incrbyfloat

  1. 127.0.0.1:6379> incr k1
  2. (integer) 101
  3. 127.0.0.1:6379> incrby k1 3
  4. (integer) 104
  5. 127.0.0.1:6379> decr k1
  6. (integer) 103
  7. 127.0.0.1:6379> decrby k1 3
  8. (integer) 100
  9. 127.0.0.1:6379> incrbyfloat k1 0.5
  10. "100.5"

面向bitmap的操作

setbit
  1. 127.0.0.1:6379> help setbit
  2. SETBIT key offset value
  3. summary: Sets or clears the bit at offset in the string value stored at key
  4. since: 2.2.0
  5. group: string

一个字节有8个二进制位,字节有索引的概念、二进制位也有索引的概念。
Redis - 图5

setbit命令里面的offset指的是二进制位的索引,二进制位的值只能是0或者1。所以setbit设置的value也只能是0或者1

  1. 127.0.0.1:6379> setbit k1 1 1
  2. (integer) 0
  3. 127.0.0.1:6379> strlen k1
  4. (integer) 1
  5. 127.0.0.1:6379> get k1
  6. "@"

Redis存储的数据都是按照字节流存储的,上面的含义是把偏移量的第1位设置成1。二进制表示就是
0 1 0 0 0 0 0 0
继续操作

  1. 127.0.0.1:6379> setbit k1 7 1
  2. (integer) 0
  3. 127.0.0.1:6379> strlen k1
  4. (integer) 1
  5. 127.0.0.1:6379> get k1
  6. "A"

相当于又在第7位设置成1。对应的二进制数据为
0 1 0 0 0 0 0 1
继续操作

  1. 127.0.0.1:6379> setbit k1 9 1
  2. (integer) 0
  3. 127.0.0.1:6379> strlen k1
  4. (integer) 2
  5. 127.0.0.1:6379> get k1
  6. "A@"

相当于在索引9位置设置成1,9个bit位已经超过一个字节,所以需要两个字节存储。对应的二进制位为
0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0

bitpos
  1. 127.0.0.1:6379> help bitpos
  2. BITPOS key bit [start] [end]
  3. summary: Find first bit set or clear in a string
  4. since: 2.8.7
  5. group: string

查找一个bit ,bit只能是0或者1,start和end表示的是字节的索引不是二进制的索引。返回要找bit的第一个位置。

  1. 127.0.0.1:6379> bitpos k1 1 0 1
  2. (integer) 1

k1的二进制位为:0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0
从第0个字节到第1个字节查找bit 为1的位置。

  1. 127.0.0.1:6379> bitpos k1 1 1 1
  2. (integer) 9

k1的二进制位为:0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0
从第1个字节到第1个字节查找bit 为1的位置。注意这次返回的是整个k1对应的二进制位1的位置

bitcount
  1. 127.0.0.1:6379> help bitcount
  2. BITCOUNT key [start end]
  3. summary: Count set bits in a string
  4. since: 2.6.0
  5. group: string

表示返回1这个bit的个数,[start end]指的是字节的索引而不是二进制位的索引

  1. 127.0.0.1:6379> bitcount k1 0 1
  2. (integer) 3
  3. 127.0.0.1:6379> bitcount k1 0 0
  4. (integer) 2
  5. 127.0.0.1:6379> bitcount k1 1 1
  6. (integer) 1

bitop
  1. 127.0.0.1:6379> help bitop
  2. BITOP operation destkey key [key ...]
  3. summary: Perform bitwise operations between strings
  4. since: 2.6.0
  5. group: string

按位逻辑操作比如& | 运算。operation表示逻辑符,destkey表示逻辑运算结果存放的地方。

  1. 127.0.0.1:6379> setbit k2 1 1
  2. (integer) 0
  3. 127.0.0.1:6379> get k2
  4. "@"
  5. 127.0.0.1:6379> setbit k3 1 1
  6. (integer) 0
  7. 127.0.0.1:6379> get k3
  8. "@"
  9. 127.0.0.1:6379> bitop and andkey k2 k3
  10. (integer) 1
  11. 127.0.0.1:6379> get andkey
  12. "@"

List

双向链表结构

lpush

  1. 127.0.0.1:6379> help lpush
  2. LPUSH key element [element ...]
  3. summary: Prepend one or multiple elements to a list
  4. since: 1.0.0
  5. group: list

从链表的左边开始添加元素到List中

rpush

  1. 127.0.0.1:6379> help rpush
  2. RPUSH key element [element ...]
  3. summary: Append one or multiple elements to a list
  4. since: 1.0.0
  5. group: list

从链表的右侧添加元素

lpop

  1. 127.0.0.1:6379> help lpop
  2. LPOP key [count]
  3. summary: Remove and get the first elements in a list
  4. since: 1.0.0
  5. group: list

从链表的左侧移除一个元素,并把移除的元素返回。

rpop

  1. 127.0.0.1:6379> help rpop
  2. RPOP key [count]
  3. summary: Remove and get the last elements in a list
  4. since: 1.0.0
  5. group: list

从链表的右侧移除一个元素并把移除的元素返回。

实现栈操作

  1. 127.0.0.1:6379> lpush k5 a b c d e f
  2. 127.0.0.1:6379> lpop k5
  3. "f"
  4. 127.0.0.1:6379> lpop k5
  5. "e"
  6. 127.0.0.1:6379> lpop k5
  7. "d"
  8. 127.0.0.1:6379> lpop k5
  9. "c"
  10. 127.0.0.1:6379> lpop k5
  11. "b"
  12. 127.0.0.1:6379> lpop k5
  13. "a"
  14. 127.0.0.1:6379> lpop k5
  15. (nil)
  1. 127.0.0.1:6379> rpush k6 a b c d e f
  2. 127.0.0.1:6379> rpop k6
  3. "f"
  4. 127.0.0.1:6379> rpop k6
  5. "e"
  6. 127.0.0.1:6379> rpop k6
  7. "d"
  8. 127.0.0.1:6379> rpop k6
  9. "c"
  10. 127.0.0.1:6379> rpop k6
  11. "b"
  12. 127.0.0.1:6379> rpop k6
  13. "a"
  14. 127.0.0.1:6379> rpop k6
  15. (nil)

使用lpush、lpop 和rpush、rpop这种同方向的命令能够实现栈的操作。

实现队列的操作

  1. 127.0.0.1:6379> lpush k5 a b c d e f
  2. (integer) 6
  3. 127.0.0.1:6379> rpop k5
  4. "a"
  5. 127.0.0.1:6379> rpop k5
  6. "b"
  7. 127.0.0.1:6379> rpop k5
  8. "c"
  9. 127.0.0.1:6379> rpop k5
  10. "d"
  11. 127.0.0.1:6379> rpop k5
  12. "e"
  13. 127.0.0.1:6379> rpop k5
  14. "f"
  15. 127.0.0.1:6379> rpop k5
  16. (nil)
  1. 127.0.0.1:6379> rpush k6 a b c d e f
  2. (integer) 6
  3. 127.0.0.1:6379> lpop k6
  4. "a"
  5. 127.0.0.1:6379> lpop k6
  6. "b"
  7. 127.0.0.1:6379> lpop k6
  8. "c"
  9. 127.0.0.1:6379> lpop k6
  10. "d"
  11. 127.0.0.1:6379> lpop k6
  12. "e"
  13. 127.0.0.1:6379> lpop k6
  14. "f"
  15. 127.0.0.1:6379> lpop k6
  16. (nil)

使用lpush、rpop 和rpush、lpop这种反方向的命令能够实现队列的操作。

lrange获取列表元素

  1. 127.0.0.1:6379> help lrange
  2. LRANGE key start stop
  3. summary: Get a range of elements from a list
  4. since: 1.0.0
  5. group: list

和字符串一样,链表List也为每个节点维护索引值。
Redis - 图6

  1. 127.0.0.1:6379> rpush k6 a b c d e f
  2. 127.0.0.1:6379> lrange k6 0 -1
  3. 1) "a"
  4. 2) "b"
  5. 3) "c"
  6. 4) "d"
  7. 5) "e"
  8. 6) "f"

lindex 取出列表里面的一个元素

  1. 127.0.0.1:6379> lindex k6 -1
  2. "f"
  3. 127.0.0.1:6379> lindex k6 0
  4. "a"

lset 设置一个元素

  1. 127.0.0.1:6379> help lset
  2. LSET key index element
  3. summary: Set the value of an element in a list by its index
  4. since: 1.0.0
  5. group: list
  1. 127.0.0.1:6379> lset k6 0 xxx
  2. OK
  3. 127.0.0.1:6379> lrange k6 0 -1
  4. 1) "xxx"
  5. 2) "b"
  6. 3) "c"
  7. 4) "d"
  8. 5) "e"
  9. 6) "f"

lrem

  1. 127.0.0.1:6379> help lrem
  2. LREM key count element
  3. summary: Remove elements from a list
  4. since: 1.0.0
  5. group: list
  1. 127.0.0.1:6379> lpush k7 1 2 3 1 2 1
  2. (integer) 6
  3. 127.0.0.1:6379> lrange k7 0 -1
  4. 1) "1"
  5. 2) "2"
  6. 3) "1"
  7. 4) "3"
  8. 5) "2"
  9. 6) "1"
  10. 127.0.0.1:6379> lrem k7 2 1
  11. (integer) 2
  12. 127.0.0.1:6379> lrange k7 0 -1
  13. 1) "2"
  14. 2) "3"
  15. 3) "2"
  16. 4) "1"
  17. 127.0.0.1:6379>
  1. 127.0.0.1:6379> help linsert
  2. LINSERT key BEFORE|AFTER pivot element
  3. summary: Insert an element before or after another element in a list
  4. since: 2.2.0
  5. group: list

blpop

  1. 127.0.0.1:6379> help blpop
  2. BLPOP key [key ...] timeout
  3. summary: Remove and get the first element in a list, or block until one is available
  4. since: 2.0.0
  5. group: list

如果超时时间设置为0,没有拿到key里面的数据会一直阻塞,直到拿到数据为值。而且先阻塞的客户端先拿到数据。比如3个客户端同时执行上面的命令,当有数据的时候,先阻塞的客户端先拿到数据

ltrim

  1. 127.0.0.1:6379> help ltrim
  2. LTRIM key start stop
  3. summary: Trim a list to the specified range
  4. since: 1.0.0
  5. group: list

删除给定范围外两端的元素

  1. 127.0.0.1:6379> lrange k7 0 -1
  2. 1) "2"
  3. 2) "3"
  4. 3) "2"
  5. 4) "1"
  6. 127.0.0.1:6379> ltrim k7 1 -2
  7. OK
  8. 127.0.0.1:6379> lrange k7 0 -1
  9. 1) "3"
  10. 2) "2"
  11. 127.0.0.1:6379>

hash

类似hashmap

  1. 127.0.0.1:6379> help hset
  2. HSET key field value [field value ...]
  3. summary: Set the string value of a hash field
  4. since: 2.0.0
  5. group: hash
  6. 127.0.0.1:6379> help hmset
  7. HMSET key field value [field value ...]
  8. summary: Set multiple hash fields to multiple values
  9. since: 2.0.0
  10. group: hash
  1. 127.0.0.1:6379> hset person name lff
  2. (integer) 1
  3. 127.0.0.1:6379> hmset person age 18 weight 155
  4. OK
  5. 127.0.0.1:6379> hget person name
  6. "lff"
  7. 127.0.0.1:6379> hmget person age weight
  8. 1) "18"
  9. 2) "155"
  10. 127.0.0.1:6379> hkeys person
  11. 1) "name"
  12. 2) "age"
  13. 3) "weight"
  14. 127.0.0.1:6379> hvals person
  15. 1) "lff"
  16. 2) "18"
  17. 3) "155"
  18. 127.0.0.1:6379> hgetall person
  19. 1) "name"
  20. 2) "lff"
  21. 3) "age"
  22. 4) "18"
  23. 5) "weight"
  24. 6) "155"
  25. 127.0.0.1:6379> hincrbyfloat person age 0.5
  26. "18.5"
  27. 127.0.0.1:6379> hget person age
  28. "18.5"
  29. 127.0.0.1:6379> hincrbyfloat person age -1
  30. "17.5"
  31. 127.0.0.1:6379> hget person age
  32. "17.5"

set

特点:无序、去重。

  1. 127.0.0.1:6379> help sadd
  2. SADD key member [member ...]
  3. summary: Add one or more members to a set
  4. since: 1.0.0
  5. group: set
  1. 127.0.0.1:6379> sadd set_test a b c a b c
  2. (integer) 3
  3. 127.0.0.1:6379> smembers set_test
  4. 1) "c"
  5. 2) "b"
  6. 3) "a"
  7. 127.0.0.1:6379> srem set_test a
  8. (integer) 1
  9. 127.0.0.1:6379> smembers set_test
  10. 1) "c"
  11. 2) "b"

sinter 、sinterstore交集

  1. 127.0.0.1:6379> help sinter
  2. SINTER key [key ...]
  3. summary: Intersect multiple sets
  4. since: 1.0.0
  5. group: set
  6. 127.0.0.1:6379> help sinterstore
  7. SINTERSTORE destination key [key ...]
  8. summary: Intersect multiple sets and store the resulting set in a key
  9. since: 1.0.0
  10. group: set

sinter取交集,结果直接返回客户端,会走网卡。sinterstore取交集,结果存在一个新的key里面,不走网卡。

  1. 127.0.0.1:6379> sadd kset1 a b c d
  2. (integer) 4
  3. 127.0.0.1:6379> sadd kset2 a b d f
  4. (integer) 4
  5. 127.0.0.1:6379> smembers kset1
  6. 1) "d"
  7. 2) "c"
  8. 3) "b"
  9. 4) "a"
  10. 127.0.0.1:6379> smembers kset2
  11. 1) "d"
  12. 2) "b"
  13. 3) "a"
  14. 4) "f"
  15. 127.0.0.1:6379> sinter kset1 kset2
  16. 1) "d"
  17. 2) "b"
  18. 3) "a"
  19. 127.0.0.1:6379> sinterstore kset3 kset1 kset2
  20. (integer) 3
  21. 127.0.0.1:6379> smembers kset3
  22. 1) "d"
  23. 2) "a"
  24. 3) "b"

sunion、sunionstore并集

  1. 127.0.0.1:6379> help sunion
  2. SUNION key [key ...]
  3. summary: Add multiple sets
  4. since: 1.0.0
  5. group: set

sunion取并集直接返回,sunionstore取并集,结果存放一个新的key里面

  1. 127.0.0.1:6379> sunion kset1 kset2
  2. 1) "d"
  3. 2) "c"
  4. 3) "b"
  5. 4) "a"
  6. 5) "f"
  7. 127.0.0.1:6379> sunionstore kset4 kset1 kset2
  8. (integer) 5
  9. 127.0.0.1:6379> smembers kset4
  10. 1) "d"
  11. 2) "c"
  12. 3) "b"
  13. 4) "a"
  14. 5) "f"

sorted set

给出一系列元素进行排序,应该按照什么方式排序?
比如:苹果、香蕉、橙子 是按照名称排序、还是按照大小排序、还是按照含糖量排序。所以sorted set里面引入一个分值的概念用来对元素进行排序。

有序set

  1. 127.0.0.1:6379> help zadd
  2. ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
  3. summary: Add one or more members to a sorted set, or update its score if it already exists
  4. since: 1.2.0
  5. group: sorted_set
  1. 127.0.0.1:6379> zadd zk1 3 apple 7 bannana 1 orange
  2. (integer) 3
  3. 127.0.0.1:6379> zrange zk1 0 -1
  4. 1) "orange"
  5. 2) "apple"
  6. 3) "bannana"
  7. 127.0.0.1:6379> zrange zk1 0 -1 withscores
  8. 1) "orange"
  9. 2) "1"
  10. 3) "apple"
  11. 4) "3"
  12. 5) "bannana"
  13. 6) "7"

按照分值范围取数据

  1. 127.0.0.1:6379> zrangebyscore zk1 3 7
  2. 1) "apple"
  3. 2) "bannana"

zrevrange逆序取数据

取出前两个最大的元素

  1. 127.0.0.1:6379> zrange zk1 0 -1 withscores
  2. 1) "orange"
  3. 2) "1"
  4. 3) "apple"
  5. 4) "3"
  6. 5) "bannana"
  7. 6) "7"
  8. 127.0.0.1:6379> zrevrange zk1 0 1
  9. 1) "bannana"
  10. 2) "apple"

获取分值和排名

  1. 127.0.0.1:6379> help zscore
  2. ZSCORE key member
  3. summary: Get the score associated with the given member in a sorted set
  4. since: 1.2.0
  5. group: sorted_set
  6. 127.0.0.1:6379> help zrank
  7. ZRANK key member
  8. summary: Determine the index of a member in a sorted set
  9. since: 2.0.0
  10. group: sorted_set
  1. 127.0.0.1:6379> zscore zk1 apple
  2. "3"
  3. 127.0.0.1:6379> zrank zk1 apple
  4. (integer) 1

zincrby

给sorted set 集合某一个元素的分值增加,增加后也实时维护其在集合里面的顺序

  1. 127.0.0.1:6379> help zincrby
  2. ZINCRBY key increment member
  3. summary: Increment the score of a member in a sorted set
  4. since: 1.2.0
  5. group: sorted_set
  1. 127.0.0.1:6379> zrange zk1 0 -1 withscores
  2. 1) "orange"
  3. 2) "1"
  4. 3) "apple"
  5. 4) "3"
  6. 5) "bannana"
  7. 6) "7"
  8. 127.0.0.1:6379> zincrby zk1 3 orange
  9. "4"
  10. 127.0.0.1:6379> zrange zk1 0 -1 withscores
  11. 1) "apple"
  12. 2) "3"
  13. 3) "orange"
  14. 4) "4"
  15. 5) "bannana"
  16. 6) "7"

zunionstore

  1. 127.0.0.1:6379> help zunionstore
  2. ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
  3. summary: Add multiple sorted sets and store the resulting sorted set in a new key
  4. since: 2.0.0
  5. group: sorted_set

默认是sum排序,相同集合里面的元素求和

  1. 127.0.0.1:6379> zadd k1 60 jack 80 rose 100 yoga
  2. (integer) 3
  3. 127.0.0.1:6379> zadd k2 40 jack 20 rose 60 cliff
  4. (integer) 3
  5. 127.0.0.1:6379> zunionstore k3 2 k1 k2 //2为key的个数,这里key有两个k1、k2
  6. (integer) 4
  7. 127.0.0.1:6379> zrange k3 0 -1 withscores
  8. 1) "cliff"
  9. 2) "60"
  10. 3) "jack"
  11. 4) "100"
  12. 5) "rose"
  13. 6) "100"
  14. 7) "yoga"
  15. 8) "100"

可以给权重进行排序,k2给的权重是0.5,合并的时候k2集合里面的分值都会0.5倍

  1. 127.0.0.1:6379> zunionstore k3 2 k1 k2 weights 1 0.5
  2. (integer) 4
  3. 127.0.0.1:6379> zrange k3 0 -1 withscores
  4. 1) "cliff"
  5. 2) "30"
  6. 3) "jack"
  7. 4) "80"
  8. 5) "rose"
  9. 6) "90"
  10. 7) "yoga"
  11. 8) "100"