[Redis] Redis中的Hash类型和List类型

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. Redis中关于Hash相关的操作
    • 1.1 Hash的存储方式
    • 1.2 关于Hash的常见命令
    • 1.3 指令小结
  • 2. Hash的内部编码方式
  • 3. hash的应用场景
    • 3.1 作为缓存
  • 4. Redis中关于List的操作
    • 4.1 概述
    • 4.2 特点
    • 4.3 相关指令
    • 4.4 阻塞版本指令
      • 4.4.1 特点概述
      • 4.4.2 指令
    • 4.5 指令小结
  • 5. list内部编码方式
  • 6. list的应用场景

1. Redis中关于Hash相关的操作

1.1 Hash的存储方式

在我们之前学习数据结构的时候,我们就曾经接触过HashMap等哈希表相关的集合类.我们知道,在哈希表中存储的是键值对的结构.这里Redis中存储数据本身就是以键值对的形式存储的. 其中key是string类型的数据,要是想要在Redis中存储Hash,那么Redis中的value的类型就是Hash类型的数据.也就是在Hash中又存储了一层Hash.
在这里插入图片描述

注意事项: 为了区分Redis中整体的键值对和Hash数据类型的键值对,我们一般把Hash的键值对分别叫做key-field,Redis整体的键值对叫做key-value.

1.2 关于Hash的常见命令

Hash相关操作的命令一般在前面都有一个h开头.

  • hset
    hset key field value [field value...]
    设置Hash中的指定字段和指定值,可以一次性设置多个,也可以一次性设置一个.返回添加字段的个数.
  • hget
    hget key field
    获取某Hash中field的value.一次只可以获取一个.
127.0.0.1:6379> hset key1 field1 value1 field2 value2
(integer) 2
127.0.0.1:6379> hget key1 field1
"value1"
127.0.0.1:6379> hget key1 field2
"value2"
  • hexists
    hexists key field
    判断某个Hash中的某个field是否存在.
127.0.0.1:6379> HEXISTS key1 field1 field2
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> HEXISTS key1 field1
(integer) 1

注意: 在hexists命令中,不支持一次性查询多个field,一次只可以查询 一个field.

  • hdel
    hdel key field [field]
    删除Hash中的元素,可以一次删除一个元素,也可以一次删除多个元素.返回的是本次操作成功删除的字段.
127.0.0.1:6379> hdel key1 field1
(integer) 1
127.0.0.1:6379> hget key1 field1
(nil)
  • hkeys
    hkeys key
    查询指定key中的所有字段.
127.0.0.1:6379> hkeys key1
1) "field2"
  • hvals
    hvals key
    查询指定key中的所有值.
127.0.0.1:6379> hvals key1
1) "value2"
  • hgetall
    hgetall key
    获取指定key中的所有的field和value.返回值是Hash中所有的键值对.
127.0.0.1:6379> hgetall key1
1) "field2"
2) "value2"

[注意事项] 以上的三个操作和前面我们提到的string的keys *一样,存在一定的风险,我们不可以确定这个key对应的Hash中是否有很多键值对.
redis中倒是有这么一个命令会避免这些风险,它叫hscan,它属于渐进式遍历的指令,就是敲一次命令,遍历一小部分,再敲一次,在遍历一部分.有点像我们在多线程中学习的ConcurrentHashMap 的扩容机制,扩容复制元素的时候并不是一次性全部把元素全部拷贝过去,新老数组同时存在,之后每对ConcurrentHashMap操作一次,就拷贝一部分,直到把老数组的元素全部拷贝完成,老数组就会被删除.

  • hmget
    hmget key field [field...]
    一次性查询Hash中多个字段的值,返回查询到的value.
127.0.0.1:6379> hset key2 field1 value1 field2 value2 field3 value3
(integer) 3
127.0.0.1:6379> hgetall key2
1) "field1"
2) "value1"
3) "field2"
4) "value2"
5) "field3"
6) "value3"
127.0.0.1:6379> hmget key2 field1 field2 field3
1) "value1"
2) "value2"
3) "value3"

