redis类型解析汇总

redis类型解析汇总

  • 介绍
  • 数据类型简介
    • 主要数据类型:
    • 衍生类型:
  • 字符串(String)
    • 底层设计原理
    • 图例
    • 设计优势
    • 字符串使用方法
      • 设置字符串值
      • 获取字符串值
      • 获取和设置部分字符串
      • 获取字符串长度
      • 追加字符串
      • 设置新值并返回旧值
      • 递增/递减
      • 同时设置多个键值对
      • 同时获取多个键的值
      • 设置字符串值并带有过期时间
      • 自增字符串值为浮点数
  • 哈希(Hash)
    • 底层设计原理
      • 哈希表
      • 哈希冲突解决方法
    • 图例
    • 哈希使用方法
      • 设置指定key
      • 获取指定key
      • 删除指定key
      • 获取指定key字段数量
      • 获取指定key中所有字段
      • 获取指定key对应所有值
      • 获取指定key对应所有字段和值
      • 若field不存在时设置
      • 批量设置
      • 对指定key中指定字段值增加数值(int值)
      • 字段判空
      • 迭代指定key
      • 获取指定key指定字段值长度
      • 批量返回指定key值的字段值
      • 对指定key中指定字段值增加数值(float值)
      • 若field不存在时设置(存在NX/XX参数时)
      • 批量移除字段的TTL
  • 列表(List)
    • 底层设计原理
    • 图例
    • 列表使用方法
      • 列表头插
      • 列表尾插
      • 移除头部元素
      • 移除尾部元素
      • 获取指定索引元素
      • 获取列表长度
      • 获取指定范围元素
      • 移除指定数量元素
      • 设置指定索引元素
      • 裁剪指定范围元素
      • 阻塞模式头移
      • 阻塞模式尾移
      • 指定元素位置插入元素
  • 集合(Set)
    • 底层设计原理
    • 图例
    • 集合使用方法
      • 添加成员
      • 移除成员
      • 获取所有成员
      • 检查是否为集合成员
      • 获取集合元素数量
      • 获取移除的成员
      • 获取指定数量成员
      • 转移集合成员
      • 返回集合交集
      • 获取集合并集
      • 获取集合差集
      • 计算并保存集合交集
      • 计算并保存集合并集
      • 计算并保存集合差集
  • 有序集合(Sorted Set)
    • 底层设计原理
      • 跳跃表(Skip List)
      • 哈希表(Hash Table)
    • 图例
    • 有序集合使用方法
      • 添加成员
      • 删除成员
      • 查询成员个数
      • 查询成员的分数
      • 按排名查询成员
      • 按分数范围查询成员
      • 按分数范围删除成员
      • 增加成员的分数
      • 查看排名范围内的成员和分数
      • 逆序按排名查询成员
      • 逆序按分数范围查询成员
      • 删除排名范围内的成员
      • 获取有序集合中在字典范围内成员数量
      • 按字典范围查询成员
      • 按字典范围删除成员
      • 求集合的并集
      • 求集合的交集
      • 求集合的并集和
  • 位图(BitMap)
    • 底层设计原理
    • 应用场景
    • 图例
    • 位图使用方法
      • 设置位图中的位
      • 获取位图中的位
      • 获取位图的长度
      • 求位图之间的逻辑操作
      • 设置位图的长度
      • 获取位图指定范围内的所有位
      • 设置位图指定范围内的所有位
      • 获取位图指定范围内的所有位,并对它们进行位运算
  • 超级日志结构(HyperLogLog)
    • 底层设计原理
    • 应用场景
    • 图例
    • HyperLogLog使用方法
      • 添加元素到HyperLogLog
      • 获取HyperLogLog的基数估计
      • 合并多个HyperLogLog
    • 其他说明
    • 注意事项
  • 地理位置(GeoSpatial)
    • 底层设计原理
    • 应用场景
    • 图例
    • GeoSpatial使用方法
      • 添加地理位置及其经纬度信息
      • 计算两个地理位置之间的距离
      • 获取地理位置的Geohash值
      • 获取地理位置的经纬度信息
      • 根据指定地理位置查询范围内的其他地理位置
      • 根据指定的地理位置成员查询范围内的其他地理位置
      • 从节点上执行地理位置查询
      • 统计给定范围内的地理位置数量
      • 通过复杂的过滤器查询符合条件的地理位置
      • 执行GEOSEARCH查询并将结果存储到另一个GeoSpatial结构中
  • 流(Stream)
    • 底层设计原理
    • 应用场景
    • 图例
    • Stream使用方法
      • 创建Stream
      • 读取Stream
      • 消费者组管理
      • 获取Stream信息
      • 删除Stream中的条目
      • 使用示例
  • redis特性和优势
  • redis使用场景总结

介绍

Redis(Remote Dictionary Server 远程字典服务器)是一个开源的内存数据库,它可以作为缓存、数据库和消息中间件使用

数据类型简介

主要数据类型:

1. 字符串(String):

  • Redis 最基本的数据类型,可以存储文本、整数或者二进制数据。
  • 支持基本的字符串操作,如设置、获取、追加等。

2. 哈希(Hash):

  • 类似于关联数组,适合存储对象。
  • 每个哈希可以存储多个字段和对应的值。

3. 列表(List):

  • 链表结构,支持从两端压入和弹出元素,适合存储有序的元素集合。
  • 可以用于实现队列、栈等数据结构。

4. 集合(Set):

  • 无序且唯一的元素集合,支持集合间的基本操作(交集、并集等)。
  • 可以用于存储不重复的元素集合,如用户标签、好友列表等。

5. 有序集合(Sorted Set):

  • 类似于集合,但每个元素关联一个分数,支持按分数排序。
  • 可以用于实现排行榜、范围查询等功能。

衍生类型:

1. 位图(BitMap):

  • Redis 提供了位操作命令,可以将字符串作为位数组来使用,支持位的设置、获取、计数等操作。
  • 适用于存储布尔型数据或者进行一些位运算操作。

2. 超级日志结构(HyperLogLog):

  • 用于进行基数统计,估算集合中不重复元素的数量。
  • 提供了一系列的命令用于添加元素、统计基数、合并 HyperLogLog 等。

3. 地理位置(GeoSpatial):

  • 通过经纬度坐标来存储地理位置信息,并支持查询两点之间的距离、查找附近的位置等功能。
  • 适用于实现地理位置服务、附近搜索等功能。

4. 流(Stream):

  • Redis 5.0 引入的新数据类型,类似于日志结构,支持添加、读取、消费消息等操作。
  • 可以用于实现消息队列、事件日志等应用场景。

