目录
服务端操作
启动服务:redis-server
客户端操作
启动客户端:redis-cli --raw # --raw:避免中文乱码
关闭客户端:exit / quit / ctrl + d
判断服务器是否在线:ping
切换数据库:select 1 # 数据库没有名称,默认16个,通过0-15来标识
数据操作:
- redis是key-value的数据库,每条数据都是一个键值对
- 键的类型是字符串,不能重复
- 值的类型分为5种:
字符串string
哈希hash
链表list
集合set
有序集合zset
string和hash最常用;
key定义的注意点:不要过长,最好不要超过1024个字节,会消耗内存、降低查找效率;
不要过短,可能会降低key的可读性;
项目中一般是有统一的命名规范;
string
-
redis中最为基础的数据存储类型
-
在redis中是以二进制的方式进行操作的,意味着该类型存入和获取的数据是相同的
-
字符串类型的value最多可容纳的数据长度是512M
string常用命令:赋值、取值、删除、数值增减、扩展命令
127.0.0.1:6379[7]> set name ww # 添加
OK
127.0.0.1:6379[7]> get name # 获取
ww
127.0.0.1:6379[7]> getset name Oayia # 获取并顺便修改值
ww
127.0.0.1:6379[7]> get name
Oayia
127.0.0.1:6379[7]> del name # 删除
1
127.0.0.1:6379[7]> del notexist # 删除不存在的键值对返回0
0
127.0.0.1:6379[7]> incr num # 自增,初始值是0,初次定义时,在0的基础上+1,即1
1
127.0.0.1:6379[7]> incr num
2
127.0.0.1:6379[7]> incr num
3
127.0.0.1:6379[7]> get num
3
127.0.0.1:6379[7]> decr num1 # 自减,初始值是0,初次定义时,在0的基础上-1,即-1
-1
127.0.0.1:6379[7]> decr num1
-2
127.0.0.1:6379[7]> get num1
-2
127.0.0.1:6379[7]>扩展命令:
[root@localhost 桌面]# redis-cli
127.0.0.1:6379> select 7
OK
127.0.0.1:6379[7]> keys *
1) "num"
2) "num1"
127.0.0.1:6379[7]> get num
"3"
127.0.0.1:6379[7]> incrby num 7 # 在num的基础上增加7,初次定义num时,是在0的基础上+7
(integer) 10
127.0.0.1:6379[7]> incrby notexist 8
(integer) 8
127.0.0.1:6379[7]> decrby num 4 # 和incrby类似
(integer) 6
127.0.0.1:6379[7]> append num 5 # 在num的基础上追加,追加后就变成了一个字符串,初次定义追加的值就是它的值
(integer) 2 # 返回追加后字符串的长度
127.0.0.1:6379[7]> get num
"65"
127.0.0.1:6379[7]> append notexists 123
(integer) 3
127.0.0.1:6379[7]> get notexists
"123"
127.0.0.1:6379[7]>
hash
- string key和string value的map容器
- 每一个hash可以存储2^32 -1(4294967295)个键值对
存储hash常用命令:赋值、取值、删除、增加数字、自学命令
127.0.0.1:6379[7]> hset student name ww # student键添加name属性
(integer) 1
127.0.0.1:6379[7]> hset student age 14 # student键添加age属性
(integer) 1
127.0.0.1:6379[7]> hmset teacher name rose age 21 # teacher键添加name、age属性
OK
127.0.0.1:6379[7]> hget student name # 获取某键的某属性
"ww"
127.0.0.1:6379[7]> hmget student name age # 获取某键的某些属性
1) "ww"
2) "14"
127.0.0.1:6379[7]> hgetall student # 获取某键的所有属性
1) "name"
2) "ww"
3) "age"
4) "14"
127.0.0.1:6379[7]> hdel student age # 删除某键的某属性
(integer) 1
127.0.0.1:6379[7]> hgetall student
1) "name"
2) "ww"
127.0.0.1:6379[7]> hdel student age # 删除某不存在的键,返回0
(integer) 0
127.0.0.1:6379[7]> del student # 删除某键
(integer) 1
127.0.0.1:6379[7]> hgetall student
(empty list or set)
127.0.0.1:6379[7]> hgetall teacher
1) "name"
2) "rose"
3) "age"
4) "21"
127.0.0.1:6379[7]> hincrby teacher age 5 # 给某键的某属性增加5,没有hdecrby
(integer) 26
127.0.0.1:6379[7]> hgetall teacher
1) "name"
2) "rose"
3) "age"
4) "26"
127.0.0.1:6379[7]>自学命令:
127.0.0.1:6379[7]> hgetall teacher
1) "name"
2) "rose"
3) "age"
4) "26"
127.0.0.1:6379[7]> hexists teacher name # name属性是否存在,存在返回1,不存在返回0
(integer) 1
127.0.0.1:6379[7]> hexists teacher password
(integer) 0
127.0.0.1:6379[7]> hlen teacher # 键中属性个数
(integer) 2
127.0.0.1:6379[7]> hkeys teacher # 键中所有的键
1) "name"
2) "age"
127.0.0.1:6379[7]> hvals teacher # 键中所有的值
1) "rose"
2) "26"
127.0.0.1:6379[7]>
list
- Arraylist使用数组方式
- Linkedlist使用双向链接方式
- 双向链表中增加数据
- 双向链表中删除数据
存储list常用命令:两端添加、查看列表、两端弹出、获取列表元素个数、扩展命令
127.0.0.1:6379[7]> lpush mylist a b c # 左端依次添加a b c
(integer) 3
127.0.0.1:6379[7]> lpush mylist 1 2 3
(integer) 6
127.0.0.1:6379[7]> rpush mylist2 1 2 3 # 右端依次添加1 2 3
(integer) 3
127.0.0.1:6379[7]> lrange mylist 0 -1 # 遍历mylist
1) "3"
2) "2"
3) "1"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379[7]> lrange mylist2 0 -1
1) "1"
2) "2"
3) "3"
127.0.0.1:6379[7]> lrange mylist2 0 -2
1) "1"
2) "2"
127.0.0.1:6379[7]> lpop mylist # 弹出mylist中最左端的值
"3"
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "1"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379[7]> rpop mylist # 弹出mylist中最左端的值
"a"
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "1"
3) "c"
4) "b"
127.0.0.1:6379[7]> llen mylist # mylist列表中个数
(integer) 4
127.0.0.1:6379[7]>扩展命令:
127.0.0.1:6379[7]> lpushx mylist x # 给已存在的列表左端添加x,不存在没什么影响,不会新建
(integer) 5
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "x"
2) "2"
3) "1"
4) "c"
5) "b"
127.0.0.1:6379[7]> lpushx mylist3 x
(integer) 0
127.0.0.1:6379[7]> rpushx mylist y # 给已存在的列表右端添加y
(integer) 6
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "x"
2) "2"
3) "1"
4) "c"
5) "b"
6) "y"
127.0.0.1:6379[7]> lpush mylist 1 2 3 1 2 3 1 2 3
(integer) 15
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "3"
2) "2"
3) "1"
4) "3"
5) "2"
6) "1"
7) "3"
8) "2"
9) "1"
10) "x"
11) "2"
12) "1"
13) "c"
14) "b"
15) "y"
127.0.0.1:6379[7]> lrem mylist 0 1 # 移除mylist列表中所有的1
(integer) 4
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "3"
2) "2"
3) "3"
4) "2"
5) "3"
6) "2"
7) "x"
8) "2"
9) "c"
10) "b"
11) "y"
127.0.0.1:6379[7]> lrem mylist 2 3 # 从左端开始移除mylist列表中的两个3
(integer) 2
127.0.0.1:6379[7]> lrem mylist -1 3 # 从右端开始移除列表mylist中的一个3
(integer) 1
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "2"
3) "2"
4) "x"
5) "2"
6) "c"
7) "b"
8) "y"
127.0.0.1:6379[7]> lset mylist 1 mmmm # 指定修改mylist列表索引为1的值为mmmm
OK
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "mmmm"
3) "2"
4) "x"
5) "2"
6) "c"
7) "b"
8) "y"
127.0.0.1:6379[7]> linsert mylist before b hello # b的前边插入hello
(integer) 9
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "mmmm"
3) "2"
4) "x"
5) "2"
6) "c"
7) "hello"
8) "b"
9) "y"
127.0.0.1:6379[7]> linsert mylist after b hello # b的后边插入hello
(integer) 10
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "2"
2) "mmmm"
3) "2"
4) "x"
5) "2"
6) "c"
7) "hello"
8) "b"
9) "hello"
10) "y"
127.0.0.1:6379[7]> lrange mylist2 0 -1
1) "1"
2) "2"
3) "3"
127.0.0.1:6379[7]> rpoplpush mylist2 mylist # 弹出mylist2最右端值,左端添加到mylist列表中
"3"
127.0.0.1:6379[7]> lrange mylist 0 -1
1) "3"
2) "2"
3) "mmmm"
4) "2"
5) "x"
6) "2"
7) "c"
8) "hello"
9) "b"
10) "hello"
11) "y"
127.0.0.1:6379[7]> lrange mylist2 0 -1
1) "1"
2) "2"
127.0.0.1:6379[7]>rpoplpush:
redis列表会经常用于一些消息队列的一些服务,来完成多个程序之间的消息交互。假设一个应用程序正在执行lpush想列表中添加新的元素,通常将这样的角色称之为生产者,另外一个程序正在执行rpop从列表中取出元素,称之为消费者,与此同时,消费者程序在取出元素后立刻崩溃,由于该消息一经被取出且没有被正常处理,我们就可以认为这个消息已经丢失了,由此可能会导致业务数据的丢失,或者是业务状态的不一致等现象的发生。
有了这个rpoplpush这个命令,消费者程序在主消息队列中取出元素后再将它插入到一个备份的队列中,直到我们的消费者程序完成正常的逻辑处理后,再将消息从备份的消息队列中删除,这样的话,我们可以提供一个守护线程,当发现备份队列中的消息过期的时候,可以重新将它放回到主消息的队列当中,以便其他的消费者可以继续去处理
set
- 和list集合不同的是,set集合不允许出现重复的元素,即如果多次添加相同的元素,set中将仅保留一个
- 和list相比,set类型在功能上还存在着一个非常重要的特性:在服务器端完成多个sets之间的一个聚合计算操作,如:unions、diffrence由于这些操作都是在服务器端完成的,因此效率非常的高,可以节省大量的网络开销
存储set常用命令:添加/删除元素、获取集合中的元素、集合中的差集/交集/并集运算、扩展命令
127.0.0.1:6379[2]> sadd myset a b c # 添加a b c到myset
(integer) 3
127.0.0.1:6379[2]> sadd myset a
(integer) 0
127.0.0.1:6379[2]> srem myset a # 删除某成员
(integer) 1
127.0.0.1:6379[2]> smembers myset # 查看所有成员
1) "b"
2) "c"
127.0.0.1:6379[2]> sismember myset b # b是否是myset的成员,是返回1,否返回0
(integer) 1
127.0.0.1:6379[2]> sismember myset a
(integer) 0
127.0.0.1:6379[2]> sadd myset1 a b d
(integer) 3
127.0.0.1:6379[2]> sdiff myset1 myset # 差集,有先后顺序
1) "a"
2) "d"
127.0.0.1:6379[2]> sinter myset myset1 # 交集
1) "b"
127.0.0.1:6379[2]> sunion myset myset1 # 并集
1) "b"
2) "a"
3) "d"
4) "c"
127.0.0.1:6379[2]>扩展命令:
127.0.0.1:6379[2]> smembers myset
1) "b"
2) "c"
127.0.0.1:6379[2]> scard myset # 返回集合元素个数
(integer) 2
127.0.0.1:6379[2]> srandmember myset # 随机取出myset中的元素
"b"
127.0.0.1:6379[2]> srandmember myset
"c"
127.0.0.1:6379[2]> sdiffstore myset2 myset myset1 # 差集结果转储到myset2中
(integer) 1
127.0.0.1:6379[2]> smembers myset
1) "b"
2) "c"
127.0.0.1:6379[2]> smembers myset1
1) "b"
2) "a"
3) "d"
127.0.0.1:6379[2]> smembers myset2
1) "c"
127.0.0.1:6379[2]> sinterstore myset3 myset myset1 # 交集结果转储到myset3中
(integer) 1
127.0.0.1:6379[2]> smembers myset3
1) "b"
127.0.0.1:6379[2]> sunionstore myset4 myset myset1 # 并集结果转储到myset4中
(integer) 4
127.0.0.1:6379[2]> smembers myset4
1) "b"
2) "a"
3) "d"
4) "c"
127.0.0.1:6379[2]>使用场景:
- 跟踪一些唯一性数据
- 用于维护数据对象之间的关联关系
使用redis的set数据类型跟踪一些具有唯一性的数据,比如访问某一博客的唯一ip地址的信息,对于这种场景,仅需要每次在访问该博客的时候,将访问者的ip存到redis当中,然后set类型就会自动保证ip地址的唯一性,还能充分利用set类型的服务器端聚合操作的一个方便高效的一些特性可以用于维护数据对象之间的一些关联关系,比如我们所有购买某一个电子设备的客户id被存储到一个指定的set当中,而购买另外一种电子产品的客户id存储到另外一个set中,如果此时,想要获取同时购买了两件产品的客户有哪些,此时就可使用这两set的交集
Sorted-Set
- 和set相似,都是字符串的集合,都不允许重复,区别是sorted-set中的每一个成员都有一个分数与之关联,redis通过这个分数为集合中的成员进行从小到大的排序
- 成员唯一,分数可以重复
- 在sorted-set中添加、删除、更新一个成员是非常快速的,时间复杂度是集合成员总个数的对数
- sorted-set中的成员在集合中的位置是有序的,所以,即便是访问中间部分的成员也是非常高效的
redis中的数据结构sorted-set所具有的这一特征,在其他类型的数据库中都是很难实现的,换句话说,在该点上,要想达到和redis同样的高效,在其他的数据库中进行建模是非常困难的
应用场景:
-
游戏的排名
-
微薄的热点话题等等这类的使用场景上会应用
存储sorted-set常用命令:添加元素、获得元素、删除元素、范围查询、扩展命令
127.0.0.1:6379[2]> zadd mysort 70 zs 80 ls 90 ww # 添加元素到mysort,返回的是初次添加元素的个数
(integer) 3
127.0.0.1:6379[2]> zadd mysort 100 zs # 如果是已经存在的再次添加,新的分数会覆盖旧的分数
(integer) 0
127.0.0.1:6379[2]> zadd mysort 60 tom
(integer) 1
127.0.0.1:6379[2]> zscore mysort zs # 查询某成员的分数
"100"
127.0.0.1:6379[2]> zcard mysort # 查询集合中成员总个数
(integer) 4
127.0.0.1:6379[2]> zrem mysort tom ww # 删除集合中的元素tom ww
(integer) 2
127.0.0.1:6379[2]> zcard mysort
(integer) 2
127.0.0.1:6379[2]> zadd mysort 85 jack 95 rose
(integer) 2
127.0.0.1:6379[2]> zrange mysort 0 -1 # 遍历集合
1) "ls"
2) "jack"
3) "rose"
4) "zs"
127.0.0.1:6379[2]> zrange mysort 0 -1 withscores # 遍历集合,并显示分数,分数默认由低到高
1) "ls"
2) "80"
3) "jack"
4) "85"
5) "rose"
6) "95"
7) "zs"
8) "100"
127.0.0.1:6379[2]> zrevrange mysort 0 -1 withscores # 遍历集合,并显示分数,由分数高到低
1) "zs"
2) "100"
3) "rose"
4) "95"
5) "jack"
6) "85"
7) "ls"
8) "80"
127.0.0.1:6379[2]> zremrangebyrank mysort 0 1 # 按照等级进行删除,start stop是zrange排序的下标,闭区间
(integer) 2
127.0.0.1:6379[2]> zrange mysort 0 -1 withscores
1) "rose"
2) "95"
3) "zs"
4) "100"
127.0.0.1:6379[2]> zremrangebyscore mysort 95 100 # 按照分数进行删除,闭区间
(integer) 2
127.0.0.1:6379[2]> zrange mysort 0 -1 withscores
(empty list or set)127.0.0.1:6379[2]> zadd mysort 85 jack 95 rose 70 ww 80 ls 90 ss
(integer) 5127.0.0.1:6379[2]> zrange mysort 0 -1
1) "ww"
2) "ls"
3) "jack"
4) "ss"
5) "rose"
127.0.0.1:6379[2]> zremrangebyrank mysort 0 2
(integer) 3
127.0.0.1:6379[2]> zrange mysort 0 -1
1) "ss"
2) "rose"扩展命令:
127.0.0.1:6379[2]> zrange mysort 0 -1 withscores
1) "ww"
2) "70"
3) "ls"
4) "80"
5) "jack"
6) "85"
7) "ss"
8) "90"
9) "rose"
10) "95"
127.0.0.1:6379[2]> zrangebyscore mysort 0 100 withscores limit 1 2 # offset , count
1) "ls"
2) "80"
3) "jack"
4) "85"
127.0.0.1:6379[2]> zincrby mysort 5 ww # mysort中的ww分数的基础上+5
"75"
127.0.0.1:6379[2]> zcount mysort 80 90 # 统计集合中分数在80-90之间的元素个数,闭区间
(integer) 3
127.0.0.1:6379[2]>常用的 使用场景:
大型的在线游戏的积分排行榜,每当玩家分数发生变化的时候,可执行zadd命令去更新这个玩家的分数,此后,通过zrange命令来获取积分
构建索引数据
Keys的通用操作
127.0.0.1:6379[2]> keys * # 查询满足条件的键
1) "myset"
2) "myset1"
3) "myset3"
4) "myset4"
5) "mysort"
6) "myset2"
127.0.0.1:6379[2]> keys myset?
1) "myset1"
2) "myset3"
3) "myset4"
4) "myset2"
127.0.0.1:6379[2]> myset myset1 # 删除某数据结构
(integer) 2
127.0.0.1:6379[2]> exists myset # 键是否存在,存在返回1,不存在返回0
(integer) 0
127.0.0.1:6379[2]> exists myset2
(integer) 1
127.0.0.1:6379[2]> rename myset2 myset # 键重命名
OK
127.0.0.1:6379[2]> keys *
1) "myset"
2) "myset3"
3) "myset4"
4) "mysort"
127.0.0.1:6379[2]> expire myset 1000 # 设置过期时间,单位s
(integer) 1
127.0.0.1:6379[2]> ttl myset # 查看剩余多长时间过期
(integer) 985
127.0.0.1:6379[2]> type myset # 查看数据结构类型
set
127.0.0.1:6379[2]> type mysort
zset
127.0.0.1:6379[2]>