有的人现在就会想到,有没有hmset,用来一次性设置多个Hash中的键值对呢?有,但是没有必要,因为我们之前讲到的hset指令就可以一次性设置多个键值对.

  • hlen
    hlen key
    获取Hash中的元素个数.
127.0.0.1:6379> hmget key2 field1 field2 field3
1) "value1"
2) "value2"
3) "value3"
127.0.0.1:6379> hlen key2
(integer) 3
  • hsetnx
    hsetnx key field value
    类似与string操作中的setnx,如果Hash中不存在对应的键值对的话,才可以创建成功,如果存在,就创建失败.
127.0.0.1:6379> hsetnx key2 field4 value4
(integer) 1
127.0.0.1:6379> hgetall key2
1) "field1"
2) "value1"
3) "field2"
4) "value2"
5) "field3"
6) "value3"
7) "field4"
8) "value4"
127.0.0.1:6379> hsetnx key2 field2 value2
(integer) 0
  • hincrby
    hincrby key field increment
    给指定的Hash中的字段对应的值加上指定的值.返回的值是加上指定值之后的值.
127.0.0.1:6379> hset key2 field5 1
(integer) 1
127.0.0.1:6379> HINCRBY key2 field5 2
(integer) 3
127.0.0.1:6379> hget key2 field5
"3"
  • hincrbyfloat
    hincrbyfloat key field incrment
    给指定的Hash中的字段对应的值加上指定的小数.返回加上指定值之后的值.
127.0.0.1:6379> HINCRBYFLOAT key2 field5 0.7
"3.7"
127.0.0.1:6379> hget key2 field5
"3.7"

[注意] 在Redis中并没有对Hash提供像string那样的incr,decr,decrby类似的命令,我们想要对Hash对应字段的值+1,只可以使用hincrby key field 1这样的命令,想要-1,就需要hincrby key field -1这样的指令来代替,想要减指定的值,比如-2,就只能使用hincrby key field -2这样的指令来代替.其他的一些操作与上同理.

127.0.0.1:6379> hget key2 field5
"3.7"
127.0.0.1:6379> hincrbyfloat key2 field5 -0.2
"3.5"
127.0.0.1:6379> hset key2 field6 8
(integer) 1
127.0.0.1:6379> HINCRBY key2 field6 -2
(integer) 6

1.3 指令小结

在这里插入图片描述

2. Hash的内部编码方式

Hash内部编码的方式有两种,一种是hashtable,一种是ziplist.

  • ziplist
    在Hash内部元素比较少(默认阈值512个)而且字段对应的值字节数都比较短(默认阈值64字节)的时候,我们一般使用ziplist.
    ziplist会对Hash表进行一定的压缩,会占用比较少的空间.但是也有一定的代价.就是在读写元素的时候,速度是比较慢的,如果元素个数较少,慢一点也不明显,但是如果元素比较多,读写慢就会让Hash雪上加霜.
  • hashtable
    在hash中的元素个数比较多,或者是某一个元素对应的值的字节数比较长,就会让hash的编码方式从原来的ziplist转变为hashtable.
    *其中转变阈值可以在Redis(/etc/redis/redis.conf)的配置文件中设置.*一个属性是hash-max-ziplist-entries,用于配置限制hash中元素的个数,一个属性是hash-max-ziplist-value,用于配置hash中每个value中的长度限制.
    下面对编码方式的转换进行验证:
127.0.0.1:6379> hset key3 field1 value1 field2 value2
(integer) 2
127.0.0.1:6379> OBJECT encoding key3
"ziplist"
127.0.0.1:6379> hset key3 field3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
(integer) 1
127.0.0.1:6379> OBJECT encoding key3
"hashtable"
127.0.0.1:6379> hmset hashkey f1 v1 h2 v2 f3 v3 ... 省略 ... f513 v513
OK
127.0.0.1:6379> object encoding hashkey
"hashtable"