字符串(String)

底层设计原理

在 Redis 中,字符串的底层结构是简单动态字符串(Simple Dynamic String,SDS)。SDS 是 Redis自己实现的一种字符串表示方式,相比于传统的 C 语言字符串,它具有以下优势,从而使得 Redis 中字符串操作更加高效

图例

// TODO 待补充

设计优势

1. 动态扩展:SDS 可以根据需要动态扩展字符串的长度,而不需要像 C 字符串那样每次都重新分配内存和拷贝数据,这样可以避免频繁的内存分配和释放,提高了性能。
2. 减少缓冲区溢出:SDS 在字符串末尾会额外存储一个字节的空间,用于存放空字符(‘\0’),这样即使字符串长度增加,也不会发生缓冲区溢出,提高了安全性。
3. 快速获取长度:SDS 结构中记录了字符串的长度信息,因此获取字符串长度的操作是 O(1) 的时间复杂度,而不像 C 字符串需要遍历整个字符串。
4. 二进制安全:SDS 可以存储任意二进制数据,而不仅限于文本数据,这使得 Redis 的字符串类型可以应对更多的应用场景,例如存储图片、序列化对象等。
5. 支持部分修改:SDS 支持在 O(1) 的时间复杂度内进行部分字符串的修改,比如替换某个位置的字符,这在某些应用场景下非常高效。

字符串使用方法

设置字符串值

  • SET key value [EX seconds] [PX milliseconds] [NX|XX]
    • 将字符串键 key 的值设置为 value。可以设置过期时间 EX seconds 或 PX milliseconds。
    • NX:仅在键不存在时设置值。
    • XX:仅在键已存在时设置值。
SET mykey "Hello"
SET mycounter 100 EX 3600 NX

获取字符串值

  • GET key
    • 获取键 key 的值。
GET mykey

获取和设置部分字符串

  • GETRANGE key start end

    • 返回键 key 中字符串值的子字符串,从 start 到 end 的位置(包括两端)。
  • SETRANGE key offset value

    • 用指定的 value 替换键 key 中字符串的部分内容,从 offset 开始。
GETRANGE mykey 0 3  # 返回 "Hell"
SETRANGE mykey 6 "Redis"  # 将 mykey 中索引为 6 开始的部分替换为 "Redis"

获取字符串长度

  • STRLEN key
    • 返回键 key 中字符串值的长度。
STRLEN mykey

追加字符串

  • APPEND key value
    • 将 value 追加到键 key 当前值的末尾,并返回新的字符串长度。
APPEND mykey ", welcome to Redis!"

设置新值并返回旧值

  • GETSET key value
    • 将键 key 的值设置为 value,并返回旧值。
GETSET mykey "New Value"

递增/递减

  • INCR key
    • 将键 key 中存储的数字值增加 1。
  • DECR key
    • 将键 key 中存储的数字值减少 1。
  • INCRBY key increment
    • 将键 key 中存储的数字值增加指定的 increment。
  • DECRBY key decrement
    • 将键 key 中存储的数字值减少指定的 decrement。
INCR mycounter
DECR mycounter
INCRBY mycounter 10
DECRBY mycounter 5

假设我们有一个键 mykey,它最初存储的值是 “Hello”。

同时设置多个键值对

  • MSET key1 value1 [key2 value2 …]
    • 同时设置多个键值对。
MSET key1 "value1" key2 "value2"

同时获取多个键的值

  • MGET key1 [key2 …]
    • 同时获取多个键的值。
MGET key1 key2

设置字符串值并带有过期时间

  • SETEX key seconds value
    • 设置键 key 的值为 value,并设置过期时间为 seconds 秒。
SETEX mykey 60 "Hello"  # 设置 mykey 的值为 "Hello",并设置过期时间为 60

自增字符串值为浮点数

  • INCRBYFLOAT key increment
    • 将键 key 中存储的数字值增加指定的浮点数 increment。
SET myfloat 10.5     
INCRBYFLOAT myfloat 0.1  # 将 myfloat 的值增加 0.1     

哈希(Hash)

底层设计原理

其实现主要包括两个部分:哈希表(Hash table)和哈希冲突解决方法(Collision resolution)

哈希表

Redis 中的哈希表实际上是一个数组(Array),数组的每个元素称为一个哈希桶(bucket)。每个桶中可以存储多个哈希节点(Hash node),每个节点包含一个键值对。

  • 数组大小和桶的数量: Redis 在创建哈希表时会预先分配一定大小的数组,数组的每个元素是一个桶。数组的大小会动态调整,以适应哈希表中存储的键值对数量变化。
  • 桶的选择: Redis 使用键的哈希值通过取模运算来决定存储在哪个桶中,例如 hash(key) % buckets_count。这样可以快速定位到存储和检索数据的位置

哈希冲突解决方法

当两个不同的键通过哈希函数计算得到相同的索引位置时,就会发生哈希冲突。Redis 使用链地址法(Separate chaining)来解决哈希冲突:

  • 链表存储: 每个桶中存储一个链表或者其他类似的数据结构(例如跳表),用于存放哈希冲突的键值对。这样即使发生冲突,也能通过遍历链表或者其他数据结构找到正确的键值对

图例

// TODO 待补充

哈希使用方法

设置指定key

  1. HSET key field value
  • 设置哈希 key 中的字段 field 的值为 value。
HSET user:1001 username "alice"

获取指定key

  1. HGET key field
  • 获取哈希 key 中字段 field 的值。
HGET user:1001 username

删除指定key

  1. HDEL key field [field …]
  • 删除哈希 key 中的一个或多个字段。
HDEL user:1001 username

获取指定key字段数量

  1. HLEN key
  • 返回哈希 key 中字段的数量。
HLEN user:1001

获取指定key中所有字段

  1. HKEYS key
  • 返回哈希 key 中所有的字段。
HKEYS user:1001

获取指定key对应所有值

  1. HVALS key
  • 返回哈希 key 中所有的值。
HVALS user:1001

获取指定key对应所有字段和值

  1. HGETALL key
  • 返回哈希 key 中的所有字段和值。
HGETALL user:1001

假设有一个用户信息存储在哈希中:

127.0.0.1:6379> HSET user:1001 username "alice"
(integer) 1
127.0.0.1:6379> HSET user:1001 email "alice@example.com"
(integer) 1
127.0.0.1:6379> HSET user:1001 age "30"
(integer) 1

可以使用以上方法来操作这个哈希数据结构:

