• Redis的五种数据类型详解


    本篇文章更多的是通过命令来彻底掌握Redis的五种数据结构!

    一、基础的知识

    Linux上安装Redis详细教程:https://blog.csdn.net/weixin_43888891/article/details/125830622

    Redis默认有16个数据库,每一个数据库的数据是相互隔离的,在redis.conf配置文件当中可以配置!

    在这里插入图片描述
    redis官网命令大全:https://www.redis.com.cn/commands.html

    在redis的客户端当中输入命令是会有提示的,并且Tab按键可以命令补全!

    在这里插入图片描述

    redis常用的有五种数据类型,所谓的数据类型都由value值决定的,并改变Redis是key/value的整体数据结构,例如list数据结构就是一个key可以对应多个value,而hash结构就是一个key对应的value可以是个map,仅此而已,不要想的有多么复杂。

    redis的命令不分大小写!

    (1)基础的命令

    • 测试连接:ping
    • 判断是否存在key:EXISTS
    • set一个string:set
    • 切换数据库:select
    • 获取一个key的值:get
    • 查看db的大小:DBSIZE
    • 查看当前数据库所有的key:keys *
    [root@iZwz978dfoabti7b21e7xaZ bin]# redis-cli -p 6379 # 连接客户端,redis-cli是安装redis自带的
    127.0.0.1:6379> ping # 测试连接
    PONG
    127.0.0.1:6379> EXISTS test1 # 判断是否存在key为test1的数据
    (integer) 1
    127.0.0.1:6379> set test aaa aaa # key值是不允许有空格的,空格是需要进行转义的
    (error) ERR syntax error
    127.0.0.1:6379> set test1 aaa # 向DB 0 存储 key(test1)/value(aaa)
    OK
    127.0.0.1:6379> select 3 # 切换数据库3
    OK
    127.0.0.1:6379[3]> get test1 # 在数据库3当中获取key为test1的为空
    (nil)
    127.0.0.1:6379[3]> DBSIZE # 查看DB大小
    (integer) 0
    127.0.0.1:6379[3]> select 0 # 切换数据库0
    OK
    127.0.0.1:6379> dbsize # 查看DB大小
    (integer) 5
    127.0.0.1:6379> get test1 # 获取test1的值
    "aaa"
    127.0.0.1:6379> keys * # 查看当前数据库所有的key
    1) "test1"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    (2)清除数据库

    • 清除当前数据库:flushdb
    • 清除全部数据库的内容:flushall
    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> keys *
    (empty array)
    
    • 1
    • 2
    • 3
    • 4

    (3)移动指定key的数据当别的数据库当中move

    127.0.0.1:6379> set test1 aaa
    OK
    127.0.0.1:6379> move test1 1 # 将当前数据库test1数据移动到1数据库当中
    (integer) 1
    127.0.0.1:6379> get test1 # 移动过后在当前数据库就查不到了
    (nil)
    127.0.0.1:6379> select 1
    OK
    127.0.0.1:6379[1]> get test1
    "aaa"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (4)设置过期时间EXPIRE

    查看当前key剩余的时间:ttl

    127.0.0.1:6379[1]> set test1 aaa
    OK
    127.0.0.1:6379[1]> EXPIRE test1 10 # 设置key为test1的数据-过期时间为10秒
    (integer) 1
    127.0.0.1:6379[1]> ttl test1 # 查看test1距离过期的剩余时间
    (integer) 7
    127.0.0.1:6379[1]> ttl test1
    (integer) 5
    127.0.0.1:6379[1]> ttl test1 # 10秒过后已经为-2代表已经过期
    (integer) -2
    127.0.0.1:6379[1]> get test1 # 这时候查看已经为空
    (nil)
    127.0.0.1:6379[1]> keys * # 过期之后连key/value都会被删除
    (empty array)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (5)查看key是什么类型(类型就是我们所说的五大类型)type

    127.0.0.1:6379> set test1 111
    OK
    127.0.0.1:6379> type test1 # 这里的类型不是说存储111就是数字类型,他是查看的redis数据类型当中的类型
    string
    
    • 1
    • 2
    • 3
    • 4

    (6)删除给定的一个或多个 keyDEL

    127.0.0.1:6379> set test1 111
    OK
    127.0.0.1:6379> del test1
    (integer) 1
    
    • 1
    • 2
    • 3
    • 4

    二、五种数据类型

    1、String(字符串)

    90% 的java程序员使用redis只会使用一个String类型!

    我们正常的get、set命令就是操作的redis的String类型!

    (1)追加字符串(如果当前key不存在,就相当于setkey)APPEND

    127.0.0.1:6379> set key1 v1
    OK
    127.0.0.1:6379> get key1
    "v1"
    127.0.0.1:6379> keys * # 查询所有key
    1) "key1"
    127.0.0.1:6379> EXISTS key1 # 判断是否存在
    (integer) 1
    127.0.0.1:6379> APPEND key1 hello # 追加字符串,如果当前key不存在,就相当于setkey
    (integer) 7
    127.0.0.1:6379> get key1
    "v1hello"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (2)获取字符串的长度STRLEN

    127.0.0.1:6379> STRLEN key1
    (integer) 7
    
    • 1
    • 2

    (3)自增自减

    • 自增:incr
    • 自减:decr
    127.0.0.1:6379> set view 0 #初始值为0
    OK
    127.0.0.1:6379> get view
    "0"
    127.0.0.1:6379> incr view # 自增1,返回的是自增后的值
    (integer) 1
    127.0.0.1:6379> incr view # 自增1
    (integer) 2
    127.0.0.1:6379> get view
    "2"
    127.0.0.1:6379> decr view # 自减1,返回的是自增后的值
    (integer) 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (4)设置步长

    • 设置步长指定增量:INCRBY
    • 设置步长指定减量:DECRBY
    127.0.0.1:6379> set view 0
    OK
    127.0.0.1:6379> INCRBY view 10 # 指定增10
    (integer) 10
    127.0.0.1:6379> DECRBY view 10 # 指定减10
    (integer) 0
    127.0.0.1:6379> get view
    "0"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (5)字符串范围取值GETRANGE

    127.0.0.1:6379> set key1 hello,abcdefg
    OK
    127.0.0.1:6379> get key1
    "hello,abcdefg"
    127.0.0.1:6379> GETRANGE key1 0 3 # 截取字符串[0,3]
    "hell"
    127.0.0.1:6379> GETRANGE key1 0 -1 # 获取全部的字符串和get key是一样的
    "hello,abcdefg"
    127.0.0.1:6379>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (6)替换指定位置的字符SETRANGE

    127.0.0.1:6379> set key1 abcdefg
    OK
    127.0.0.1:6379> get key1
    "abcdefg"
    127.0.0.1:6379> SETRANGE key1 1 xx # 替换指定位置开始的字符串!(这里xx是两个,所以同样也是只会替换数据当中的两个)
    (integer) 7
    127.0.0.1:6379> get key1
    "axxdefg"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (7)设置过期时间setex,前面提到过一个过期时间EXPIRE,他和setex的区别是setex还可以set值,而EXPIRE一般是给现存在的key设置过期时间!

    127.0.0.1:6379> setex key1 30 hello # 设置key1 的值为he11o,30秒后过期
    OK
    127.0.0.1:6379> ttl key1
    (integer) 25
    127.0.0.1:6379> get key1
    "hello"
    127.0.0.1:6379> ttl key1
    (integer) -2
    127.0.0.1:6379> get key1
    (nil)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (8)如果key不存在,创建key,如果存在不覆盖原来的值SETNX

    127.0.0.1:6379> SETNX mykey redis # 如果mykey不存在,创建mykey
    (integer) 1
    127.0.0.1:6379> SETNX mykey aaa # 如果mykey存在,也不会覆盖原有的值!
    (integer) 0
    127.0.0.1:6379> get mykey
    "redis"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (9)批量操作:

    • 同时设置多个值:mset
    • 同时获取多个值:mget
    • 原子性批量赋值(赋值的key不存在的时候会失败的):msetnx
    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 v5 k4 v6 # msetnx是一个原子性的操作,要么一起成功,要么一起失败!(k4是不存在的,导致失败)
    (integer) 0
    127.0.0.1:6379> get k4
    (nil)
    127.0.0.1:6379> get k1
    "v1"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    (10)关于redis存储对象常见的有两种方式:

    第一种:value存储json

    127.0.0.1:6379> set user:1 {name:zhangsan,age:3} # 设置一个user:1 对象 值为json字符来保存一个对象!
    OK
    127.0.0.1:6379> get user:1
    "{name:zhangsan,age:3}"
    
    • 1
    • 2
    • 3
    • 4

    注意:这里的json当中的属性value不能使用"引号"(单引号和双引号),不然会报错,正常的都是需要转义的

    在这里插入图片描述

    第二种:这里的key是一个巧妙的设计: user:[id):[filed] ,如此设计在Redis中是完全OK了!

    127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
    OK
    127.0.0.1:6379> mget user:1:name user:1:age
    1) "zhangsan"
    2) "2"
    127.0.0.1:6379> keys *
    1) "user:1:name"
    2) "user:1"
    3) "user:1:age"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (11)先get后setgetset

    127.0.0.1:6379> getset db redis # 如果不存在值,则返回ni1
    (nil)
    127.0.0.1:6379> get db
    "redis"
    127.0.0.1:6379> getset db mongodb # 如果存在值,获取原来的值,并设置新的值
    "redis"
    127.0.0.1:6379> get db
    "mongodb"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    String的使用场景value除了是我们的字符串还可以是我们的数字!

    • 通过以上掌握,命令当中存在自增自减,所以我们可以当做 计数器 来使用
    • 也可以用来统计多单位的数量粉丝数
    • 对象缓存存储!
    • 最常见的就是存储token,我们可以给他设置过期时间等等。

    2、List(列表)

    在redis里面,我们可以把list玩成,栈、队列、阻塞队列!

    redis当中的list说白了就是一个key值可以对应多个value值!

    所有的list命令都是用L开头的,Redis不区分大小命令

    (1)基础的命令:

    • list插入元素:LPUSH
    • 向list尾部插入值:RPUSH
    • 根据范围获取list的值:LRANGE
    • 移除list的第一个元素:lpop
    • 移除list的最后一个元素:rpop
    • 返回list列表的长度:Llen
    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 four # 将一个值或者多个值,插入到列表头部(左)
    (integer) 4
    127.0.0.1:6379> LRANGE list 0 -1 # 获取list中的值(可以看出先插入的在最后的位置,而最后插入的在最前面的位置,当然我这个前后值的是他这个序号,1234)
    1) "four"
    2) "three"
    3) "two"
    4) "one"
    127.0.0.1:6379> LRANGE list 0 1 # 通过区间获取具体的值(通过这里会发现,有点类似于栈的结构,先存进去的反而没取到,取到的后进来的)
    1) "four"
    2) "three"
    127.0.0.1:6379> RPUSH list right # 将一个值或者多个值插入到列表尾部(右)
    (integer) 5
    127.0.0.1:6379> LRANGE list 0 -1 # 获取list中的值
    1) "four"
    2) "three"
    3) "two"
    4) "one"
    5) "right"
    127.0.0.1:6379> lpop list # 移除list的第一个元素
    "four"
    127.0.0.1:6379> rpop list # 移除list的最后一个元素
    "right"
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> LLEN list # 返回list的长度
    (integer) 3
    
    • 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

    (2)LPUSHRPUSH的区别

    • LPUSH是先set的值在list当中序号最大的位置。
    • RPUSH是先set的值在list当中序号最小的位置。
    • LRANGE list 0 1:就是取list下标0和1的值,0和1是从序号最小的位置取的!
    127.0.0.1:6379> RPUSH mylist hello hello1 hello2 hello3
    (integer) 4
    127.0.0.1:6379> LRANGE mylist 0 -1
    1) "hello"
    2) "hello1"
    3) "hello2"
    4) "hello3"
    127.0.0.1:6379> LPUSH mylist1 hello hello1 hello2 hello3
    (integer) 4
    127.0.0.1:6379> LRANGE mylist1 0 -1
    1) "hello3"
    2) "hello2"
    3) "hello1"
    4) "hello"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (3)移除指定个数的元素LREM

    127.0.0.1:6379> LRANGE list 0 -1
    1) "four"
    2) "three"
    3) "three"
    4) "three"
    5) "two"
    127.0.0.1:6379> LREM list 1 three # 移除list集合中指定个数的value,精确匹配
    (integer) 1
    127.0.0.1:6379> LRANGE list 0 -1
    1) "four"
    2) "three"
    3) "three"
    4) "two"
    127.0.0.1:6379> LREM list 2 three
    (integer) 2
    127.0.0.1:6379> LRANGE list 0 -1
    1) "four"
    2) "two"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (4)list截断trim

    127.0.0.1:6379> LPUSH mylist2 hello hello1 hello2 hello3 hello4
    (integer) 5
    127.0.0.1:6379> LRANGE mylist2 0 -1
    1) "hello4"
    2) "hello3"
    3) "hello2"
    4) "hello1"
    5) "hello"
    127.0.0.1:6379> LTRIM mylist2 1 2
    OK
    127.0.0.1:6379> LRANGE mylist2 0 -1 # 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素!
    1) "hello3"
    2) "hello2"
    127.0.0.1:6379> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (5)移除列表的最后一个元素,将他移动到新的列表中rpop1push

    127.0.0.1:6379> RPUSH mylist2 hello hello1 hello2 hello3 hello4
    (integer) 5
    127.0.0.1:6379> RPOPLPUSH mylist2 mylist3 # 移除列表的最后一个元素,将他移动到新的列表中!(新的list不存在会新建)
    "hello4"
    127.0.0.1:6379> LRANGE mylist2 0 -1
    1) "hello"
    2) "hello1"
    3) "hello2"
    4) "hello3"
    127.0.0.1:6379> LRANGE mylist3 0 -1 # 查看目标列表中,确实存在该值!
    1) "hello4"
    127.0.0.1:6379> RPOPLPUSH mylist2 mylist3 # 再次移动一个,这时候mylist3就有两个元素了,他是以LPUSH的形式进行追加元素的!
    "hello3"
    127.0.0.1:6379> LRANGE mylist3 0 -1
    1) "hello3"
    2) "hello4"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    (6)将列表中指定下标的值替换为另外一个值,更新操作lset

    127.0.0.1:6379> EXISTS list # 判断这个列表是否存在
    (integer) 0
    127.0.0.1:6379> lset list 0 item # 如果不存在列表我们去更新就会报错
    (error) ERR no such key
    127.0.0.1:6379> LPUSH list value1
    (integer) 1
    127.0.0.1:6379> LRANGE list 0 -1
    1) "value1"
    127.0.0.1:6379> lset list 0 item # 如果存在,更新当前下标的值
    OK
    127.0.0.1:6379> LRANGE list 0 -1
    1) "item"
    127.0.0.1:6379> lset list 1 other # 如果当前下标不存在,也会报错!
    (error) ERR index out of range
    127.0.0.1:6379> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    (7)将某个具体的value插入到列把你中某个元素的前面或者后面linsert

    127.0.0.1:6379> RPUSH mylist hello word
    (integer) 2
    127.0.0.1:6379> LRANGE mylist 0 -1
    1) "hello"
    2) "word"
    127.0.0.1:6379> LINSERT mylist before word other # 在value为word的之前追加other元素
    (integer) 3
    127.0.0.1:6379> LRANGE mylist 0 -1
    1) "hello"
    2) "other"
    3) "word"
    127.0.0.1:6379> LINSERT mylist after word new  # 在value为word的之后追加new元素
    (integer) 4
    127.0.0.1:6379> LRANGE mylist 0 -1
    1) "hello"
    2) "other"
    3) "word"
    4) "new"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (8)栈(先进后出)的使用示例Lpush Lpop

    127.0.0.1:6379> lpush list one two three # 在list当中赋值了3个元素,其中three是最后add的
    (integer) 3
    127.0.0.1:6379> LRANGE list 0 -1 # 查询list的元素
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> LPOP list # 移除list当中的元素(one是先进来的,出的确是three)
    "three"
    127.0.0.1:6379> LRANGE list 0 -1 # 查询list的元素
    1) "two"
    2) "one"
    127.0.0.1:6379> RPUSH list fore # 假如来了个需求,将这个人最后出栈,直接使用RPUSH,如果想让他优先出栈,直接使用lpush
    (integer) 3
    127.0.0.1:6379> LRANGE list 0 -1
    1) "two"
    2) "one"
    3) "fore"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    (9)消息队列(先进先出)的使用示例Lpush Rpop

    127.0.0.1:6379> LPUSH list one two three
    (integer) 3
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> RPOP list # one是先进来的所以先进先出
    "one"
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    127.0.0.1:6379> RPUSH list fore # 有人要插队,这时候直接使用RPUSH,这样下一个出队列的就是他了
    (integer) 3
    127.0.0.1:6379> LRANGE list 0 -1
    1) "three"
    2) "two"
    3) "fore"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    小结:

    • 他实际上是一个链表, before Node after , left, right 都可以插入值
    • 如果key不存在,创建新的链表,如果key存在,新增内容
    • 如果移除了所有值,空链表,也代表不存在!
    • 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~

    List的使用场景:消息队列(Lpush Rpop) , 栈( Lpush Lpop)

    3、Set(集合)

    redis当中的Set说白了就是List一样,一个key值可以对应多个value值,唯一区别就是set中的值是不能重复的,当已经一个key中对应的value值已经有a了,这时候再向这个key当中添加a就会失败!

    所有的set命令都是用S开头的,Redis不区分大小命令

    (1)基础的命令:

    • set集合当中添加数据(可以一下子添加多个):SADD
    • 查看指定的set的所有值:SMEMBERS
    • 判断某一个值是不是在set集合:SISMEMBER
    • 获取set集合中的内容元素个数:SCARD
    • 移除set集合中的指定元素:SREM
    127.0.0.1:6379> SADD myset hello # set集合当中添加数据
    (integer) 1
    127.0.0.1:6379> sadd myset aaaa
    (integer) 1
    127.0.0.1:6379> sadd myset bbbb cccc # set集合同时添加多个值
    (integer) 2
    127.0.0.1:6379> SMEMBERS myset # 查看指定的set的所有值
    1) "bbbb"
    2) "cccc"
    3) "aaaa"
    4) "hello"
    127.0.0.1:6379> sadd myset aaaa # 向set当中存储相同值的时候,会返回0代表失败
    (integer) 0
    127.0.0.1:6379> SISMEMBER myset hello # 判断某一个值是不是在set集合,如果存在返回1,不存在返回0
    (integer) 1
    127.0.0.1:6379> SISMEMBER myset word
    (integer) 0
    127.0.0.1:6379> SCARD myset # 获取set集合中的内容元素个数!
    (integer) 4
    127.0.0.1:6379> SREM myset hello # 移除set集合中的指定元素
    (integer) 1
    127.0.0.1:6379> scard myset # 获取set集合中的内容元素个数!
    (integer) 3
    127.0.0.1:6379> SMEMBERS myset # 查看指定的set的所有值
    1) "cccc"
    2) "bbbb"
    3) "aaaa"
    
    • 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

    (2)从set集合当中抽随机

    • 可以抽取一个,也可以抽取多个,只是从中抽取,并不会删除元素:SRANDMEMBER
    127.0.0.1:6379> SADD myset a b c d e f g
    (integer) 7
    127.0.0.1:6379> SRANDMEMBER myset # myset当中抽取1个
    "b"
    127.0.0.1:6379> SRANDMEMBER myset
    "d"
    127.0.0.1:6379> SRANDMEMBER myset 2 # myset当中抽取2个
    "b"
    1) "d"
    2) "a"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (3)随机删除set集合当中的元素spop

    127.0.0.1:6379> SMEMBERS myset # 查询myset当中的所有value值
    1) "e"
    2) "f"
    3) "a"
    4) "g"
    5) "c"
    6) "d"
    7) "b"
    127.0.0.1:6379> spop myset # 随机删除一个,删除过后返回的是删除的值
    "f"
    127.0.0.1:6379> SMEMBERS myset
    1) "e"
    2) "a"
    3) "g"
    4) "c"
    5) "d"
    6) "b"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    (4)将一个指定的值,移动到另外一个set集合smove

    127.0.0.1:6379> SADD myset a b c d
    (integer) 4
    127.0.0.1:6379> smove myset myset2 a # 将一个指定的值,移动到另外一个set集合
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset
    1) "d"
    2) "c"
    3) "b"
    127.0.0.1:6379> SMEMBERS myset2
    1) "a"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (5)数据集合类

    • 差集:SDIFF
    • 交集:SINTER
    • 并集:SUNION
    127.0.0.1:6379> SADD myset a b c
    (integer) 3
    127.0.0.1:6379> SADD myset1 c d e
    (integer) 3
    127.0.0.1:6379> SDIFF myset myset1 # 差集,myset存在的,而myset1不存在的元素
    1) "a"
    2) "b"
    127.0.0.1:6379> SINTER myset myset1 # 交集,两个共同相同的元素
    1) "c"
    127.0.0.1:6379> SUNION myset myset1 # 并集,两个set进行去重
    1) "a"
    2) "c"
    3) "b"
    4) "e"
    5) "d"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用场景:

    • 微博当中,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!
    • 共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)
    • set本身就具备去重,再加上他是有抽去随机的功能,所以抽奖可以用set数据结构来做

    六度分割理论:你和任何一个陌生人之间所间隔的人不会超过六个

    • 数学解释:若每个人平均认识260人,其六度就是260的6次方=308,915,776,000,000(约300万亿)。消除一些节点重复,那也几乎覆盖了整个地球人口若干多倍。

    4、Hash(哈希表)

    Hash数据结构,就是key对应的value是一个map集合!

    所有的Hash命令都是用H开头的,Redis不区分大小命令!

    (1)基础的命令:

    • 创建一个Hash:hset
    • 获取一个字段值:hget
    • set多个key-vlaue(也可以当中覆盖来使用):hmset
    • 获取多个字段值:HMGET
    • 获取全部的数据(ke value都获取):HGETALL
    127.0.0.1:6379> hset myhash user zhangsan # set一个具体 key-vlaue
    (integer) 1
    127.0.0.1:6379> hget myhash user # 获取一个字段值
    "zhangsan"
    127.0.0.1:6379> hmset myhash user lisi # 覆盖user属性的值
    OK
    127.0.0.1:6379> hget myhash user
    "lisi"
    127.0.0.1:6379> hmset myhash user hello age 8 # set多个key-vlaue(hmset会覆盖hset的值)
    OK
    127.0.0.1:6379> HMGET myhash user age # 获取多个字段值
    1) "hello"
    2) "8"
    127.0.0.1:6379> HGETALL myhash # 获取全部的数据
    1) "user"
    2) "hello"
    3) "age"
    4) "8"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (2)删除hash指定key字段!对应的value值也就消失了hdel

    127.0.0.1:6379> hmset myhash user hello age 8
    OK
    127.0.0.1:6379> hdel myhash user # 删除hash指定key字段!对应的value值也就消失了!
    (integer) 1
    127.0.0.1:6379> hgetall myhash
    1) "age"
    2) "8"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (3)数量、判断是否存在、获得map里面所有的key、获得所有的value

    • 获取hash表的字段数量:hlen
    • 判断hash中指定字段是否存在(存在返回1,不存在返回0):HEXISTS
    • 只获得所有field(field就是value当中的key):hkeys
    • 只获得所有value:HVALS
    127.0.0.1:6379> hmset myhash user hello age 8
    OK
    127.0.0.1:6379> hlen myhash # 获取hash表的字段数量!
    (integer) 2
    127.0.0.1:6379> HEXISTS myhash user # 判断hash中指定字段是否存在!
    (integer) 1
    127.0.0.1:6379> HDEL myhash user #删除hash指定key字段!对应的value值也就消失了!
    (integer) 1
    127.0.0.1:6379> HEXISTS myhash user # 判断hash中指定字段是否存在!(不存在返回0)
    (integer) 0
    127.0.0.1:6379> hkeys myhash # 只获得所有field
    1) "age"
    127.0.0.1:6379> HVALS myhash # 只获得所有value
    1) "8"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (4)指定增量HINCRBY
    如果不存在则可以设置,存在则不能设置(hmset是存在可以覆盖,不存在可以创建):hsetnx

    127.0.0.1:6379> hset myhash count 5
    (integer) 1
    127.0.0.1:6379> HINCRBY myhash count 1 # 指定count+1,返回新的count属性的值
    (integer) 6
    127.0.0.1:6379> HINCRBY myhash count -1 # 指定count-1,返回新的count属性的值
    (integer) 5
    127.0.0.1:6379> hsetnx myhash field1 hello # 如果不存在则可以设置
    (integer) 1
    127.0.0.1:6379> HSET myhash field1 word # 如果存在则不能设置
    (integer) 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (5)对象存储:hash更适合于对象的存储,String更加适合字符串存储~!

    127.0.0.1:6379> hset user:1 name zhangsan age 8
    (integer) 2
    127.0.0.1:6379> hget user:1 age
    "8"
    
    • 1
    • 2
    • 3
    • 4

    5、Zset(有序集合)

    Zset有的地方也会叫做SortedSet,Zset就是在set基础上添加了一个序号,当我们获取set当中所有的属性的时候,默认会根据这个序号进行排序!

    所有的Zset命令都是用Z开头的,Redis不区分大小命令!

    在set的基础上,增加了一个值

    • set赋值:set k1 v1
    • zset赋值:zset k1 score1 v1(一般我们把这个score1叫做分数)

    (1)基础的命令:

    • 添加值:ZADD
    • 获取下标(这里是下标不是我们设置的那个数值)区间的值,按分数升序排序的(带WITHSCORES会将数值也返回来):ZRANGE
    • 获取下标(这里是下标不是我们设置的那个数值)区间的值,按分数倒序排序的(带WITHSCORES会将数值也返回来):ZREVRANGE
    • 返回分数区间的值,按分数从低到高排序的(带WITHSCORES会将数值也返回来):ZRANGEBYSCORE
    127.0.0.1:6379> ZADD myset 5 five # 添加1个值
    (integer) 1
    127.0.0.1:6379> ZADD myset 1 one # 添加1个值
    (integer) 1
    127.0.0.1:6379> ZADD myset 4 fore 3 three # 添加多个值
    (integer) 2
    127.0.0.1:6379> ZRANGE myset 0 -1 # 查询的时候会发现,默认是按照从小到大排序的
    1) "one"
    2) "three"
    3) "fore"
    4) "five"
    127.0.0.1:6379> ZRANGE myset 0 -1 WITHSCORES # 带WITHSCORES会将数值也返回来
    1) "one"
    2) "1"
    3) "three"
    4) "3"
    5) "fore"
    6) "4"
    7) "five"
    8) "5"
    127.0.0.1:6379> ZRANGEBYSCORE myset 1 4 # 获取数值 1-4的value
    1) "one"
    2) "three"
    3) "fore"
    127.0.0.1:6379> ZRANGEBYSCORE myset 1 4 WITHSCORES # 获取数值 1-4的value和设置的数值
    1) "one"
    2) "1"
    3) "three"
    4) "3"
    5) "fore"
    6) "4"
    127.0.0.1:6379> ZRANGEBYSCORE myset -inf +inf WITHSCORES #min和max可以是-inf和+inf,这样就相当于返回所有的
    1) "one"
    2) "1"
    3) "three"
    4) "3"
    5) "fore"
    6) "4"
    7) "five"
    8) "5"
    127.0.0.1:6379> ZREVRANGE myset 0 -1 # 获取所有的值,倒序排序
    1) "five"
    2) "fore"
    3) "three"
    4) "one"
    127.0.0.1:6379> ZREVRANGE myset 0 -1 WITHSCORES # 获取所有的分数和值,倒序排序
    1) "five"
    2) "5"
    3) "fore"
    4) "4"
    5) "three"
    6) "3"
    7) "one"
    8) "1"
    
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    (2)根据元素进行移除zrem

    127.0.0.1:6379> ZADD myset 1 one 3 three # set两个值
    (integer) 2
    127.0.0.1:6379> ZRANGE myset 0 -1 # 查询zset当中所有值
    1) "one"
    2) "three"
    127.0.0.1:6379> zrem myset one # 移除有序集合中的指定元素
    (integer) 1
    127.0.0.1:6379> ZRANGE myset 0 -1
    1) "three"
    127.0.0.1:6379> ZCARD myset # 获取有序集合中的个数
    (integer) 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (3)统计分数区间的数量ZCOUNT

    127.0.0.1:6379> ZADD myset 1 one 4 fore
    (integer) 2
    127.0.0.1:6379> ZCOUNT myset 1 3 # 获取指定区间的成员数量!
    (integer) 1
    
    • 1
    • 2
    • 3
    • 4

    使用场景: set排序可以存储班级成绩表,工资表排序!

    Redis的数据类型不仅仅只有这五种,只不过这五种是最常用的,而且面试经常会问到的,Redis所有的数据类型都是指的value的数据类型!

  • 相关阅读:
    FFmpeg转换器分析-基础篇
    OpenglEs之三角形绘制
    普通人做自媒体视频剪辑会有出路吗?
    Oracle查询
    一、java版 SpringCloud分布式微服务云架构之Java 简介
    QT下跨平台库实现及移植经验分享
    软考随记(二)
    Unity下tga和png格式图片打包成AB包大小和加载速度测试
    Flutter视频播放video_player + chewie
    2023小米秋招真题-手机流畅运行的秘密
  • 原文地址:https://blog.csdn.net/weixin_43888891/article/details/125837793