3. hash的应用场景

3.1 作为缓存

Redis中存储用户信息的方式不同于MySQL数据库,Redis是一种非关系型数据库,MySQL是一种关系型数据库,Redis中存储数据是以键值对的方式(映射关系)存储的,MySQL中存储数据是以表的方式存储的.
比如我们想要在Redis和MySQL中存储用户信息.
关系型数据表存储结构如下:
在这里插入图片描述
映射关系存储结构如下:
在这里插入图片描述

  1. 从上述的数据存储的方式中,我们可以看出,使用hash的方式存储数据在读写的时候更加的直观高效.
  2. 哈希类型是稀疏的,而关系型数据库是完全结构化的,例如哈希类型每个键可以有不同的field,而关系型数据库⼀旦添加新的列,所有行都要为其设置值,即使为null.
  3. 但是Redis也相对于MySQL有一定的缺点,Redis付出一些空间的代价.这是因为hash在编码转换的时候,需要消耗一定的内存空间.其次,关系数据库可以做复杂的关系查询,而Redis去模拟关系型复杂查询,例如联表查询、聚合查询等基本不可能,维护成本高.
    在这里插入图片描述

上述这种数据的存储使用json字符串的方式也可以存储.
如果我们使用json字符串的话,只读取某一个字段的时候,需要先把json读取出来,之后解析为对象,之后对想要操作的指端进行操作,之后再重写为json字符串,之后再重新写回去.
如果使用hash的凡是来表示的时候,就可以直接使用字段中相应的值,此时就可以非常方便的修改和获取一个属性的值了.避免了对象和字符串之间来回解析的工作.

我们还可以使用原生字符串的形式表示,*使用Redis中的字符串类型,每个属性一个键值对.

set user:1:name James
set user:1:age 23
set user:1:city Beijing

这种表示方式,相当于把同一个数据给分散开表示了,这样的表现方式就是低内聚的表现方式.而使用hash来存储数据,就会把同一个对象的所有数据都保存在一起.这样的表现方式就是高内聚的.我们在编程的时候,一般使用的是高内聚的表现方式.

4. Redis中关于List的操作

4.1 概述

提到list我们会想到java中的List集合,这样的List就相当于数组或者是顺序表.
但是Redis中的List并非是一个简单的数组,更接近于双端队列(deque).因为Redis中的list支持头插,头删,尾插,尾删,还可以获取指定范围之内的元素和指定下表的元素(和python一样,支持负数下标).它可以充当栈和队列的角色.在实际开发中的应用场景非常广泛.
在这里插入图片描述

4.2 特点

  • 列表中的元素是有序的
    这里的有序,指的是list中的元素可以通过下标来访问.这里的下标可以是正数下表,可以是负数下标.和python一样,正数下标从0开始,负数下标从-1开始.正数表示的是第n+1个元素,负数表示的是倒数第n个元素.
  • 区分删除和获取的区别
    这里之所以要区分,是因为删除和获取的返回值都是指定下标的值.容易混淆.
  • 列表中的元素允许重复
    -在这里插入图片描述
    在这里插入图片描述

4.3 相关指令

  • lpush
    lpush key element [element...]
    从list的左端插入指定的元素,(lpush中的l就是left的缩写). 可以一次插入多个元素,也可以一次插入一个元素.这里需要注意的是,并不是把这些所有的元素整体进行头插,而是按照顺序依次头插.比如我们要在一个list中插入1234,插入完成之后,list的头部是4321的顺序.如果key不存在,创建列表,如果已经创建了key,key对应的value必须是列表类型,否则报错.
  • lrange
    lrange key start stop
    查询列表中指定范围的所有元素.这个指令支持负数下标.其中start区间和stop区间都是闭区间.(这里的l和上面的l意义不一样,这里的l指的是list),如果想要查询list中所有元素的值,就需要使用lrange key 0 -1这个指令.