127.0.0.1:6379> HGET user:1001 username
"alice"
127.0.0.1:6379> HGETALL user:1001
1) "username"
2) "alice"
3) "email"
4) "alice@example.com"
5) "age"
6) "30"
127.0.0.1:6379> HDEL user:1001 age
(integer) 1
127.0.0.1:6379> HLEN user:1001
(integer) 2
127.0.0.1:6379> HKEYS user:1001
1) "username"
2) "email"
127.0.0.1:6379> HVALS user:1001
1) "alice"
2) "alice@example.com"

若field不存在时设置

  1. HSETNX key field value
  • 当字段 field 不存在时,设置哈希 key 中的字段 field 的值为 value。
HSETNX user:1001 username "alice"

批量设置

  1. HMSET key field value [field value …]
  • 同时设置多个字段的值。
HMSET user:1001 username "alice" email "alice@example.com" age "30"

对指定key中指定字段值增加数值(int值)

  1. HINCRBY key field increment
  • 将哈希 key 中的字段 field 的值增加 increment。
HINCRBY user:1001 age 1

字段判空

  1. HEXISTS key field
  • 判断哈希 key 中是否存在字段 field。
HEXISTS user:1001 username

迭代指定key

  1. HSCAN key cursor [MATCH pattern] [COUNT count]
  • 迭代哈希 key 中的键值对。
HSCAN user:1001 0

获取指定key指定字段值长度

  1. HSTRLEN key field
  • 返回哈希 key 中字段 field 的值的长度。
HSTRLEN user:1001 username

批量返回指定key值的字段值

  1. HMGET key field [field …]
  • 返回哈希 key 中一个或多个字段的值。
HMGET user:1001 username email

对指定key中指定字段值增加数值(float值)

  1. HINCRBYFLOAT key field increment
  • 将哈希 key 中的字段 field 的值增加 increment(浮点数)。
HINCRBYFLOAT user:1001 score 0.5

若field不存在时设置(存在NX/XX参数时)

  1. HSET key field value [NX|XX]
  • 当指定 NX 或 XX 参数时,只在字段不存在或者已存在时才设置值。
HSET user:1001 username "alice" NX

批量移除字段的TTL

  1. HPERSIST key field [field …]
  • 移除哈希 key 中一个或多个字段的生存时间(TTL)。
HPERSIST user:1001 username

列表(List)

底层设计原理

List数据结构是一个双向链表(双端链表)实现的,支持在列表的两端进行快速的插入(push)和删除(pop)操作。这种实现保证了在头部和尾部进行插入和删除的时间复杂度都是O(1)

图例

// TODO

列表使用方法

列表头插

  1. LPUSH key value [value …]
  • 将一个或多个值插入到列表头部。
LPUSH mylist "world"
LPUSH mylist "hello"

列表尾插

  1. RPUSH key value [value …]
  • 将一个或多个值插入到列表尾部。
RPUSH mylist "foo"
RPUSH mylist "bar"

移除头部元素

  1. LPOP key
  • 移除并返回列表头部的元素。
LPOP mylist

移除尾部元素

  1. RPOP key
  • 移除并返回列表尾部的元素。
RPOP mylist

获取指定索引元素

  1. LINDEX key index
  • 返回列表中指定索引位置的元素。
LINDEX mylist 0

获取列表长度

  1. LLEN key
  • 返回列表的长度。
LLEN mylist

获取指定范围元素

  1. LRANGE key start stop
  • 返回列表中指定范围内的元素。
LRANGE mylist 0 2

移除指定数量元素

  1. LREM key count value
  • 移除列表中指定数量的元素。
LREM mylist 2 "hello"

设置指定索引元素

  1. LSET key index value
  • 设置列表中指定索引位置的元素值。
LSET mylist 1 "new_value"

裁剪指定范围元素

  1. LTRIM key start stop
  • 对列表进行裁剪,保留指定范围内的元素。
LTRIM mylist 0 2

阻塞模式头移

  1. BLPOP key [key …] timeout
  • 从列表头部弹出元素,如果列表为空则阻塞并等待元素的到来。
BLPOP mylist 10

阻塞模式尾移

  1. BRPOP key [key …] timeout
  • 从列表尾部弹出元素,如果列表为空则阻塞并等待元素的到来。
BRPOP mylist 10

指定元素位置插入元素

  1. LINSERT key BEFORE|AFTER pivot value
  • 在列表中指定元素 pivot 的前面或后面插入元素 value。
LINSERT mylist BEFORE "world" "new_value"

集合(Set)

底层设计原理

  • 每个集合成员(如 member1, member2, member3)被映射到哈希表的一个桶中。
  • 桶内的数据结构可以是链表或其他形式,用于处理哈希冲突,但每个键值对的键都是成员的值,值则是一个常量(NULL)。
  • Set 数据结构非常适合用于存储唯一值的场景,例如标签、用户 ID 等,并且能够通过交集、并集、差集等操作,支持更复杂的数据处理需求

图例

// TODO

集合使用方法

添加成员

  1. SADD key member [member …]
  • 向集合添加一个或多个成员。
SADD myset "member1"
SADD myset "member2"

移除成员

  1. SREM key member [member …]
  • 从集合中移除一个或多个成员。
SREM myset "member1"

获取所有成员

  1. SMEMBERS key
  • 返回集合中的所有成员。
SMEMBERS myset

检查是否为集合成员

  1. SISMEMBER key member
  • 检查 member 是否是集合 key 的成员。
SISMEMBER myset "member1"

获取集合元素数量

  1. SCARD key
  • 返回集合的基数(集合中元素的数量)。
SCARD myset

获取移除的成员

  1. SPOP key [count]
  • 移除并返回集合中的一个或多个随机元素。
SPOP myset

获取指定数量成员

  1. SRANDMEMBER key [count]
  • 返回集合中一个或多个随机元素(不移除元素)。
SRANDMEMBER myset 2

转移集合成员

  1. SMOVE source destination member
  • 将 member 从 source 集合移动到 destination 集合。
SMOVE myset myotherset "member1"

返回集合交集

  1. SINTER key [key …]
  • 返回多个集合的交集。
SINTER myset myotherset

获取集合并集

  1. SUNION key [key …]
  • 返回多个集合的并集。
SUNION myset myotherset

获取集合差集

  1. SDIFF key [key …]
  • 返回多个集合的差集。
SDIFF myset myotherset

计算并保存集合交集

  1. SINTERSTORE destination key [key …]
  • 计算多个集合的交集,并将结果存储到新的集合中。
SINTERSTORE newset myset1 myset2

计算并保存集合并集

  1. SUNIONSTORE destination key [key …]
  • 计算多个集合的并集,并将结果存储到新的集合中。
