一、redis 概述
1.概念了解
redis 默认有 16 个数据库,且默认使用的是第 0 个数据库,可以使用
select
命令切换数据库,使用flushdb
清空当前数据库,使用flushall
清空全部数据库。redis是单线程的(但是在 redis 6 引入了多线程 IO,但执行命令还是单线程),官方表示,redis 是基于内存操作,所以 CPU 不是 redis 的性能瓶颈,redis 的性能瓶颈是计算机的内存和网络带宽,那么这样的话 redis 就可以不用多线程,直接使用单线程来实现,于是最终 redis 就被设计为单线程了。
为什么 redis 是单线程效率还这么高?
误区1:高性能的服务器一定是多线程的
误区2:多线程的效率一定比单线程高
事实上,多线程执行的时候会有 CPU 的上下文切换,这会造成一定的性能开销,所以多线程的效率不一定比单线程高。
就速度来说,CPU > 内存 > 硬盘
**答案:**redis 是将数据全部存放在内存中的,使用单线程,多次读写都是在一个CPU上进行,可以避免 CPU 的上下文切换,节省性能开销,所以使用单线程反而效率是最高的(对于内存系统来说,没有上下文切换效率就是最高的)。
2.基本命令
127.0.0.1:6379> select 3 #切换数据库
OK
127.0.0.1:6379[3]> dbsize #查看数据库大小
(integer) 0
127.0.0.1:6379[3]> set name zhangsan #插入键值对
OK
127.0.0.1:6379[3]> dbsize
(integer) 1
127.0.0.1:6379[3]> get name #通过键获取值
"zhangsan"
127.0.0.1:6379[3]> select 8
OK
127.0.0.1:6379[8]> dbsize
(integer) 0
127.0.0.1:6379[8]> get name
(nil)
127.0.0.1:6379[3]> keys * #查看当前数据库中所有的键
1) "name"
127.0.0.1:6379[3]> flushdb #清空当前数据库
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> select 0
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> flushall #清空所有数据库
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> select 0
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> move name 1 #将数据移到其他数据库,1 是指将当前键值对移到 1 号数据库
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> expire name 10 #设置键的过期时间,10 指的是过期时间设置为 10s
(integer) 1
127.0.0.1:6379> ttl name
(integer) 6
127.0.0.1:6379> ttl name #查看键的过期时间,-2 则表示数据已过期
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> type name #查看数据类型
string
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> del name #删除键
(integer) 1
127.0.0.1:6379> keys *
1) "age"
二、redis 的常用命令
1.string(字符串)
- 基本命令
127.0.0.1:6379> set k1 v1 #设置键值对
OK
127.0.0.1:6379> get k1 #通过键获取值
"v1"
127.0.0.1:6379> keys * #查看所有键
1) "k3"
2) "\xac\xed\x00\x05t\x00\x02k2"
3) "k6"
4) "k1"
5) "k4"
6) "k5"
127.0.0.1:6379> exists k1 #查看键是否存在
(integer) 1
127.0.0.1:6379> exists k7
(integer) 0
127.0.0.1:6379> exists k1 k3 k5
(integer) 3
127.0.0.1:6379> append k1 value #往对应键的值后面追加内容【如果当前key不存在,则等价于set key value】
(integer) 7
127.0.0.1:6379> get k1
"v1value"
127.0.0.1:6379> append k2 sss
(integer) 3
127.0.0.1:6379> get k2
"sss"
127.0.0.1:6379> STRLEN k1 #获取键对应值的长度
(integer) 7
- 数值增减命令(适用于类似于阅读量用户阅读一次加一等场景,排行榜点击加一)
127.0.0.1:6379> set num 0
OK
127.0.0.1:6379> get num
"0"
127.0.0.1:6379> incr num #自增一
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> decr num #自减一
(integer) 1
127.0.0.1:6379> decr num
(integer) 0
127.0.0.1:6379> decr num
(integer) -1
127.0.0.1:6379> get num
"-1"
127.0.0.1:6379> incrby num 10 #自增指定步长
(integer) 9
127.0.0.1:6379> get num
"9"
127.0.0.1:6379> decrby num 2 #自减指定步长
(integer) 7
127.0.0.1:6379> get num
"7"
- 字符串常用命令
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> get k1
"helloworld"
127.0.0.1:6379> getrange k1 0 4 #截取字符串 [0,4]
"hello"
127.0.0.1:6379> getrange k1 0 -1 #获取整个字符串,等价于 get key
"helloworld"
127.0.0.1:6379> set k2 abcdefg
OK
127.0.0.1:6379> get k2
"abcdefg"
127.0.0.1:6379> setrange k2 1 xxxx #替换指定位置开始的字符串,偏移量为替换字符串的长度
(integer) 7
127.0.0.1:6379> get k2
"axxxxfg"
127.0.0.1:6379> setex k3 30 hello #设置值的同时设置过期时间,30 指过期时间为 30s,hello 为设置的值
OK
127.0.0.1:6379> ttl k3 #查看过期时间
(integer) 25
127.0.0.1:6379> get k3
"hello"
127.0.0.1:6379> setnx k4 redis #如果 key 不存在,则创建 key,返回 1
(integer) 1
127.0.0.1:6379> keys *
1) "k4"
2) "k1"
3) "k2"
127.0.0.1:6379> ttl k3 #此时 k3 已过期
(integer) -2
127.0.0.1:6379> setnx k4 mongo #如果已存在,则创建失败,返回 0(不会替换,通常用于分布式锁)
(integer) 0
127.0.0.1:6379> get k4
"redis"
127.0.0.1:6379> flushdb #清空当前数据库
OK
127.0.0.1:6379> keys * #查看所有键
(empty list or set)
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 v1 k4 v4 #msetnx 是一个原子性的操作,要么全部成功,要么全部失败,此时 k1 已存在
(integer) 0
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> getset db redis #先获取再设置值,如果不存在,则返回 nil,再设置值(用于更新操作)
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongo #先获取再设置值,如果存在则返回存在的值,再设置新的值(用于更新操作)
"redis"
127.0.0.1:6379> get db
"mongo"
2.list(列表)
- 基本命令
127.0.0.1:6379> flushdb #清空当前数据库
OK
127.0.0.1:6379> keys * #查看当前数据库中存在的所有键
(empty list or set)
127.0.0.1:6379> lpush list one #插入一个或多个值,插入到列表头部(左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 #查看当前列表中全部的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 #通过区间获取具体的值 [0,1]
1) "three"
2) "two"
127.0.0.1:6379> rpush list right #插入一个或多个值,插入到列表尾部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1 #查看列表中全部的值
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lpop list #从列表头部移除一个值
"three"
127.0.0.1:6379> lrange list 0 -1 #查看当前列表中全部的值
1) "two"
2) "one"
3) "right"
127.0.0.1:6379> rpop list #从列表尾部移除一个值
"right"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 0 #通过索引获取单个的值
"two"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> llen list #获取当前列表的长度
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lpush list two #列表是有序可重复的
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "two"
3) "one"
127.0.0.1:6379> lpush list three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one #移除指定的值,1 指移除一个,one 是被移除的值(>0 从左边移除,=0 移除全部,<0 从右边移除)
(integer) 1
127.0.0.1:6379> lrange list 0 -1 #查看当前列表中全部的值
1) "three"
2) "two"
3) "two"
127.0.0.1:6379> lrem list 1 two
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lpush list two
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 2 two #移除指定的值,2 指移除两个,two 是被移除的值(>0 从左边移除,=0 移除全部,<0 从右边移除)
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "three"
127.0.0.1:6379> flushdb #清空当前数据库
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush list k1 k2 k3 k4 k5 #从列表尾部插入多个值
(integer) 5
127.0.0.1:6379> lrange list 0 -1 #查看当前列表中的所有元素
1) "k1"
2) "k2"
3) "k3"
4) "k4"
5) "k5"
127.0.0.1:6379> ltrim list 1 2 #通过索引截取当前列表中的一部分元素 [1,2]
OK
127.0.0.1:6379> lrange list 0 -1
1) "k2"
2) "k3"
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush list k0 k1 k2 k3
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "k0"
2) "k1"
3) "k2"
4) "k3"
127.0.0.1:6379> rpoplpush list newlist #从 list 尾部移除一个元素,将其插入到 newlist 的头部(newlist 不存在则会创建)
"k3"
127.0.0.1:6379> keys *
1) "newlist"
2) "list"
127.0.0.1:6379> lrange list 0 -1
1) "k0"
2) "k1"
3) "k2"
127.0.0.1:6379> lrange newlist 0 -1
1) "k3"
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> exists list #判断当前列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 one #如果当前列表不存在,使用 lset 会报错
(error) ERR no such key
127.0.0.1:6379> lpush list one #使用 lpush,如果列表不存在,则会创建列表,再插入值
(integer) 1
127.0.0.1:6379> lrange list 0 0 #获取列表索引为 0 的元素
1) "one"
127.0.0.1:6379> lset list 0 two #更新列表索引为 0 的元素值
OK
127.0.0.1:6379> lrange list 0 0
1) "two"
127.0.0.1:6379> lset list 1 two #如果列表索引为 1 的元素不存在,则执行更新操作会报错
(error) ERR index out of range
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> rpush list one
(integer) 1
127.0.0.1:6379> rpush list two
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
127.0.0.1:6379> linsert list before two three #在当前列表的元素 two 之前插入 three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> linsert list after two three #在当前列表的元素 two 之后插入 three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "three"
3) "two"
4) "three"
3.set(集合)
- 基本命令
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> sadd set one #插入一个或多个元素
(integer) 1
127.0.0.1:6379> sadd set two
(integer) 1
127.0.0.1:6379> sadd set three
(integer) 1
127.0.0.1:6379> smembers set #查看集合中的所有元素
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> sismember set three #查看集合中是否存在某个元素,存在则返回 1
(integer) 1
127.0.0.1:6379> sismember set four #查看集合中是否存在某个元素,不存在则返回 0
(integer) 0
127.0.0.1:6379> scard set #获取集合里面的元素个数
(integer) 3
127.0.0.1:6379> sadd set three #set 集合元素不能重复,添加重复元素会返回 0
(integer) 0
127.0.0.1:6379> smembers set
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> sadd set four
(integer) 1
127.0.0.1:6379> scard set
(integer) 4
127.0.0.1:6379> smembers set #集合元素是无序的,新添加的元素位置不固定
1) "one"
2) "four"
3) "three"
4) "two"
127.0.0.1:6379> srem set four #移除集合中指定元素
(integer) 1
127.0.0.1:6379> scard set
(integer) 3
127.0.0.1:6379> smembers set
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> srandmember set #从指定集合中随机获取一个元素
"one"
127.0.0.1:6379> srandmember set
"two"
127.0.0.1:6379> srandmember set
"two"
127.0.0.1:6379> srandmember set 2 #从指定集合中随机获取多个元素
1) "one"
2) "two"
127.0.0.1:6379> srandmember set 2
1) "three"
2) "two"
127.0.0.1:6379> smembers set #查看集合中全部元素
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> spop set #随机从指定集合中删除一个元素
"three"
127.0.0.1:6379> spop set 2 #随机从指定集合中删除多个元素
1) "one"
2) "two"
127.0.0.1:6379> smembers set
(empty list or set)
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> sadd set one
(integer) 1
127.0.0.1:6379> sadd set two
(integer) 1
127.0.0.1:6379> sadd set three
(integer) 1
127.0.0.1:6379> smembers set
1) "one"
2) "three"
3) "two"
127.0.0.1:6379> smove set newset one #将集合中的指定元素移动到另一个集合中,如果该集合不存在则会创建
(integer) 1
127.0.0.1:6379> smembers set
1) "three"
2) "two"
127.0.0.1:6379> smembers newset
1) "one"
- 数字集合命令
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> sadd set1 a b c d e #创建一个集合并添加多个元素
(integer) 5
127.0.0.1:6379> sadd set2 d e f g
(integer) 4
127.0.0.1:6379> smembers set1
1) "d"
2) "b"
3) "c"
4) "a"
5) "e"
127.0.0.1:6379> smembers set2
1) "d"
2) "f"
3) "e"
4) "g"
127.0.0.1:6379> sdiff set1 set2 #获取前一个集合与后一个集合的差集
1) "b"
2) "a"
3) "c"
127.0.0.1:6379> sdiff set2 set1 #获取前一个集合与后一个集合的差集
1) "f"
2) "g"
127.0.0.1:6379> sinter set1 set2 #获取两个集合的交集
1) "d"
2) "e"
127.0.0.1:6379> sunion set1 set2 #获取两个集合的并集
1) "e"
2) "f"
3) "c"
4) "d"
5) "b"
6) "g"
7) "a"
4.hash(哈希)
类似于 Map 集合,只是 hash 存的值是 key - map,而不是简单的单个 key - value
- 基本命令
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> hset hash field zero #设置一组键值对,可同时设置多组
(integer) 1
127.0.0.1:6379> hget hash field #通过键获取值,一次只能获取一组
"zero"
127.0.0.1:6379> hmset hash field one field1 one #同时设置多组键值对,如果键已存在,则不同的值会覆盖
OK
127.0.0.1:6379> hmget hash field field1 #同时获取多个键对应的值
1) "one"
2) "one"
127.0.0.1:6379> hgetall hash #获取所有的键值对元素
1) "field"
2) "one"
3) "field1"
4) "one"
127.0.0.1:6379> hdel hash field1 #删除指定的键对应的一组元素
(integer) 1
127.0.0.1:6379> hgetall hash
1) "field"
2) "one"
127.0.0.1:6379> hlen hash #查看元素数量,一组键值对算一个元素
(integer) 1
127.0.0.1:6379> hset hash field1 one field2 two #通过 hset 同时设置多组键值对
(integer) 2
127.0.0.1:6379> hgetall hash
1) "field"
2) "one"
3) "field1"
4) "one"
5) "field2"
6) "two"
127.0.0.1:6379> hget hash field1 field2 #hget 一次只能获取一组元素,多了会报错
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hlen hash #查看元素数量,一组键值对算一个元素
(integer) 3
127.0.0.1:6379> hexists hash field #判断元素是否存在,存在则返回 1
(integer) 1
127.0.0.1:6379> hexists hash field3 #判断元素是否存在,不存在则返回 0
(integer) 0
127.0.0.1:6379> hkeys hash #获取所有的键
1) "field"
2) "field1"
3) "field2"
127.0.0.1:6379> hvals hash #获取所有的值
1) "one"
2) "one"
3) "two"
127.0.0.1:6379> hset hash field3 3
(integer) 1
127.0.0.1:6379> hgetall hash
1) "field"
2) "one"
3) "field1"
4) "one"
5) "field2"
6) "two"
7) "field3"
8) "3"
127.0.0.1:6379> hincrby hash field3 2 #给数值类型的数据增加指定步长
(integer) 5
127.0.0.1:6379> hgetall hash
1) "field"
2) "one"
3) "field1"
4) "one"
5) "field2"
6) "two"
7) "field3"
8) "5"
127.0.0.1:6379> hincrby hash field3 -1 #如果想要给数值类型的值减指定步长,则可以指定步长为负数(注意:没有 hdecrby 命令)
(integer) 4
127.0.0.1:6379> hset hash field4 four #如果指定元素键不存在则创建元素
(integer) 1
127.0.0.1:6379> hset hash field4 five #如果指定元素键存在则不会创建元素
(integer) 0
5.zset(有序集合)
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> zadd set 1 one #往有序集合中添加一个元素,1 是这个元素的分数
(integer) 1
127.0.0.1:6379> zadd set 2 two 3 three #往有序集合中一次性添加多个元素
(integer) 2
127.0.0.1:6379> zrange set 0 -1 #查看指定有序集合中的所有元素,会默认按照分数的升序排序
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zadd salary 2500 zhangsan 2000 lisi 3000 wangwu 1800 zhaoliu #创建一个薪水集合,用分数来表示薪水
(integer) 4
127.0.0.1:6379> zrange salary 0 -1 #按照升序获取所有元素
1) "zhaoliu"
2) "lisi"
3) "zhangsan"
4) "wangwu"
127.0.0.1:6379> zrangebyscore salary -inf +inf #按照分数的升序排序查看所有元素,-inf 指的是负无穷,+inf 指的是正无穷,即查看所有元素
1) "zhaoliu"
2) "lisi"
3) "zhangsan"
4) "wangwu"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores #按照升序查看所有元素并查看这些元素的分数
1) "zhaoliu"
2) "1800"
3) "lisi"
4) "2000"
5) "zhangsan"
6) "2500"
7) "wangwu"
8) "3000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores #只查看部分数据 [-∞,2500]
1) "zhaoliu"
2) "1800"
3) "lisi"
4) "2000"
5) "zhangsan"
6) "2500"
127.0.0.1:6379> zrevrange salary 0 -1 #按照降序获取所有元素
1) "wangwu"
2) "zhangsan"
3) "lisi"
4) "zhaoliu"
127.0.0.1:6379> zrevrangebyscore salary +inf -inf withscores #按照降序获取所有元素及其分数
1) "wangwu"
2) "3000"
3) "zhangsan"
4) "2500"
5) "lisi"
6) "2000"
7) "zhaoliu"
8) "1800"
127.0.0.1:6379> zrem salary zhangsan #从集合中移除一个元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zhaoliu"
2) "lisi"
3) "wangwu"
127.0.0.1:6379> zcard salary #查看集合中有多少个元素
(integer) 3
127.0.0.1:6379> zcount salary 1000 2000 #判断在一个分数区间中有多少个值 [1000,2000]
(integer) 2
127.0.0.1:6379> zcount salary 1000 3000
(integer) 3