127.0.0.1:6379> lpush key1 1 2 3 4
(integer) 4
127.0.0.1:6379> lrange key1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"

谈到下标,我们往往就会关注下标越界的情况,在java中,要是数组或者线性表下表越界,就会抛出下表越界的异常.但是Redis中并没有采取上述的方案.Redis中的做法,==是直接尽可能的获取到给定区间的元素.==如果给定区间不合法,就会尽可能在不合法的区域中获取元素.此处对于下表的处理方式,类似与python中的列表切片.

127.0.0.1:6379> lrange key1 0 100
1) "4"
2) "3"
3) "2"
4) "1"

比如我们给出的范围是0~100,在这个区间内只有4321,那么Redis也只能获取4321这4个元素.

  • lpushx
    lpushx key element [element...]
    在指定的list的左边插入元素,这个指令和lpush最大的区别就是,如果这个key不存在的时候,不会自动创建key,只可以在已经存在的key的list中头插元素.
127.0.0.1:6379> lpushx key1 4 3 2 1
(integer) 8
127.0.0.1:6379> lrange key1 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "4"
6) "3"
7) "2"
8) "1"
127.0.0.1:6379> lpushx key2 4 3 2 1
(integer) 0
127.0.0.1:6379> get key2
(nil)

我们从上面的代码中可以看出,如果key不存在的时候,会返回0,而且不会主动创建key.

  • rpush
    rpush key element [element...]
    在list的右边插入指定的元素(这里的r就是right的缩写),可以一次插入多个元素,也可以一次插入一个元素.如果key不存在,创建列表,如果已经创建了key,key对应的value必须是列表类型,否则报错.
127.0.0.1:6379> rpush key 1 2 3 4 
(integer) 4
127.0.0.1:6379> lrange key 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
  • rpushx
    在指定的list的右边插入元素,这个指令和rpush最大的区别就是,如果这个key不存在的时候,不会自动创建key,只可以在已经存在的key的list中头插元素.
127.0.0.1:6379> rpushx key3 1 2 3 4
(integer) 0
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> rpushx key 1 2 3 4
(integer) 8
127.0.0.1:6379> lrange key 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "1"
6) "2"
7) "3"
8) "4"
  • lpop
    lpop key
    从list的最左边取出元素,即头删.
127.0.0.1:6379> lpop key
"1"
127.0.0.1:6379> lpop key
"2"
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "4"
3) "1"
4) "2"
5) "3"
6) "4"
  • rpop
    从list的右边取出元素,即尾删
127.0.0.1:6379> rpop key
"4"
127.0.0.1:6379> rpop key
"3"
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "4"
3) "1"
4) "2"

在Redis5的版本中,没有设置count参数,即一次可以pop元素的个数,但是从6.2开始,新增了一个count参数,可以指定pop元素的个数.比如 rpop key [count].

Redis中的list相当于一个双端队列,从两头插入/删除元素都非常高效,搭配使用rpush和lpop就相当于队列,搭配使用rpush和rpop就相当于栈.

  • lindex
    lindex key index
    获取指定位置的元素.如果下标是非法的,返回的就是nil
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "4"
3) "1"
4) "2"
127.0.0.1:6379> lindex key 2
"1"
127.0.0.1:6379> lindex key 100
(nil)
  • linsert
    linsert key <before|after> pivot element
    在list中指定元素的位置插入指定的元素.可以在指定元素的左边插入,也可以在指定元素的右边插入.在查找list中指定元素的时候,如果在list中找到了多个基准值,值插入第一个.返回值是插入之后得到的心得list长度.