SUNIONSTORE newset myset1 myset2

计算并保存集合差集

  1. SDIFFSTORE destination key [key …]
  • 计算多个集合的差集,并将结果存储到新的集合中。
SDIFFSTORE newset myset1 myset2

有序集合(Sorted Set)

底层设计原理

有序集合是一种特殊的数据结构,它类似于集合(Set),但每个成员都关联了一个分数(score),该分数用于对成员进行排序。有序集合的底层设计原理主要涉及两个核心点:跳跃表(SkipList)和哈希表(Hash Table)。

跳跃表(Skip List)

跳跃表是一种数据结构,用于在有序元素的集合中快速查找某个元素。它通过层级结构来实现快速查找,每一层都是元素的一个有序子集,最底层包含所有元素。在跳跃表中,每个节点包含一个指向下一个节点的指针,以及一个指向同一层下一个节点的指针。
在Redis中,有序集合的底层实现就是通过跳跃表来实现的。每个成员在跳跃表中都是一个节点,节点中包含了成员本身的值和分数,以及指向下一个节点和下一层节点的指针。通过跳跃表,Redis可以实现有序集合的快速查找和排序功能。

哈希表(Hash Table)

除了跳跃表,有序集合在底层还使用了哈希表来存储成员和分数之间的映射关系。哈希表是一种以键值对形式存储数据的数据结构,可以快速查找和访问数据。
在Redis中,有序集合使用哈希表来存储成员和分数之间的映射关系,这样可以在跳跃表中快速定位到某个成员的节点,然后通过哈希表找到成员对应的分数。哈希表的使用使得在有序集合中查找某个成员的分数变得高效。

图例

// TODO

有序集合使用方法

添加成员

  1. ZADD key score member [score member …]
  • 将一个或多个成员及其对应的分数添加到有序集合中。
ZADD myset 1 "member1" 2 "member2"

删除成员

  1. ZREM key member [member …]
  • 从有序集合中删除一个或多个成员。
ZREM myset "member1"

查询成员个数

  1. ZCARD key
  • 获取有序集合中成员的数量。
ZCARD myset

查询成员的分数

  1. ZSCORE key member
  • 获取指定成员的分数。
ZSCORE myset "member1"

按排名查询成员

  1. ZRANK key member
  • 获取指定成员在有序集合中的排名(从0开始)。
ZRANK myset "member1"

按分数范围查询成员

  1. ZRANGE key start stop [WITHSCORES]
  • 按分数从小到大的顺序,获取指定范围内的成员。
ZRANGE myset 0 1 WITHSCORES

按分数范围删除成员

  1. ZREMRANGEBYSCORE key min max
  • 删除分数在指定范围内的成员。
ZREMRANGEBYSCORE myset 0 5

增加成员的分数

  1. ZINCRBY key increment member
  • 给指定成员的分数增加增量increment。
ZINCRBY myset 2 "member1"

查看排名范围内的成员和分数

  1. ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
  • 按分数范围获取成员及其分数,支持分页。
ZRANGEBYSCORE myset 0 10 WITHSCORES LIMIT 0 2

逆序按排名查询成员

  1. ZREVRANK key member
  • 获取指定成员在有序集合中的逆序排名(从0开始)。
ZREVRANK myset "member1"

逆序按分数范围查询成员

  1. ZREVRANGE key start stop [WITHSCORES]
  • 按分数从大到小的顺序,获取指定范围内的成员。
ZREVRANGE myset 0 1 WITHSCORES

删除排名范围内的成员

  1. ZREMRANGEBYRANK key start stop
  • 删除排名在指定范围内的成员。
ZREMRANGEBYRANK myset 0 1

获取有序集合中在字典范围内成员数量

  1. ZLEXCOUNT key min max
  • 获取有序集合中在字典范围内(字典区间使用"-“和”+"表示)的成员数量。
ZLEXCOUNT myset "-" "+"

按字典范围查询成员

  1. ZRANGEBYLEX key min max [LIMIT offset count]
  • 按字典范围获取成员。
ZRANGEBYLEX myset "-" "[m" LIMIT 0 2

按字典范围删除成员

  1. ZREMRANGEBYLEX key min max
  • 删除字典范围内的成员。
ZREMRANGEBYLEX myset "-" "[m"

求集合的并集

  1. ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
  • 计算给定有序集合的并集,并将结果存储在新的有序集合中。
ZUNIONSTORE dest 2 set1 set2 WEIGHTS 1 2

求集合的交集

  1. ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
  • 计算给定有序集合的交集,并将结果存储在新的有序集合中。
ZINTERSTORE dest 2 set1 set2

求集合的并集和

  1. ZUNION key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]
  • 计算给定有序集合的并集,并返回结果集。
ZUNION 2 set1 set2 WEIGHTS 1 2

位图(BitMap)

底层设计原理

位图是一种特殊的数据结构,它实际上是一个特定长度的字符串,字符串中的每个比特位都可以被设置或清除。这种设计使得Redis的位图非常节省内存,特别适合于需要高效存储大量布尔类型数据的场景

1. 存储结构:

  • Redis的位图是一个由字符串实现的位数组,其中每个比特位可以代表一个状态(通常是0或1)。
  • 位图的长度由用户定义,在Redis中可以使用命令 SETBIT 来设置位图的长度,如果超过当前长度,Redis会自动扩展。

2. 位操作命令:

  • Redis提供了一系列位操作的命令,包括设置位、清除位、查看位的值等,这些操作都是针对位图中的单个比特位进行的。

3. 内存优化:

  • 位图采用了非常紧凑的存储方式,每个比特位只占用1位(0或1),因此在存储大量布尔类型数据时非常节省内存。

应用场景

1. 用户在线状态:

  • 可以用一个位图来表示用户的在线状态,每个用户对应位图中的一个比特位,该位在用户在线时置为1,离线时置为0。这样可以高效地查询多个用户的在线状态。

2. 统计数据:

  • 可以用位图来记录用户的操作行为或者事件发生情况,比如记录用户每天的登录情况、签到情况等。通过位操作命令,可以快速统计和分析这些数据。

3. 布隆过滤器(Bloom Filter):

  • 布隆过滤器是一种快速判断一个元素是否在集合中的数据结构。Redis的位图可以用来实现简单的布隆过滤器,通过多个不同的哈希函数在位图中设置对应的比特位,来判断一个元素可能存在于集合中(不准确,但是高效)。

图例

// TODO

位图使用方法

设置位图中的位

  1. SETBIT key offset value
  • 将位图key中偏移量为offset的位的值设置为value(0或1)。
