数据库引擎网址https://db-engines.com/en/,有不同类型的数据库对比,架构师有个很重要的能力就是技术选型和技术对比。
Redis英文网址:https://redis.io/
Redis中文网址:http://redis.cn/
Redis的数据模型以Key、value的形式存储的。支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)、 bitmaps。支持的类型指的是value。
对比Memcache
Memcache也是key、value的形式存放数据,最重要的不同是Memcache的value没有类型,而Redis有类型。这就导致Memcache传输数据的带宽和IO销毁非常大,怎么理解这句话?比如Memcache和Redis中存储的是如下JSON数据
{"hobby":["打篮球","踢足球","羽毛球"]}
我们需要拿出hobby里面的第一个元素”打篮球”返回给调用者(客户端)
这种思想就是:计算向数据移动。
使用
Redis像MYSQL一样是有库的概念的,默认从0开始编号到16。库与库之间是隔离的互相看不到对方的数据。
String相关操作
面向字符串的操作
127.0.0.1:6379> set keyxx:1 hahaha //在1号库里面存放数据key为keyxx value为:hahahaOK127.0.0.1:6379> get keyxx //默认从0号库获取数据,库与库之间是隔离的所以获取不到(nil)127.0.0.1:6379> get keyxx:1 //从1号库里面获取数据"hahaha"
切换9号库
127.0.0.1:6379> select 9OK127.0.0.1:6379[9]>
nx(not exisit)表示不存在k1的时候才会设置(相当于新建)
127.0.0.1:6379[9]> set k1 v1 nxOK127.0.0.1:6379[9]> get k1"v1"
xx表示只有存在的时候才会设置(相当于更新)
127.0.0.1:6379> set k2 v2 xx(nil)127.0.0.1:6379> get k2(nil)
mset、mget
127.0.0.1:6379> mset k3 v3 k4 v4OK127.0.0.1:6379> get k3"v3"127.0.0.1:6379> get k4"v4"
127.0.0.1:6379> mget k3 k41) "v3"2) "v4"
append
127.0.0.1:6379> get k3"v3"127.0.0.1:6379> append k3 haha(integer) 6127.0.0.1:6379> get k3"v3haha"
getrange、setrange
127.0.0.1:6379> get k3"v3haha"127.0.0.1:6379>127.0.0.1:6379> getrange k3 2 6"haha"127.0.0.1:6379> getrange k3 2 5"haha"
正向索引和反向索引,以字符串abcdef为例
127.0.0.1:6379> get k3"v3haha"127.0.0.1:6379> getrange k3 -6 -5"v3"127.0.0.1:6379> getrange k3 0 1"v3"127.0.0.1:6379> getrange k3 0 -5"v3"127.0.0.1:6379> setrange k3 2 xxx(integer) 6127.0.0.1:6379> get k3"v3xxxa"
strlen
127.0.0.1:6379> get k3"v3xxxa"127.0.0.1:6379> strlen k3(integer) 6
type命令查看key对应的value类型
127.0.0.1:6379> help setSET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]summary: Set the string value of a keysince: 1.0.0group: string
set命令属于String组里面,那边通过set设置key的value的时候,应该也是string类型
127.0.0.1:6379> get k1"100"127.0.0.1:6379> type k1string127.0.0.1:6379> object encoding k1"int"
面向数值的操作
可以对int这种编码类型的数据进行计算操作,比如incr、incrby、decr、decrby、incrbyfloat
127.0.0.1:6379> incr k1(integer) 101127.0.0.1:6379> incrby k1 3(integer) 104127.0.0.1:6379> decr k1(integer) 103127.0.0.1:6379> decrby k1 3(integer) 100127.0.0.1:6379> incrbyfloat k1 0.5"100.5"
面向bitmap的操作
setbit
127.0.0.1:6379> help setbitSETBIT key offset valuesummary: Sets or clears the bit at offset in the string value stored at keysince: 2.2.0group: string
一个字节有8个二进制位,字节有索引的概念、二进制位也有索引的概念。
setbit命令里面的offset指的是二进制位的索引,二进制位的值只能是0或者1。所以setbit设置的value也只能是0或者1
127.0.0.1:6379> setbit k1 1 1(integer) 0127.0.0.1:6379> strlen k1(integer) 1127.0.0.1:6379> get k1"@"
Redis存储的数据都是按照字节流存储的,上面的含义是把偏移量的第1位设置成1。二进制表示就是
0 1 0 0 0 0 0 0
继续操作
127.0.0.1:6379> setbit k1 7 1(integer) 0127.0.0.1:6379> strlen k1(integer) 1127.0.0.1:6379> get k1"A"
相当于又在第7位设置成1。对应的二进制数据为
0 1 0 0 0 0 0 1
继续操作
127.0.0.1:6379> setbit k1 9 1(integer) 0127.0.0.1:6379> strlen k1(integer) 2127.0.0.1:6379> get k1"A@"
相当于在索引9位置设置成1,9个bit位已经超过一个字节,所以需要两个字节存储。对应的二进制位为
0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0
bitpos
127.0.0.1:6379> help bitposBITPOS key bit [start] [end]summary: Find first bit set or clear in a stringsince: 2.8.7group: string
查找一个bit ,bit只能是0或者1,start和end表示的是字节的索引不是二进制的索引。返回要找bit的第一个位置。
127.0.0.1:6379> bitpos k1 1 0 1(integer) 1
k1的二进制位为:0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0
从第0个字节到第1个字节查找bit 为1的位置。
127.0.0.1:6379> bitpos k1 1 1 1(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
127.0.0.1:6379> help bitcountBITCOUNT key [start end]summary: Count set bits in a stringsince: 2.6.0group: string
表示返回1这个bit的个数,[start end]指的是字节的索引而不是二进制位的索引
127.0.0.1:6379> bitcount k1 0 1(integer) 3127.0.0.1:6379> bitcount k1 0 0(integer) 2127.0.0.1:6379> bitcount k1 1 1(integer) 1
bitop
127.0.0.1:6379> help bitopBITOP operation destkey key [key ...]summary: Perform bitwise operations between stringssince: 2.6.0group: string
按位逻辑操作比如& | 运算。operation表示逻辑符,destkey表示逻辑运算结果存放的地方。
127.0.0.1:6379> setbit k2 1 1(integer) 0127.0.0.1:6379> get k2"@"127.0.0.1:6379> setbit k3 1 1(integer) 0127.0.0.1:6379> get k3"@"127.0.0.1:6379> bitop and andkey k2 k3(integer) 1127.0.0.1:6379> get andkey"@"
List
lpush
127.0.0.1:6379> help lpushLPUSH key element [element ...]summary: Prepend one or multiple elements to a listsince: 1.0.0group: list
从链表的左边开始添加元素到List中
rpush
127.0.0.1:6379> help rpushRPUSH key element [element ...]summary: Append one or multiple elements to a listsince: 1.0.0group: list
从链表的右侧添加元素
lpop
127.0.0.1:6379> help lpopLPOP key [count]summary: Remove and get the first elements in a listsince: 1.0.0group: list
从链表的左侧移除一个元素,并把移除的元素返回。
rpop
127.0.0.1:6379> help rpopRPOP key [count]summary: Remove and get the last elements in a listsince: 1.0.0group: list
实现栈操作
127.0.0.1:6379> lpush k5 a b c d e f127.0.0.1:6379> lpop k5"f"127.0.0.1:6379> lpop k5"e"127.0.0.1:6379> lpop k5"d"127.0.0.1:6379> lpop k5"c"127.0.0.1:6379> lpop k5"b"127.0.0.1:6379> lpop k5"a"127.0.0.1:6379> lpop k5(nil)
127.0.0.1:6379> rpush k6 a b c d e f127.0.0.1:6379> rpop k6"f"127.0.0.1:6379> rpop k6"e"127.0.0.1:6379> rpop k6"d"127.0.0.1:6379> rpop k6"c"127.0.0.1:6379> rpop k6"b"127.0.0.1:6379> rpop k6"a"127.0.0.1:6379> rpop k6(nil)
使用lpush、lpop 和rpush、rpop这种同方向的命令能够实现栈的操作。
实现队列的操作
127.0.0.1:6379> lpush k5 a b c d e f(integer) 6127.0.0.1:6379> rpop k5"a"127.0.0.1:6379> rpop k5"b"127.0.0.1:6379> rpop k5"c"127.0.0.1:6379> rpop k5"d"127.0.0.1:6379> rpop k5"e"127.0.0.1:6379> rpop k5"f"127.0.0.1:6379> rpop k5(nil)
127.0.0.1:6379> rpush k6 a b c d e f(integer) 6127.0.0.1:6379> lpop k6"a"127.0.0.1:6379> lpop k6"b"127.0.0.1:6379> lpop k6"c"127.0.0.1:6379> lpop k6"d"127.0.0.1:6379> lpop k6"e"127.0.0.1:6379> lpop k6"f"127.0.0.1:6379> lpop k6(nil)
使用lpush、rpop 和rpush、lpop这种反方向的命令能够实现队列的操作。
lrange获取列表元素
127.0.0.1:6379> help lrangeLRANGE key start stopsummary: Get a range of elements from a listsince: 1.0.0group: list
和字符串一样,链表List也为每个节点维护索引值。
127.0.0.1:6379> rpush k6 a b c d e f127.0.0.1:6379> lrange k6 0 -11) "a"2) "b"3) "c"4) "d"5) "e"6) "f"
lindex 取出列表里面的一个元素
127.0.0.1:6379> lindex k6 -1"f"127.0.0.1:6379> lindex k6 0"a"
lset 设置一个元素
127.0.0.1:6379> help lsetLSET key index elementsummary: Set the value of an element in a list by its indexsince: 1.0.0group: list
127.0.0.1:6379> lset k6 0 xxxOK127.0.0.1:6379> lrange k6 0 -11) "xxx"2) "b"3) "c"4) "d"5) "e"6) "f"
lrem
127.0.0.1:6379> help lremLREM key count elementsummary: Remove elements from a listsince: 1.0.0group: list
127.0.0.1:6379> lpush k7 1 2 3 1 2 1(integer) 6127.0.0.1:6379> lrange k7 0 -11) "1"2) "2"3) "1"4) "3"5) "2"6) "1"127.0.0.1:6379> lrem k7 2 1(integer) 2127.0.0.1:6379> lrange k7 0 -11) "2"2) "3"3) "2"4) "1"127.0.0.1:6379>
127.0.0.1:6379> help linsertLINSERT key BEFORE|AFTER pivot elementsummary: Insert an element before or after another element in a listsince: 2.2.0group: list
blpop
127.0.0.1:6379> help blpopBLPOP key [key ...] timeoutsummary: Remove and get the first element in a list, or block until one is availablesince: 2.0.0group: list
如果超时时间设置为0,没有拿到key里面的数据会一直阻塞,直到拿到数据为值。而且先阻塞的客户端先拿到数据。比如3个客户端同时执行上面的命令,当有数据的时候,先阻塞的客户端先拿到数据
ltrim
127.0.0.1:6379> help ltrimLTRIM key start stopsummary: Trim a list to the specified rangesince: 1.0.0group: list
删除给定范围外两端的元素
127.0.0.1:6379> lrange k7 0 -11) "2"2) "3"3) "2"4) "1"127.0.0.1:6379> ltrim k7 1 -2OK127.0.0.1:6379> lrange k7 0 -11) "3"2) "2"127.0.0.1:6379>
hash
类似hashmap
127.0.0.1:6379> help hsetHSET key field value [field value ...]summary: Set the string value of a hash fieldsince: 2.0.0group: hash127.0.0.1:6379> help hmsetHMSET key field value [field value ...]summary: Set multiple hash fields to multiple valuessince: 2.0.0group: hash
127.0.0.1:6379> hset person name lff(integer) 1127.0.0.1:6379> hmset person age 18 weight 155OK127.0.0.1:6379> hget person name"lff"127.0.0.1:6379> hmget person age weight1) "18"2) "155"127.0.0.1:6379> hkeys person1) "name"2) "age"3) "weight"127.0.0.1:6379> hvals person1) "lff"2) "18"3) "155"127.0.0.1:6379> hgetall person1) "name"2) "lff"3) "age"4) "18"5) "weight"6) "155"127.0.0.1:6379> hincrbyfloat person age 0.5"18.5"127.0.0.1:6379> hget person age"18.5"127.0.0.1:6379> hincrbyfloat person age -1"17.5"127.0.0.1:6379> hget person age"17.5"
set
特点:无序、去重。
127.0.0.1:6379> help saddSADD key member [member ...]summary: Add one or more members to a setsince: 1.0.0group: set
127.0.0.1:6379> sadd set_test a b c a b c(integer) 3127.0.0.1:6379> smembers set_test1) "c"2) "b"3) "a"127.0.0.1:6379> srem set_test a(integer) 1127.0.0.1:6379> smembers set_test1) "c"2) "b"
sinter 、sinterstore交集
127.0.0.1:6379> help sinterSINTER key [key ...]summary: Intersect multiple setssince: 1.0.0group: set127.0.0.1:6379> help sinterstoreSINTERSTORE destination key [key ...]summary: Intersect multiple sets and store the resulting set in a keysince: 1.0.0group: set
sinter取交集,结果直接返回客户端,会走网卡。sinterstore取交集,结果存在一个新的key里面,不走网卡。
127.0.0.1:6379> sadd kset1 a b c d(integer) 4127.0.0.1:6379> sadd kset2 a b d f(integer) 4127.0.0.1:6379> smembers kset11) "d"2) "c"3) "b"4) "a"127.0.0.1:6379> smembers kset21) "d"2) "b"3) "a"4) "f"127.0.0.1:6379> sinter kset1 kset21) "d"2) "b"3) "a"127.0.0.1:6379> sinterstore kset3 kset1 kset2(integer) 3127.0.0.1:6379> smembers kset31) "d"2) "a"3) "b"
sunion、sunionstore并集
127.0.0.1:6379> help sunionSUNION key [key ...]summary: Add multiple setssince: 1.0.0group: set
sunion取并集直接返回,sunionstore取并集,结果存放一个新的key里面
127.0.0.1:6379> sunion kset1 kset21) "d"2) "c"3) "b"4) "a"5) "f"127.0.0.1:6379> sunionstore kset4 kset1 kset2(integer) 5127.0.0.1:6379> smembers kset41) "d"2) "c"3) "b"4) "a"5) "f"
sorted set
给出一系列元素进行排序,应该按照什么方式排序?
比如:苹果、香蕉、橙子 是按照名称排序、还是按照大小排序、还是按照含糖量排序。所以sorted set里面引入一个分值的概念用来对元素进行排序。
有序set
127.0.0.1:6379> help zaddZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]summary: Add one or more members to a sorted set, or update its score if it already existssince: 1.2.0group: sorted_set
127.0.0.1:6379> zadd zk1 3 apple 7 bannana 1 orange(integer) 3127.0.0.1:6379> zrange zk1 0 -11) "orange"2) "apple"3) "bannana"127.0.0.1:6379> zrange zk1 0 -1 withscores1) "orange"2) "1"3) "apple"4) "3"5) "bannana"6) "7"
按照分值范围取数据
127.0.0.1:6379> zrangebyscore zk1 3 71) "apple"2) "bannana"
zrevrange逆序取数据
取出前两个最大的元素
127.0.0.1:6379> zrange zk1 0 -1 withscores1) "orange"2) "1"3) "apple"4) "3"5) "bannana"6) "7"127.0.0.1:6379> zrevrange zk1 0 11) "bannana"2) "apple"
获取分值和排名
127.0.0.1:6379> help zscoreZSCORE key membersummary: Get the score associated with the given member in a sorted setsince: 1.2.0group: sorted_set127.0.0.1:6379> help zrankZRANK key membersummary: Determine the index of a member in a sorted setsince: 2.0.0group: sorted_set
127.0.0.1:6379> zscore zk1 apple"3"127.0.0.1:6379> zrank zk1 apple(integer) 1
zincrby
给sorted set 集合某一个元素的分值增加,增加后也实时维护其在集合里面的顺序
127.0.0.1:6379> help zincrbyZINCRBY key increment membersummary: Increment the score of a member in a sorted setsince: 1.2.0group: sorted_set
127.0.0.1:6379> zrange zk1 0 -1 withscores1) "orange"2) "1"3) "apple"4) "3"5) "bannana"6) "7"127.0.0.1:6379> zincrby zk1 3 orange"4"127.0.0.1:6379> zrange zk1 0 -1 withscores1) "apple"2) "3"3) "orange"4) "4"5) "bannana"6) "7"
zunionstore
127.0.0.1:6379> help zunionstoreZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]summary: Add multiple sorted sets and store the resulting sorted set in a new keysince: 2.0.0group: sorted_set
默认是sum排序,相同集合里面的元素求和
127.0.0.1:6379> zadd k1 60 jack 80 rose 100 yoga(integer) 3127.0.0.1:6379> zadd k2 40 jack 20 rose 60 cliff(integer) 3127.0.0.1:6379> zunionstore k3 2 k1 k2 //2为key的个数,这里key有两个k1、k2(integer) 4127.0.0.1:6379> zrange k3 0 -1 withscores1) "cliff"2) "60"3) "jack"4) "100"5) "rose"6) "100"7) "yoga"8) "100"
可以给权重进行排序,k2给的权重是0.5,合并的时候k2集合里面的分值都会0.5倍
127.0.0.1:6379> zunionstore k3 2 k1 k2 weights 1 0.5(integer) 4127.0.0.1:6379> zrange k3 0 -1 withscores1) "cliff"2) "30"3) "jack"4) "80"5) "rose"6) "90"7) "yoga"8) "100"