127.0.0.1:6379> rpush key 4 4 
(integer) 6
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "4"
3) "1"
4) "2"
5) "4"
6) "4"
127.0.0.1:6379> linsert key before 4 22
(integer) 7
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "4"
4) "1"
5) "2"
6) "4"
7) "4"
127.0.0.1:6379> linsert key after 4 22
(integer) 8
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "4"
4) "22"
5) "1"
6) "2"
7) "4"
8) "4"
  • llen
    llen key
    获取list的长度
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "4"
4) "22"
5) "1"
6) "2"
7) "4"
8) "4"
127.0.0.1:6379> llen key
(integer) 8
  • lrem
    lrem key count element
    删除list中指定的值,其中count是要删除的个数,element是要删除的元素.
    其中,count > 0的时候,从list的左边开始删除指定个数的元素,count = 0的时候,将指定的元素全部删除.当count < 0的时候,从list的右边开始删除指定个数的元素.
127.0.0.1:6379> lrem key 1 4
(integer) 1
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "22"
4) "1"
5) "2"
6) "4"
7) "4"
127.0.0.1:6379> lrem key -2 4
(integer) 2
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "22"
4) "1"
5) "2"
127.0.0.1:6379> lpush key 4 4 4
(integer) 8
127.0.0.1:6379> lrem key 0 4
(integer) 3
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "22"
4) "1"
5) "2"
  • ltrim
    itrim key start stop
    保留指定区间(闭区间)之内的元素,其他元素全部删除.
127.0.0.1:6379> lrange key 0 -1
1) "3"
2) "22"
3) "22"
4) "1"
5) "2"
127.0.0.1:6379> ltrim key 1 3
OK
127.0.0.1:6379> lrange key 0 -1
1) "22"
2) "22"
3) "1"
  • lset
    lset key index element
    将指定下标的元素修改为指定元素.
    注意: 这里不像lrange那样下标可以越界,这里的下标如果越界了,会报错.
127.0.0.1:6379> lrange key 0 -1
1) "22"
2) "22"
3) "1"
127.0.0.1:6379> lset key 1 44
OK
127.0.0.1:6379> lset key 5 55
(error) ERR index out of range
127.0.0.1:6379> lrange key 0 -1
1) "22"
2) "44"
3) "1"

4.4 阻塞版本指令

4.4.1 特点概述

  • 阻塞指的就是: 当前线程的代码不会继续执行,会在满足一定条件之后唤醒.但是只有当前客户端表现为阻塞状态,不会影响到其他客户端的Redis指令的执行.
  • 如果list中存在元素,blpop,brpop的效果和不加b(这里的b就是block的缩写)完全一样.如果list不存在元素,blpop,brpop就会阻塞等待,一直阻塞到list不为空或者是超时为止.

说到这里,我们可以回忆一下我们java中的BlockingQueue.java中的阻塞队列主要用于生产者消费者模型.它一方面主要用于生产者和消费者的削峰填谷,另一方面用于解除生产者和消费者的强耦合.

  • Redis这里的list与阻塞相关的指令也是一样.只是这里的线程安全是通过单线程来实现的,阻塞只支持"队列为空"的情况,不支持"队列为满"的情况,和阻塞相关的指令只有pop相关的操作.
  • 这里的阻塞等待也不是无休止的阻塞等待,我们可以自定义阻塞等待的时间.
  • 命令中如果设置了多个键,会从头到尾遍历所有的键,一旦有个一键对应的列表中可以弹出元素,命令立即返回.也就是blpop和brpop都可以同时尝试获取多个key的列表元素,多个key对应多个list,哪个list中有元素,就返回哪个元素.
  • 如果有多个客户端同时对一个键执行pop,则最先执行命令的客户端会得到弹出的元素.
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

4.4.2 指令

  • blpop
    blpop key [key...] timeout
    指定要弹出元素的list对应的key,这个key可以有多个,可以只有一个,命令中如果设置了多个键,会从头到尾遍历所有的键,一旦有个一键对应的列表中可以弹出元素,命令立即返回.可以指定阻塞等待的时间,如果在等待时间之内list中新增了元素,则立即返回.如果超时,则返回nil.如果获取到元素,返回的值是一个二元组,分别是得到返回值的key(也就是告诉我们当前数据来自于哪个key)和list中弹出的值(数据是什么).