SETBIT mybitmap 0 1   # 将mybitmap中偏移量为0的位设置为1

获取位图中的位

  1. GETBIT key offset
  • 获取位图key中偏移量为offset的位的值。
GETBIT mybitmap 0   # 获取mybitmap中偏移量为0的位的值

获取位图的长度

  1. BITCOUNT key [start end]
  • 统计位图key中值为1的位的数量。
BITCOUNT mybitmap   # 统计mybitmap中所有值为1的位的数量

求位图之间的逻辑操作

  1. BITOP operation destkey key [key …]
  • 对一个或多个位图执行位运算,并将结果保存到destkey中。operation可以是AND、OR、XOR、NOT等。
BITOP AND destbitmap mybitmap1 mybitmap2   # 将mybitmap1和mybitmap2按位进行AND操作,并将结果存储到destbitmap中

设置位图的长度

  1. BITFIELD key [GET type offset] [SET type offset value]
  • 对位图进行更加复杂的操作,可以用于获取和设置指定偏移量的位。
BITFIELD mybitmap GET u4 0   # 获取mybitmap中偏移量为04位无符号整数
BITFIELD mybitmap SET u4 0 10   # 设置mybitmap中偏移量为04位无符号整数为10

获取位图指定范围内的所有位

  1. BITFIELD key [GET type offset] [GET type offset] …
  • 可以一次性获取多个不同偏移量的位的值。
BITFIELD mybitmap GET u4 0 GET u4 4   # 获取mybitmap中偏移量044位无符号整数

设置位图指定范围内的所有位

  1. BITFIELD key [SET type offset value] [SET type offset value] …
  • 可以一次性设置多个不同偏移量的位的值。
BITFIELD mybitmap SET u4 0 10 SET u4 4 5   # 设置mybitmap中偏移量044位无符号整数分别为105

获取位图指定范围内的所有位,并对它们进行位运算

  1. BITFIELD key [GET type offset] [GET type offset] … [operation type] [operation value]
  • 可以在获取位的同时,对获取到的位进行位运算。
BITFIELD mybitmap GET u4 0 GET u4 4 OR 5   # 获取mybitmap中偏移量044位无符号整数,并对它们进行OR运算(假设5是一个值)

超级日志结构(HyperLogLog)

HyperLogLog(简称HLL)是一种用于近似计数的数据结构,主要用于解决集合的基数估计问题。它可以在极小的内存消耗下,对大型数据集合的基数进行估计

底层设计原理

1. 基数估计:

  • HyperLogLog利用一种概率性算法来估计集合的基数(即不重复元素的数量),它的基本原理是通过对数据进行哈希映射,统计哈希值前导0的个数来估计基数。

2. 哈希函数:

  • HyperLogLog使用一种特殊的哈希函数,将元素映射到一个固定长度的二进制字符串中。这个哈希函数的设计对结果的准确性有很大影响。

3. 桶与计数器:

  • HyperLogLog将哈希值分配到多个桶中,并在每个桶中维护一个计数器,用于记录对应桶中哈希值前导0的最大长度。

4. 合并计数器:

  • 当多个HyperLogLog数据结构需要合并时,采用的是取各个桶中计数器的最大值作为合并后的结果,这样可以保证合并后的结果不会低于原始数据结构的估计值。

应用场景

HyperLogLog在Redis中的应用场景包括但不限于:
1. 独立用户数量统计:

  • 可以用于统计网站或应用的独立访客数量,以便进行用户行为分析和精准营销。

2. 基数估计:

  • 可以用于统计大数据集合的基数,例如网页访问量、搜索关键词数量等。

3. 数据去重:

  • 可以用于判断数据集合中是否存在重复元素,帮助进行数据去重处理。

图例

// TODO

HyperLogLog使用方法

添加元素到HyperLogLog

  1. PFADD key element [element …]
  • 将一个或多个元素添加到HyperLogLog中。
PFADD myloglog user1 user2 user3   # 将user1, user2, user3添加到名为myloglog的HyperLogLog中

获取HyperLogLog的基数估计

  1. PFCOUNT key [key …]
  • 获取一个或多个HyperLogLog的基数估计值。
PFCOUNT myloglog   # 获取名为myloglog的HyperLogLog的基数估计值

合并多个HyperLogLog

  1. PFMERGE destkey sourcekey [sourcekey …]
  • 将多个HyperLogLog合并为一个,并将结果存储到destkey中。
PFMERGE mergedlog myloglog1 myloglog2   # 将myloglog1和myloglog2合并为一个HyperLogLog,并将结果存储到mergedlog中

其他说明

1. HyperLogLog与其他数据结构结合使用:

  • 可以将HyperLogLog的结果与其他数据结构(如Sorted Set或Hash)结合使用,以实现更复杂的统计和分析功能。

2. 内存消耗与精度权衡:

  • HyperLogLog通过牺牲一定的精度来换取极小的内存消耗,但在实际使用中,需要根据具体的应用场景权衡精度和内存消耗。

注意事项

1. 基数估计误差:

  • HyperLogLog在进行基数估计时存在一定的误差,这个误差通常在1-2%之间,但在合适的场景下可以接受。

2. 数据存储和备份:

  • 在使用HyperLogLog时,需要考虑数据的持久化存储和备份策略,以防止数据丢失或出现不一致情况。

3. 数据更新和删除:

  • HyperLogLog结构本身不支持删除单个元素或更新元素的操作,因此需要在设计时考虑如何处理数据的更新和删除需求。

地理位置(GeoSpatial)

GeoSpatial(地理空间)数据结构是一种用于存储地理位置坐标的数据结构,主要包括地理位置的经度和纬度信息。它提供了高效的空间查询和距离计算功能,适用于需要基于地理位置进行检索和分析的应用场景

底层设计原理

1. 数据存储:

  • GeoSpatial在Redis内部使用有序集合(Sorted Set)来存储地理位置信息。有序集合的成员是地理位置的名称或标识符,而分数(score)则是地理位置的经纬度信息。

2. 地理位置编码:

  • 地理位置的经纬度信息通过一种特定的编码方式存储在有序集合中,通常使用WGS84坐标系的经度和纬度作为分数。Redis使用的是双精度浮点数来表示经纬度。

3. 空间索引:

  • Redis使用基于Geohash的空间索引来加速地理位置的查询。Geohash是一种将地理位置编码为字符串的方法,具有天然的空间特性,相近的地理位置在Geohash编码上也会比较接近。

4. 距离计算:

  • GeoSpatial支持根据地理位置计算两点之间的距离,通常使用的是欧氏距离或球面距离(例如大圆距离)来度量地理空间的距离。

