Redis的五种数据类型详解

2023-10-28

本篇文章更多的是通过命令来彻底掌握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是一个key value的缓存数据库,常用的有五种数据类型,所谓的数据类型都由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"

(2)清除数据库

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

(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"

(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)

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

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

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

127.0.0.1:6379> set test1 111
OK
127.0.0.1:6379> del test1
(integer) 1

二、五种数据类型

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"

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

127.0.0.1:6379> STRLEN key1
(integer) 7

(3)自增自减

  • 自增:incr
  • 自减:decr

自增是有范围的,它的范围是signed long 的最大最小值,超过了这个值,Redis 会报错。INCR是原子操作,即使多个客户端对同一个密钥发出INCR,也永远不会进入竞争状态。例如,客户机1读取“10”,客户机2同时读取“10”,两者都增加到11,并将新值设置为11,这样的情况永远不会发生。最终的值将始终是12,并且在所有其他客户机不同时执行命令时执行读-增量集操作。

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

127.0.0.1:6379> set codehole 9223372036854775807
OK
127.0.0.1:6379> get codehole
"9223372036854775807"
127.0.0.1:6379> incr codehole
(error) ERR increment or decrement would overflow
127.0.0.1:6379>

(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"

(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>

(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"

(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)

(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"

(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"

(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}"

注意:这里的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"

(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"

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

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

2、List(列表)

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

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

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

(1)基础的命令:

  • list插入元素:LPUSH
  • 向list尾部插入值:RPUSH
  • 移除list的第一个元素:lpop
  • 移除list的最后一个元素:rpop
  • 返回list列表的长度:Llen
  • 根据坐标获取值:lindex
  • 根据范围获取list的值:LRANGE
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> lindex list 0 # 根据坐标获取值
"two"
127.0.0.1:6379> lindex list 1 # 根据坐标获取值
"one"
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

(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"

(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"

(4)list截断LTRIM

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 # 只保留坐标为1和2的
OK
127.0.0.1:6379> LRANGE mylist2 0 -1 # 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素!
1) "hello3"
2) "hello2"
127.0.0.1:6379> 

(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"

(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> 

(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"

(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"

(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"

lindex、lrange还有ltrimd都是以index下标来作为条件,其中lrangehe和ltrimd是两个参数 start_index 和 end_index 定义了一个区间,index 可以为负数,index=-1 表示倒数第一个元素,同样 index=-2 表示倒数第二个元素。

Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为O(n),这点让人非常意外。这意味着这些根据下标来查询值的它需要对链表进行遍历,性能随着参数index 增大而变差。

小结:

  • 他实际上是一个链表, 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"

(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"

(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"

(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"

(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"

使用场景:

  • 微博当中,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"

(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"

(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"

(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

(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"

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"

(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

(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

(4)获取指定 value 的 scorezscore

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> zadd books 9.0 "think in java"
(integer) 1
127.0.0.1:6379>  zadd books 8.9 "java concurrency"
(integer) 1
127.0.0.1:6379>  zscore books "java concurrency"  # 内部 score 使用 double 类型进行存储,所以存在小数点精度问题
"8.9000000000000004"

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis的五种数据类型详解 的相关文章

  • 仅当尚未设置时才进行原子设置

    仅当尚未在 Redis 中设置时 是否有办法执行原子设置 具体来说 我正在创建一个像 myapp user user email 这样的用户 并且希望 Redis 在 user email 已被占用时返回错误 而不是默默地替换旧值 比如声明
  • PooledRedisClientManager 未释放连接

    我将 json 数据列表存储在 redis 中并使用 ServiceStack c 客户端访问它 我本质上是在管理自己的外键 我在其中存储zrangeid 我使用应用程序内部的接口从zrange然后从 Redis 获取底层 json 对象并
  • 如何在节点redis客户端上设置读取超时?

    在 github 上我没有看到读取超时的选项 https github com NodeRedis node redis https github com NodeRedis node redis There s connect timeo
  • 如何测试我的 Redis 缓存是否正常工作?

    我已经安装了 django redis cache 和 redis py 我遵循了 Django 的缓存文档 据我所知 以下设置就是我所需要的 但我如何判断它是否正常工作 设置 py CACHES default BACKEND redis
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • 使用 Redis 命令 incr 和 expire 时的竞争条件

    根据redis文档 http redis io commands incr http redis io commands incr 在段落模式 速率限制器 2 较短的版本代码 value INCR ip IF value 1 THEN EX
  • socket.io 广播功能 & Redis pub/sub 架构

    如果有人能帮助我解决一个小疑问 我将不胜感激 使用socket io广播功能和在Redis上使用pub sub设计架构有什么区别 例如 在另一个示例中 node js 服务器正在侦听 socket io 针对 键 模型 todo 和值 数据
  • Node Js:Redis 作业在完成其任务后未完成

    希望你们做得很好 我在我的 Nodejs 项目中实现了 BullMQ Bull 的下一个主要版本 来安排发送电子邮件的作业 例如 发送忘记密码请求的电子邮件 所以 我编写了如下所示的代码 用户服务 await resetPasswordJo
  • Lua中按字符分割字符串

    我有像这样的字符串 ABC DEF 我需要将它们分开 字符并将两个部分分别分配给一个变量 在 Ruby 中 我会这样做 a b ABC DEF split 显然Lua没有这么简单的方法 经过一番挖掘后 我找不到一种简短的方法来实现我所追求的
  • 2 个具有共享 Redis 依赖的 Helm Chart

    目前 我有 2 个 Helm Charts Chart A 和 Chart B Chart A 和 Chart B 对 Redis 实例具有相同的依赖关系 如Chart yaml file dependencies name redis v
  • redis - 使用哈希

    我正在使用 redis 为我的 Web 应用程序实现社交流和通知系统 我是 redis 的新手 我对哈希值及其效率有一些疑问 我读过这篇很棒的文章Instagram 帖子 http instagram engineering tumblr
  • StackExchange.Redis的正确使用方法

    这个想法是使用更少的连接和更好的性能 连接会随时过期吗 对于另一个问题 redis GetDatabase 打开新连接 private static ConnectionMultiplexer redis private static ID
  • 想要在后台不间断地运行redis-server

    我已经下载了 redis 2 6 16 tar gz 文件并安装成功 安装后我运行 src redis server 它工作正常 但我不想每次都手动运行 src redis server 而是希望 redis server 作为后台进程持续
  • Scala 使用的 Redis 客户端库建议

    我正在计划使用 Scala 中的 Redis 实例进行一些工作 并正在寻找有关使用哪些客户端库的建议 理想情况下 如果存在一个好的库 我希望有一个为 Scala 而不是 Java 设计的库 但如果现在这是更好的方法 那么仅使用 Java 客
  • Spring Redis删除不删除key

    我正在尝试删除一个 Redis 键 但由于某种原因它没有删除 但也没有抛出异常 这是我要删除的代码 import com example service CustomerService import com example model Cu
  • Laravel 异常队列最大尝试次数超出

    我创建了一个应用程序来向多个用户发送电子邮件 但在处理大量收件人时遇到问题 该错误出现在failed jobs table Illuminate Queue MaxAttemptsExceededException App Jobs ESe
  • 如何使用 Redis 自动删除与模式匹配的键

    在我的 Redis DB 中 我有很多prefix
  • docker-compose:容器之间的 Redis 连接被拒绝

    我正在尝试设置一个 docker compose 文件 该文件旨在替换运行多个进程 RQ 工作线程 RQ 仪表板和 Flask 应用程序 的单个 Docker 容器解决方案导师 http supervisord org 主机系统是 Debi
  • Laravel Redis 配置

    我目前正在使用 Laravel 和 Redis 创建一个应用程序 几乎一切都工作正常 我按照文档中的说明扩展了身份验证 用户可以订阅 登录 注销 我可以创建内容 所有内容都存储在 Redis 中 但我有一个问题 我无法运行 php arti
  • 将文件传递给活动作业/后台作业

    我通过标准文件输入接收请求参数中的文件 def create file params file upload Upload create file file filename img png end 但是 对于大型上传 我想在后台作业中执行

随机推荐

  • Transformer学习笔记

    The Illustrated Transformer Jay Alammar Visualizing machine learning one concept at a time jalammar github io 上面是图片出处 是否
  • CSS列表与表格

    目录 编辑 HTML 列表和 CSS 列表属性 不同的列表项目标记 实例 图像作为列表项标记 实例 定位列表项标记 实例 删除默认设置 实例 列表 简写属性 实例 设置列表的颜色样式 实例 更多实例 所有 CSS 列表属性 表格边框 实例
  • python PDF转docx库的安装与使用

    python PDF转docx库的安装与使用 下载 使用 三种方法 效果 下载 anaconda中直接通过anaconda prompt下载pdf2docx库 pip install pdf2docx 使用 三种方法 可以直接通过命令行使用
  • SpringMVC基础(5): SpringMVC常用注解

    目录 1 handler method 参数绑定常用注解 2 常用注解 1 PathVariable 2 RequestHeader CookieValue 3 Re Body 5 RequestBody和 RequestParam区别 6
  • 安装部署mysql、redis、minio、nginx

    离线安装部署mysql redis minio nginx jar包启动 系统环境 centos7 9 架构 X86 安装目录 server 记录安装笔记 依赖项在线安装的 下载离线依赖 yum install y nginx downlo
  • 最新升级的STM32CubeIDE属于一站式工具,本文带你体验它的强大

    目录 下载安装 配置生成代码 硬件在线调试 1 写在前面 2 STM32CubeIDE介绍 主要特点 3 STM32CubeIDE下载 4 STM32CubeMX安装 5创建工程并编译 下载安装 配置生成代码 硬件在线调试 1 写在前面 S
  • Vue 如何使用WebSocket与服务器建立链接 持续保持通信

    WebSocket 浏览器通过JavaScript向服务器发出建立WebSocket链接的请求 链接建立后 客户端和服务器端就可以通过TCP链接直接交互数据 WebSocket链接后可以通过send 方法来向服务器发送数据 并通过onnes
  • 【nodejs课堂】Node.js 创建第一个应用

    在我们创建Node js第一个 hello world 应用前 先了解一下Node js应用由哪几部分组成 1 引入required模块 我们可以使用require指令来载入Node js模块 2 创建服务器 服务器可以监听客户端的请求 类
  • MyEclipse8 GA 下载地址 注册码 优化指南

    官方网站限制大陆IP 可以通过http ajava org 直接下载 下面是winodws linux的下载地址 其他版本请自行去http ajava org 下载 注册码7 5GA 8 0GA貌似通用 但不绝对 window版下载地址 h
  • 语义分割数据增强(Data augmentation for semantic segmentation)

    数据增强 深度学习模型的鲁棒性 robustness 和泛化性受到训练数据的多样性和数据量所影响 数据增强 data augmentation 是机器学习和深度学习中经常采用的一个方法 其目的是扩大训练样本的数量 语义分割是计算机视觉一个重
  • 期货十三篇 第七篇 平仓篇

    在期货交易中曾经流行这样一句话 会开仓的是徒弟 会平仓的是师傅 会空仓的是大师傅 在最初的期货交易过程中 我的开仓还算比较顺利 基本上都可以获得一定的盈利 但是我的平仓却十分糟糕 往往把自己的盈利单变成微利单或者亏损单而狼狈离场 我实在不能
  • 贝锐蒲公英:助力企业打造稳定高效的智能安防监控网络

    随着技术的快速发展和物联网的普及 企业面临着许多安全威胁和风险 如盗窃 入侵 信息泄露等 企业需要建立安防监控系统来保护其资产 员工和业务运营的安全 然而 企业在搭建安防监控系统的过程中 可能会面临一些难点 包括以下几个方面 1 监控设备多
  • sysdig_系统分析工具 Sysdig 详解

    Sysdig 是 Sysdig Cloud 开发的主要基于Lua语言的一个开源系统分析工具 Sysdig 能从运行的系统中 获取系统状态和行为 做过滤分析 功能上超同类开源工具 Sysdig 可以看做是 strace tcpdump lso
  • Java将图片转换成透明底图片

    package com stefan test import java awt Graphics2D import java awt Image import java awt image BufferedImage import java
  • android黑科技系列——手机端破解神器MT的内购VIP功能破解教程

    一 前言 在破解app的时候 我们现在几乎都是在PC端进行操作 但是之前bin神的MT管理器 可以在手机端直接破解 不过也有很大的局限性 但是对于一些简单的app破解没问题的 这个工具其实原理也很简单 就是解析apk中的dex arsc等文
  • 宝兰德BES中间件单机版安全加固相关操作

    因某公司对安全的要求 需要对bes中间件进行安全加固 安全加固的内容主要包括对控制台默认地址修改 实例默认端口修改 控制台默认密码修改 密码加密 加密后的实例启停方式等 首先说一下今天安全加固操作的前提 需要已经分离式部署安装成功bes单机
  • 什么是数据结构?什么是算法

    记得是大一大二的时候学习了数据结构 时间过的好快 现在实现了 现在感觉自己的基础好差很多都不会 欠的帐还是要还的 什么是数据结构 什么是算法 呃呃呃呃 哎 不会 多次参加了MOOC姥姥的数据结构 都没有坚持下来 希望这次可以坚持下来 引用姥
  • MySQL 查询表字段

    复制表结构 CREATE TABLE tb students copy LIKE tb students info 查询mysql所有表数据 字段信息mysql 查询表 所有字段 前2种有重复 select COLUMN NAME colu
  • LINQ之路 8: 解释查询(Interpreted Queries)

    LINQ提供了两个平行的架构 针对本地对象集合的本地查询 local queries 以及针对远程数据源的解释查询 Interpreted queries 在讨论LINQ to SQL等具体技术之前 我们有必要先对这两种架构进行了解和学习
  • Redis的五种数据类型详解

    目录 一 基础的知识 二 五种数据类型 1 String 字符串 2 List 列表 3 Set 集合 4 Hash 哈希表 5 Zset 有序集合 本篇文章更多的是通过命令来彻底掌握Redis的五种数据结构 一 基础的知识 Linux上安