127.0.0.1:6379> lpush key2 100
(integer) 1
127.0.0.1:6379> blpop key2 5
1) "key2"
2) "100"//有元素立即弹出,无需等待
127.0.0.1:6379> lpush key3 100
(integer) 1
127.0.0.1:6379> lpush key4 100
(integer) 1
127.0.0.1:6379> blpop key2 key3 key4 5
1) "key3"//弹出第一个获取到元素的key中的元素
2) "100"
127.0.0.1:6379> blpop key3 5
(nil)
(5.04s)//如果指定的key中没有元素,阻塞等待,最后返回nil
//客户端1
127.0.0.1:6379> blpop key3 100
1) "key3"
2) "1"
(33.40s)
//客户端2
127.0.0.1:6379> lpush key3 1
(integer) 1//在一个客户端阻塞的期间,不影响其他客户端的命令执行
//在等待期间,在客户端2中对key3插入元素,只要key3中有了元素,客户端1中阻塞等待的命令就会立即返回
  • brpop
    和blpop是同样的道理,只不过是尾删.

4.5 指令小结

在这里插入图片描述

5. list内部编码方式

在旧版本的Redis中,Redis中的编码方式分为了两种,一种是ziplist,一种是linkedlist.

  • ziplist
    这个ziplist的编码方式和hash中的ziplist的编码方式的限制条件是一样的,在list中的元素较少的时候(默认512个),或者是list中每个元素很短(默认不超过64字节).按照这种编码方式可以节省一定的空间,但是缺点就是读取的时候是比较慢的.
  • linkedlist
    在list内部的元素个数和每个元素的字节长度超过阈值的时候,就会转换为linkedlist.

但是在新版本中的Redis中,list的编码方式并不是采用这样的方式,它采用的是quicklist的方式.
关于quicklist,它相当于结合了ziplist和linkedlist两者的优点.整体还是一个链表,但是每个链表的结点是一个压缩链表.每个压缩列表都不是很大,这些研所列表是通过链式结构连接起来的.
在这里插入图片描述
在之前配置文件中的list-max-ziplist-entries和list-max-ziplist-value这两个属性由于list底层编码方式的改变,现在都不再使用了.

6. list的应用场景

  • 用list作为想数组这样的结构来存储数据
    假如我们有这样两种数据,一种是班级,一种是学生.
    在Redis中,我们存储学生信息的时候使用的是hash的方式来存储的,中存储的是学生的id,value中的hash中存储的是学生的各种不同的信息.存储班级信息的时候,key中存储的是class的id,value中存储的是该班级中有多少人.但是我们想要存储class中有哪些学生,我们就需要list存储,在key中存储的是class的id,在value中使用list存储的是学生的id.
    在这里插入图片描述

由于Redis只能存储键值对,并不像MySQL中使用表存储数据,并提供了丰富的查询功能,所以在Redis中如何组织数据,就要根据实际的业务场景来决定.

  • 用作消息队列
    list中的阻塞命令可以为Redis作为消息队列提供很好的支持.和java一样,Redis作为消息队列的时候,一般也是用于生产者消费者模型.
    在这里插入图片描述
    这里我们假如生产者只有一个,那么生产者就会把信息交给Redis中的列表,其中列表就是消息队列,消费者有好多个.==这里消费者在获取信息的时候,是通过轮训的方式来获取信息.==谁先执行的drpop,谁就可以先获取到信息,此消费者获取完信息之后,假如还想要使用brpop获取信息,就会到达消费者优先级的末尾.比如消费者执行的顺序是123,在1消费者执行完成之后,1消费者想要再次获取消息队列中的元素,这时候就要排到消费者优先级的末尾,也就是按照231的方式执行的.消费者2也是同样的道理.