5. 查询优化:

  • Redis通过有序集合的分数范围查询功能,可以高效地进行地理位置范围内的查询,比如获取某个位置周围一定距离内的其他位置。

应用场景

1. 位置推荐与附近搜索:

  • 许多应用需要根据用户当前位置或指定地点,推荐附近的商家、服务或活动。使用GeoSpatial可以高效地找到某个地理位置附近的其他位置,比如附近的餐馆、酒店或公园。

2. 地理围栏与地理提醒:

  • 通过设置地理围栏(Geofence),可以监控用户是否进入或离开某个特定的地理区域。这在位置服务和地理提醒应用中非常有用,如出租车调度、安全警报系统等。

3. 路径规划与导航:

  • 根据多个地理位置点,可以进行路径规划和导航功能。例如,从起点到终点之间的最佳路线,或者找到途径特定地点的路线。

4. 地理统计分析:

  • 分析地理位置数据可以提供有价值的商业洞察,如不同地区的用户分布、热门区域的访问频率等。这对于市场营销、城市规划或资源分配有重要意义。

5. 地理位置的实时更新与管理:

  • 对于需要实时更新的场景,如共享经济平台(共享单车、共享汽车)、实时定位服务(快递追踪、司机位置追踪)等,GeoSpatial提供了高效的数据存储和查询能力。

6. 地理位置相关的社交网络功能:

  • 在社交网络中,根据用户的地理位置推荐附近的朋友、活动或社区,增强用户交互和社交体验。

图例

// TODO

GeoSpatial使用方法

添加地理位置及其经纬度信息

  1. GEOADD key longitude latitude member [longitude latitude member …]
  • key: GeoSpatial的键名。
  • longitude, latitude: 地理位置的经度和纬度。
  • member: 地理位置的名称或标识符。
GEOADD cities 116.405285 39.904989 Beijing 121.472644 31.231706 Shanghai

计算两个地理位置之间的距离

  1. GEODIST key member1 member2 [unit]
  • key: GeoSpatial的键名。
  • member1, member2: 要计算距离的两个地理位置的名称或标识符。
  • unit (可选): 距离单位,默认为m(米),可选km(千米)、mi(英里)、ft(英尺)。
GEODIST cities Beijing Shanghai km

获取地理位置的Geohash值

  1. GEOHASH key member [member …]
  • key: GeoSpatial的键名。
  • member: 要获取Geohash的地理位置的名称或标识符。
GEOHASH cities Beijing Shanghai

获取地理位置的经纬度信息

  1. GEOPOS key member [member …]
  • key: GeoSpatial的键名。
  • member: 要获取经纬度的地理位置的名称或标识符。
GEOPOS cities Beijing

根据指定地理位置查询范围内的其他地理位置

  1. GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
  • key: GeoSpatial的键名。
  • longitude, latitude: 中心点的经度和纬度。
  • radius: 查询半径。
  • unit: 单位,可以是m(米)、km(千米)、mi(英里)、ft(英尺)。
  • 可选参数包括WITHCOORD(返回地理位置的经纬度)、WITHDIST(返回与中心点的距离)、WITHHASH(返回地理位置的Geohash)、COUNT(返回结果的数量)、ASC|DESC(结果排序)、STORE(将结果存储到另一个GeoSpatial结构)等。
GEORADIUS cities 116.405285 39.904989 1000 km WITHDIST

根据指定的地理位置成员查询范围内的其他地理位置

  1. GEORADIUSBYMEMBER key member radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
    参数与GEORADIUS类似,不同之处在于使用成员名称而不是经纬度来指定中心点。
GEORADIUSBYMEMBER cities Beijing 1000 km WITHCOORD

从节点上执行地理位置查询

  1. 只读版本的GEORADIUS与GEORADIUSBYMEMBER用于在从节点上执行地理位置查询。
    示例应用
    假设有一个名为cities的GeoSpatial结构存储了几个城市的地理位置信息:
GEOADD cities 116.405285 39.904989 Beijing
GEOADD cities 121.472644 31.231706 Shanghai

可以通过以下示例展示如何使用各种操作:

# 计算北京和上海之间的距离
GEODIST cities Beijing Shanghai km# 获取北京的Geohash值
GEOHASH cities Beijing# 获取上海的经纬度信息
GEOPOS cities Shanghai# 查找距离北京1000公里范围内的其他城市及距离
GEORADIUS cities 116.405285 39.904989 1000 km WITHDIST

统计给定范围内的地理位置数量

  1. GEOCOUNT key longitude latitude radius unit
  • key: GeoSpatial的键名。
  • longitude, latitude: 中心点的经度和纬度。
  • radius: 统计范围的半径。
  • unit: 单位,可以是m(米)、km(千米)、mi(英里)、ft(英尺)。
GEOCOUNT cities 116.405285 39.904989 1000 km

通过复杂的过滤器查询符合条件的地理位置

  1. GEOSEARCH key [FROMMEMBER member] [FROMLONLAT longitude latitude] [BYRADIUS radius unit] [BYBOX width height unit] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
  • key: GeoSpatial的键名。
  • 可选参数包括从成员开始、从经纬度开始、通过半径、通过矩形框、返回经纬度、返回距离、返回Geohash、结果数量、排序、存储等。
GEOSEARCH cities BYRADIUS 1000 km FROMMEMBER Beijing WITHDIST

执行GEOSEARCH查询并将结果存储到另一个GeoSpatial结构中

  1. GEOSEARCHSTORE destkey [key] [FROMMEMBER member] [FROMLONLAT longitude latitude] [BYRADIUS radius unit] [BYBOX width height unit] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
  • destkey: 存储结果的目标GeoSpatial的键名。
  • 其他参数与GEOSEARCH类似。
    GEOSEARCHSTORE result_cities BYRADIUS 1000 km FROMMEMBER Beijing WITHCOORD
    应用示例
    假设继续使用名为cities的GeoSpatial结构:
GEOADD cities 116.405285 39.904989 Beijing
GEOADD cities 121.472644 31.231706 Shanghai

展示如何使用这些新命令:

# 统计距离北京1000公里范围内的城市数量
GEOCOUNT cities 116.405285 39.904989 1000 km# 按半径查询距离北京1000公里范围内的城市及距离
GEOSEARCH cities BYRADIUS 1000 km FROMMEMBER Beijing WITHDIST# 执行查询并将结果存储到另一个GeoSpatial结构中
GEOSEARCHSTORE result_cities BYRADIUS 1000 km FROMMEMBER Beijing WITHCOORD