具体说明: 买包子
假如滑稽老铁有一天想吃包子,他要去包子摊买包子,轮到他的时候,他买了2个包子,刚一出队列,一想到自己还没有给女票带早饭,又想返回头去再买一个包子,这时候滑稽老铁一定是不可以插回原来的位置的,他只能到队尾再次进行排队.
在这里插入图片描述

  • 分频道的消息队列
    我们在Redis中,可能不止一个列表在作为消息队列,可能有多个消息队列,不同的消息队列中保存的是不同主题的消息.一个消费者可以从多个频道中获取信息.每一个消息队列都和上面我们提到的消息队列的特点是一样的.这样搞成多个频道的消息队列,可以在某种主题的数据发生问题的时候,不会对其他的频道造成影响.
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

eureka.client.service-url.defaultZone的坑

错误的配置 eureka: client: service-url: default-zone: http://192.168.100.10:8080/eureka正确的配置 eureka: client: service-url: defaultZone: http://192.168.100.10:8080/eureka根据错误日志堆栈打断电调试 出现两个key&#xff0c;也就是defaultZone不支持snake-c…

【PCB工艺】如何实现PCB板层间的互连

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言①、什么是通孔②、通孔是怎样产生的③、通孔种类④、盘中孔⑤、设计建议 前言 送给大学毕业后找不到奋斗方向的你…

C++函数在库中的地址

本文讲述C如何直接调用动态库dll或者so中的函数。 首先我们准备一个被调用库&#xff0c;这个库里面有两个函数&#xff0c;分别是C98 与 C11 下的&#xff0c;名称是run2和run1。 被调用库 相关介绍请看之前的文章《函数指针与库之间的通信讲解》。 //dll_ex_im.h #ifndef…

OpenSSH9.8p1编译rpm包(建议收藏)

1.升级前的openssh版本 [root@ncayu8847 ~]# ssh -V OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 20172.下载软件包(离线包) openssh 源码下载地址: https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/openssl源码下载 https:/

JUC学习笔记(二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 四、共享模型之内存4.1 Java 内存模型4.2 可见性退不出的循环解决方法可见性 vs 原子性模式之 Balking1.定义2.实现 4.3 有序性原理之指令级并行1. 名词2.鱼罐头的故…

关于手机号码数理的计算和推导,获得“平替”尾号

文章背景&#xff1a;我个人比较相信命运&#xff0c;对于手机号码的吉凶或是数理颇为在乎。最近&#xff0c;我沉浸于这方面的研究中&#xff0c;并发现许多手机号码的数理核心竟出奇地一致——关键在于后四位尾号&#xff0c;而前面的数字似乎并不占据主导位置。然而&#xf…

使用 GaLore 预训练LLaMA-7B

项目代码&#xff1a; https://github.com/jiaweizzhao/galorehttps://github.com/jiaweizzhao/galore 参考博客&#xff1a; https://zhuanlan.zhihu.com/p/686686751 创建环境 基础环境配置如下&#xff1a; 操作系统: CentOS 7CPUs: 单个节点具有 1TB 内存的 Intel CP…

【C++】入门基础(下)

Hi&#xff01;很高兴见到你~ 目录 7、引用 7.3 引用的使用&#xff08;实例&#xff09; 7.4 const引用 【第一分点】 【第二分点1】 【第二分点2】 7.5 指针和引用的关系&#xff08;面试点&#xff09; 8、inline 9、nullptr Relaxing Time&#xff01; ———…

Mysql(二) - 约束, 进阶查询

目录 一.约束 1.not null 2.unique 3.default 4.primary key 5. foreign key 6.check 7. 综合使用 二.进阶查询 1.新增(插入查询的结果) 2.聚合查询 a.聚合函数 b.使用 3.分组查询 4.联合查询 a.内连接 b.外连接 c.自连接 d.子查询 5.合并查询 三.总结 一…

基于SpringBoot的招生宣传管理系统【附源码】

基于SpringBoot的招生宣传管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概述 4.2系统功能结构设计 4.3数据库设计 4.3.1数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1管理员功能介绍 5.1.1管理员登录 …

Ubuntu22.04系统安装opencv步骤简述及问题解决方法

前言 opencv是一个功能强大、开源且跨平台的计算机视觉库&#xff0c;适用于多种编程语言和操作系统&#xff0c;能够帮助开发者构建各种视觉项目。其模块众多&#xff0c;提供了诸多功能&#xff0c;能够进行图像处理、视频处理等等。比如&#xff1a;Highgui模块提供图像用户…

Python 解析 JSON 数据

1、有如下 JSON 数据&#xff0c;存放在 data.json 文件&#xff1a; [{"id":1, "name": "小王", "gender": "male", "score": 96.8}, {"id":2, "name": "小婷", "gender&qu…

Python 课程12-Python 自动化应用

前言 Python 自动化应用 可以帮助开发者节省时间和精力&#xff0c;将重复性、手动操作变为自动化脚本。例如&#xff0c;Python 可以用于自动化处理文件、邮件、生成报表&#xff0c;甚至可以控制浏览器执行复杂的网页操作任务。借助 Python 的强大库和工具&#xff0c;可以轻…

python学习——对无人机影像有RGB转换到HSV

问题描述 最近需要对无人机影像中绿色植被信息进行提取&#xff0c;查看相关论文&#xff0c;发现用的比较多的就是HSV色彩转换方法&#xff0c;动手实践一下。 解决思路 #mermaid-svg-5ejGodIusPv6zFVS {font-family:"trebuchet ms",verdana,arial,sans-serif;fon…

浪潮信息首推3秒智能控温!告别服务器开机噪音

在当前的数据中心运维实践中&#xff0c;运维人员在部署服务器时常被“飞机起飞”般的开机噪音所困扰。服务器刚刚接通电源&#xff0c;其内部元件尚处于预热待命状态&#xff0c;而风扇却已全速运转&#xff0c;这不仅加剧了噪音污染&#xff0c;还拖慢了启动速度&#xff0c;…

了解华为云容器引擎(Cloud Container Engine)

1.什么是云容器引擎&#xff1f; 云容器引擎&#xff08;Cloud Container Engine&#xff0c;简称CCE&#xff09;提供高度可扩展的、高性能的企业级Kubernetes集群。借助云容器引擎&#xff0c;您可以在华为云上轻松部署、管理和扩展容器化应用程序。云容器引擎是一个企业级的…

【Python机器学习】循环神经网络(RNN)——超参数

几乎所有模型都可以根据数据和样本进行调整&#xff0c;它们都有各自的优势和相应的利弊权衡方式。寻找最优超参数集通常是一个棘手的问题&#xff0c;但是人类的直觉和经验可以为我们提供解决问题的方法。比如之前的例子&#xff1a; #设置任意输入序列的最大长度 maxlen100 …

鸿蒙 ArkUI组件二

ArkUI组件&#xff08;续&#xff09; 文本组件 在HarmonyOS中&#xff0c;Text/Span组件是文本控件中的一个关键部分。Text控件可以用来显示文本内容&#xff0c;而Span只能作为Text组件的子组件显示文本内容。 Text/Span组件的用法非常简单和直观。我们可以通过Text组件来显…

多模态大语言模型综述(中)-算法实用指南

本文是Multimodal Large Language Models: A Survey的译文之算法实用指南部分。 上&#xff1a;摘要、概念与技术要点实用指南中&#xff1a;算法实用指南(本文)下: 任务的实用指南(应用)、挑战等 原始信息 标题: Multimodal Large Language Models: A Survey译文: 多模态大…

拓扑排序算法

拓扑排序算法 上图意思为在我想要完成C7这件事之前我必须先完成事件C1&#xff0c;在完成C5这件事之前我必须先完成事件C6和C3.由图可以提看出拓扑序列是不唯一的。 有向图拓扑排序算法基本步骤&#xff1a; 1.从图中选择一一个入入度为0的顶点, 输出该顶点; 2.从图中删除该…