这些命令扩展了Redis GeoSpatial在处理地理位置数据时的灵活性和功能性,适用于更复杂和精细化的地理空间数据分析和查询需求。

流(Stream)

Stream是一种高性能、持久化的数据结构,主要用于处理消息队列和日志系统,Stream通过简单而强大的命令集提供了高效的消息传输和处理方式,适用于实时数据处理、日志收集、消息队列等多种应用场景。使用Redis
Stream,可以轻松地实现消息的存储、传输和消费,并通过消费者组管理确保消息的有序处理和可靠传递

底层设计原理

1. 日志结构存储:

  • Stream基于日志(log)结构存储数据。每个Stream内部实际上是一个由多个条目(entry)组成的有序日志,每个条目都有唯一的ID,称为条目ID。

2. 条目ID生成:

  • 每个新添加到Stream的条目都会自动生成一个唯一的全局递增的ID。这个ID包含了一个64位的毫秒时间戳和一个序列号,确保了每个条目在Stream内的顺序和全局唯一性。

3. 内存结构与持久化:

  • Stream的条目可以部分保存在内存中,以保证高性能的写入和读取操作。Redis会根据配置的策略将部分或全部Stream数据持久化到磁盘上。

4. 消费者组:

  • Stream支持消费者组(consumer group),这是一种消费Stream消息的方式。每个消费者组可以有多个消费者,消费者可以独立或并行地处理消息,而无需担心重复消费或消息丢失。

5. 消费位置管理:

  • 每个消费者组中的消费者会记录自己消费的位置(offset),这个位置信息存储在Redis中。消费者组内的消费者可以通过ACK机制告知Redis已经处理完特定的消息,Redis根据ACK来更新消费位置,以确保消息不会被重复消费。

应用场景

1. 消息队列:

  • Stream可以作为高性能的消息队列使用,特别是在需要持久化、顺序保证和可靠传输的场景中,比如任务队列、实时通知等。

2. 日志系统:

  • 由于Stream内部是有序的日志结构,并且支持消费者组和持久化存储,因此非常适合作为日志收集和处理系统的基础。可以用于实时日志分析、事件溯源等场景。

3. 实时数据处理:

  • Stream的特性使其非常适合处理实时生成的数据流,比如实时监控、数据管道、实时分析等应用。

4. 消息发布订阅:

  • Stream可以替代传统的发布订阅(Pub/Sub)模式,提供更多的持久化和顺序保证。这对于需要持久订阅历史消息的应用非常有用。

5. 事件驱动架构:

  • 在微服务架构或事件驱动架构中,Stream可以作为事件消息的主要传输和存储方式,支持各种事件驱动的应用场景。

图例

// TODO

Stream使用方法

创建Stream

使用 XADD 命令向Stream中添加新条目:

  1. XADD mystream MAXLEN ~100 * field1 value1 field2 value2 …
  • mystream: Stream 的键名。
  • MAXLEN ~100: 可选参数,设置Stream的最大长度(条目数)。~ 表示不精确,即允许一定程度的超出。
  • *: 自动分配一个唯一的ID。
  • field1 value1 field2 value2 …: 条目的字段和值。
XADD mystream * sensor_id 1001 temperature 37.5 timestamp 1624142935.01234

读取Stream

使用 XREAD 命令从Stream中读取条目:
2. XREAD COUNT 10 STREAMS mystream 0

  • COUNT 10: 可选参数,指定读取的条目数。
  • STREAMS mystream 0: 0 表示从Stream中读取所有未读条目。
XREAD COUNT 5 STREAMS mystream 0

消费者组管理

创建消费者组:

XGROUP CREATE mystream mygroup $

读取和确认消息:

XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
XACK mystream mygroup <message-id>

获取Stream信息

XINFO STREAM mystream

删除Stream中的条目

XDEL mystream <message-id>

使用示例

假设要创建一个名为 mystream 的Stream,并进行基本的操作:
1. 创建Stream并添加条目:

XADD mystream * sensor_id 1001 temperature 37.5 timestamp
1624142935.01234 XADD mystream * sensor_id 1002 temperature 36.8 timestamp 1624142945.01567

2. 读取Stream中的条目:

XREAD COUNT 2 STREAMS mystream 0

3. 创建消费者组并消费消息:
- 创建消费者组:

XGROUP CREATE mystream mygroup $

- 消费消息:

XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
XACK mystream mygroup <message-id>

4. 获取Stream信息:

XINFO STREAM mystream

5. 删除条目:

XDEL mystream <message-id>

redis特性和优势

高性能:Redis 数据存储在内存中,操作非常快速。
持久化:支持多种持久化方式,可以将数据持久化到磁盘,保证数据安全。
复制和高可用:支持主从复制和 Sentinel 或 Cluster 方式的高可用解决方案。
事务:支持事务,可以批量执行一系列命令,保证原子性。
发布/订阅:支持发布与订阅模式,用于消息传递和通知。
丰富的功能扩展:通过 Lua 脚本和插件机制,可以扩展 Redis 的功能。

redis使用场景总结

缓存:作为高速缓存存储常用数据,加速访问速度。
会话存储:存储用户会话信息,实现无状态服务。
计数器:实现实时计数功能,如网站访问次数、商品销量等。
排行榜:通过有序集合存储用户积分和排名信息。
消息队列:利用列表和发布/订阅功能实现异步消息传递。

// TODO 未完待续

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

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

相关文章

通过 WireGuard 组建虚拟局域网 实现多个局域网全互联

本文后半部分代码框较多,欢迎点击原文链接获得更佳的阅读体验。 前言 上一篇关于 WireGuard 的文章通过 Docker 安装 wg-easy 的形式来使用 WireGuard,但 wg-easy 的功能比较有限,并不能发挥出 WireGuard 的全部功力。 如果只是想要出门在外连随时随地的连回家里的局域网,…

067、Python 高阶函数的编写:优质冒泡排序

以下写了个简单的冒泡排序函数&#xff1a; def bubble_sort(items: list) -> list:for i in range(1, len(items)):swapped Falsefor j in range(0, len(items) - 1):if items[j] > items[j 1]:items[j], items[j 1] items[j 1], items[j]swapped Trueif not swa…

UCOS高频面试题及参考答案(2万字长文)

目录 UCOS-II/UCOS-III的基本特点和适用场景 UCOS-II与UCOS-III的主要区别 UCOS的任务状态 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数 UCOS-III任务调度过程 时间片轮转调度与UCOS-II 创建UCOS任务的步骤 使用UCOS信号量进行任务同步 信号量与互斥量的区别 UCOS中…

[数据集][目标检测]棉花叶子害虫检测数据集VOC+YOLO格式571张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;595 标注数量(xml文件个数)&#xff1a;595 标注数量(txt文件个数)&#xff1a;595 标注类别…

Linux驱动调试——使用DEVICE_ATTR实现cat、echo指令调试驱动

在平常做一些驱动调试的时候&#xff0c;每次都写应用去调试相对较麻烦&#xff0c;有一个非常便捷的操作方法就是使用device_attr&#xff0c;只需要执行shell指令例如echo和cat就可以看到效果&#xff0c;不需要再单独写一个测试demo。 看网上很多博客在这一块的使用上写的都…

FENDI CLUB精酿啤酒与小麦的不解之缘

FENDI CLUB精酿啤酒与小麦之间这种联系体现在啤酒的酿造原料、口感特色以及文化内涵等多个方面。以下是关于这两者之间关系的详细分析&#xff1a; 一、酿造原料的紧密联系 小麦作为关键原料&#xff1a;FENDI CLUB精酿啤酒在酿造过程中&#xff0c;小麦是不可或缺的原料之一…

Mybatis 系列全解(1)——全网免费最细最全,手把手教,学完就可做项目!

Mybatis 系列全解&#xff08;1&#xff09; 1. 第一个小程序2. CURD 增删改查3. 模糊查询4. 配置解析4.1 核心配置文件4.2 环境配置4.3 属性4.4 类型别名4.5 设置4.6 映射器 mappers 1. 第一个小程序 1&#xff09;创建一个数据库&#xff0c;一个表&#xff0c;填入一些数据…

OpenAI项目爆改GLM——以基于llama_index的pdf阅读助手

最近在做大模型agent构建&#xff0c;看了许多不错的开源项目&#xff0c;但是clone下来就是一整个不能用&#xff0c;因为github上开源的项目基本都是基于openai做的。而如果想要转成国内大模型backbone&#xff0c;需要修改的地方挺多的。 现在以一个简单的pdf reader agent…

【Qt】QList<QVariantMap>中数据修改

1. 问题 QList<QVariantMap> 类型中&#xff0c;修改QVariantMap中的值。 2. 代码 //有效代码1QVariantMap itemMap itemList.at(0);itemMap.insert("title", "test");itemList.replace(0, itemMap);//有效代码 2itemList.operator [](0).insert(…

17岁中专生姜萍数学竞赛成绩可信吗?

数学竞赛已经消失很久&#xff0c;但是因为焦虑家长存在需求&#xff0c;”赢在赛跑起点“的认知偏见&#xff0c;以及学术象牙塔为自己存在寻求存在理由和荣誉感&#xff0c;等诸多因素&#xff0c;最近一名17岁女中专生闯入某个互联网企业举办的民间数学决赛&#xff0c;引发…

Python3简单实现与Java的Hutool库SM2的加解密互通

1、背景&#xff1a; 因业务需求&#xff0c;需要与某平台接口对接。平台是Java基于Hutool库实现的SM2加密解密&#xff0c;研究了下SM2的加解密算法&#xff0c;网上找的资料&#xff0c;都是说SM2【椭圆曲线】 公钥长【x,y分量 64字节】&#xff0c;私钥短【32字节】&#x…

华为---OSPF被动接口配置(四)

9.4 OSPF被动接口配置 9.4.1 原理概述 OSPF被动接口也称抑制接口&#xff0c;成为被动接口后&#xff0c;将不会接收和发送OSPF报文。如果要使OSPF路由信息不被某一网络中的路由器获得且使本地路由器不接收网络中其他路由器发布的路由更新信息&#xff0c;即已运行在OSPF协议…

FuTalk设计周刊-Vol.031

&#x1f525;AI漫谈 热点捕手 1、如何用自然语言 5 分钟构建个人知识库应用&#xff1f;我的 GPTs builder 尝试 开发者的想象力闸门一旦打开&#xff0c;迎接我们的必然是目不暇接的 AI 应用浪潮冲击。 链接https://sspai.com/post/84325 2、GPT-4 Turbo、功能融合&#x…

Android的OverlayFS原理与作用

标签: OverlayFS; Android;Overlay Filesystem; Android的OverlayFS原理与作用 概述 OverlayFS(Overlay Filesystem)是一种联合文件系统,允许将一个或多个文件系统叠加在一起,使它们表现为一个单一的文件系统。Android系统利用OverlayFS来实现动态文件系统的叠加和管…

Java延迟初始化Logger日志对象

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ 将日志Logger对象定义在静态内部类中是一种常见的做法&#xff0c;这样做是有它特殊的好处&#xff0c;示例如下&#xff1a; privat…

MDPI期刊汇总(AI方向)

前言 本blog统计了计算机和工程领域的期刊&#xff0c;常见分区包括三种&#xff0c;中科院分区&#xff0c;JCR分区&#xff0c;CiteScore分区&#xff0c;下面分别介绍这三种分区的区别&#xff1a; 1. 中科院分区 中科院分区是中国科学院发布的期刊评价体系&#xff0c;涵…

【机器学习】大模型驱动下的医疗诊断应用

摘要&#xff1a; 随着科技的不断发展&#xff0c;机器学习在医疗领域的应用日益广泛。特别是在大模型的驱动下&#xff0c;机器学习为医疗诊断带来了革命性的变化。本文详细探讨了机器学习在医疗诊断中的应用&#xff0c;包括疾病预测、图像识别、基因分析等方面&#xff0c;并…

Qt 技术博客:深入理解 Qt 中的 delete 和 deleteLater 与信号槽机制

在 Qt 开发中&#xff0c;内存管理和对象生命周期的处理是至关重要的一环。特别是在涉及信号和槽机制时&#xff0c;如何正确删除对象会直接影响应用程序的稳定性。本文将详细讨论在使用 Qt 的信号和槽机制时&#xff0c;delete 和 deleteLater 的工作原理&#xff0c;并给出最…

IOS Swift 从入门到精通: For 循环, While 循环, 重复循环, 退出循环, 退出多重循环, 跳过项目, 无限循环

文章目录 For 循环While 循环重复循环退出循环退出多重循环跳过项目无限循环总结 For 循环 Swift 有几种编写循环的方法&#xff0c;但它们的底层机制是相同的&#xff1a;重复运行一些代码&#xff0c;直到条件计算为假。 Swift 中最常见的循环是一个for循环&#xff1a;它将…

LCR 142.训练计划IV

1.题目要求: /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ int compare(const void* a,const void* b) {return (*(int*)a - *(int*)b); } struct ListNode* trainningPlan(struct ListNode* l1, struct Li…