当前位置: 首页 > news >正文

Redis7.0八种数据结构底层原理

导读

本文介绍redis应用数据结构与物理存储结构,共八种应用数据结构和
在这里插入图片描述

一. 内部数据结构

1. sds

sds是redis自己设计的字符串结构有以下特点:

  • jemalloc内存管理
  • 预分配冗余空间
  • 二进制安全(c原生使用\0作为结尾标识,所以无法直接存储\0)
  • 动态计数类型(根据字符串长度动态选择结构)
  • 功能强大

最为重点是引入了jemalloc,十分高效且能有效在redis的场景中减少内存碎片;
在这里插入图片描述
不同的字符串长度使用的结构不同最高可以节省18字节;

2. dict

redis的hash表实现
核心结构
核心结构由两个类型为dictEntry的数组组成,使用开链法的数据结构;

扩容

采用渐进式扩容数组,但数组需要扩容或缩容时开辟数组2,使用数组2存储新数组,在后续操作命中数组1的bucket时,只复制命中的bucket数据到数组2;
同时主线程在每次循环任务时会分配1毫秒协助尚未复制的;
扩容完成
完成所有数组1复制到数组2后,使用2替代1,并空出2为下一次扩容准备

总结点
  • 扩容阈值更低,链条均长不过4
  • 渐进式rehash,响应时间更加平滑

3. listpack(紧凑集合,双向链表)

在这里插入图片描述
紧凑类型集合,在申请的一块连续的内存(byte[])中存储一个集合数据结构,使用少量的内存但支持所需的集合操作

实现原理

主数据结构上分两快:

  • 记录数据使用总长度,因为连续的内存快可能有一部分还未使用
  • Body存储实际数据

Body内存储多个条目(实际数据),每个条目头尾都会记录条目长度,从而实现快速的头尾遍历。此外条目头部会分配一个字节记录条目的类型,这个类型可以减少记录长度的使用内存(小数据量的条目可能8位的int就够记录了,而长的可能需要32位int才够记录)。

核心操作时间复杂度:

操作时间复杂度对应指令
头插O(1)LPUSH
尾插O(1)RPUSH
头取O(1)LPOP
尾取O(1)RPOP

缺点

因为每个条目的头尾都记录了长度,所以从头和尾顺序操作很快,但涉及集合中间数据数据时间复杂度就会增加:

操作时间复杂度对应指令
范围取O(n)LRANGE
指定取O(n)LINDEX

同时因为基于连续内存快(byte[]数组),涉及到LINSERT(指定下标插入)就需要重新对内存块的数据做移动操作;

4. quicklist

listpack明显的一个问题是数据量大了对于O(n)时间复杂度指令性能变差,这对于单线程处理指令模型很容易成为性能短板,quicklist为解决这点而设计。
在这里插入图片描述
通过拆分多个小块的listpack(从而可以快速定位范围),quicklist使用双向链表管理这些小块的listpack,同时quicklist会根据阈值对listpack进行lzf算法压缩,进一步缩减内存占用提升效率

缺点

额外的管理结构内存quicklist(40 byte)、quicklistNode(32 byte),但在效率的提升面前不值一提

5. intset

这是一个只存储int类型(最大支持64位int)的唯一值集合,头部存储值的编码类型与长度其他位置都存储实际数据,因为数组内的数据大小都严格是头部设置的编码类型所以没有分隔符,同时从小到大存储,所以可以用二分快速查找值。
在这里插入图片描述
从新增值的角度切入有一下核心点:

  • 每新增一个值都要开辟新内存
  • 如果当前编码类型不够存储新值,那将需要重新对所有数据变更数据结构(INT16->INT32)
  • 修改头部数据:当前数据长度

从这点可以发现一些问题,每次添加值都需要扩容内存,为了保持步长一样所有数据都要保持一样的编码类型导致浪费内存;

优点也明显,内存占用少、查询效率O(log n)

核心操作时间复杂度:

操作时间复杂度对应指令
查询值O(log n)SISMEMBER
添加值O(n)SADD

6. skiplist

跳表是zset的核心数据结构,有序且读写操作效率保持O(logN),从贴出来的代码能出来它不是一个存储在连续内存快的实现(对比listpack和intset);

/* ZSET使用特殊版本的跳表 */
typedef struct zskiplistNode {sds ele;//实际值double score;//分数struct zskiplistNode *backward;//最上层的前一位(例如node3的最上层前一位是node1)struct zskiplistLevel {struct zskiplistNode *forward;//向后的node(例如层级1的node3:向后是node4->node5->node6)unsigned long span;} level[];//存储这个node所在的所有层级(例如节点3那么这个level将只有两个槽位,别存储level1和level2)
} zskiplistNode;typedef struct zskiplist {struct zskiplistNode *header, *tail;//头与尾(最大或最小值)unsigned long length;  //存储的数据量int level;//跳表深度(也就是索引层数量)
} zskiplist;typedef struct zset {dict *dict;	//<值:Score>(为了快速检查是否唯一)zskiplist *zsl;//跳表
} zset;

在这里插入图片描述
zset是有序&唯一的数据结构,这两特性决定了需要频繁排序和确认唯一,对于保持有序重点对比的是红黑树(也是java中TreeMap的内部实现方法):

操作跳表 (QPS)红黑树 (QPS)优势
插入 10w 元素125,00098,000+27.5%
范围查询 1000 元素45,00032,000+40.6%
查询 1 元素110,000125,000-13%
内存占用 (10w 元素)45MB52MB-13.5%
代码实现量200行500+行150%

红黑树的树深和跳表的level都可以理解成一个组合的索引,同样是定位"4"但红黑树的二叉树实现明显是可以更快的(红黑树从头到尾都是二分查找)因为红黑树的每一个层级(索引)分布更加均匀,而跳表得益于每个动态随机的层级分布(每个level)层级节点更少从而跳表使用更少的内存
在这里插入图片描述
在Redis中的跳表实现,已节点3为例: 每个节点都会存储自己在每个level的情况,同时单向链表链接向后的节点 ,有了这些信息就可以从最高的level往下找到目标;
在这里插入图片描述
以上介绍可以总结以下几点:

  • 排序快
  • 内存占用少
  • 范围取值性能好
  • 查询效率O(logN)
  • 代码相比简单

而在redis中的跳表还使用了一个dict<值,Scroe>哈希表优化实现唯一值检查和快速过滤无效操作,因为查找某个值不是跳表的强项(相比红黑树);

7. HyperLogLog(Dense稠密存储&SPARSE稀疏)

理解数据结构前需要先理解HyperLogLog算法原理(请先看下方的[应用数据结构->HyperLogLog])

struct hllhdr {char magic[4]; /* 魔法值由于识别结构体"HYLL" */uint8_t encoding; /* 编码:HLL_DENSE(稠密) or HLL_SPARSE(稀疏). */uint8_t notused[3]; /* 预留字段,暂无使用 */uint8_t card[8]; /* 缓存统计结果 */uint8_t registers[]; /* 实际存储 */
}

registers[]存储的就是桶数据,以稠密存储为例,会一口气申请12KB,6位为一个桶一共16,384个桶:

12KB=12,288B=98,304bit
98,304÷6=16,384个桶

桶中记录最长的末尾连续0次数,6bit最高能记录64次,算法只使用hash的末50位所以6bit足够记录最大连续50位0(节省内存);
在这里插入图片描述

SPARSE稀疏存储

通过 稀疏存储结构(Sparse Encoding) 在数据量较小时大幅减少内存占用,其核心原理是将连续的零值桶压缩表示,并通过动态编码策略平衡内存与性能。稀疏存储在uint8_t registers[]的存储方式与稠密存储不同,更加节省内存;
不再是一下子申请12KB,而是2B;
初始化结果实例
在这里插入图片描述

稀疏存储的编码结构
Redis 的 HLL 稀疏存储使用 三元组(Triplet) 表示连续的桶状态,通过操作码(Opcode)标识块类型:

操作码二进制格式占用字节描述
XZERO01xxxxxx xxxxxxxx2B表示连续 16384 个桶的值为 0(最大覆盖范围,仅用于初始化)
ZERO00xxxxxx1B表示连续 1~64 个桶的值为 0,长度由低 6 位(xxxxxx)表示
VAL1vvvvvv11B表示 1 个桶的非零值,值由高 5 位(vvvvv)存储,低 1 位(l)固定为 1

只有槽位1001是3示例:
在这里插入图片描述
示例中使用XZERO表示0-1000的桶都是0,使用VAL表示第1001个桶是3,最后又使用XZERO表示剩余的15382个桶都是0;
不再一次性开辟所有桶的内存,一但超过阈值再转换为密集存储,从而在空间与时间上有较好的平衡:

性能与内存对比

指标稀疏编码(小基数)密集编码
内存占用300B ~ 3KB固定 12KB
PFADD 延迟较高(需遍历块)极低(直接位操作)
适用场景基数 < 10000基数 ≥ 10000 或高并发

Radix tree(基数树)

Redis 选择 Rax树(基数树,Radix Tree) 作为 Stream 类型数据的底层存储结构,是为了在 内存效率、范围查询性能 和 有序性维护 之间取得平衡

typedef struct rax {raxNode *head; //根节点uint64_t numele;//数据量uint64_t numnodes;//节点数量void *metadata[]; //元数据
} rax;typedef struct raxNode {uint32_t iskey:1;uint32_t isnull:1; uint32_t iscompr:1;uint32_t size:29;  //以上:节点标记位unsigned char data[]; //实际节点数据:存储listpack结构数据
} raxNode;

data内使用listpack存储节点数据,并不是常规的二叉树
在这里插入图片描述
追加到listpack:
若当前listpack未满(默认限制约 4096字节),直接追加新消息。
若已满,创建新的listpack,并在Rax树中插入新叶子节点。

二. 应用数据结构

0. 存储框架

Redis是个KV数据库,它的最外层是16,384个solt(也就是一致性hash的槽位),每个槽位中是实际存储dictkey:应用数据结构的数据(hash表);

当执行以下指令后:

LSET key1 index value
SET key2 value
HSET key10 field value

实际在redis中的存储结构会是:
在这里插入图片描述
16384个solt组成一致性hash环,每个sold都是一个db,db内部是Hash表,也就是RedisKV数据库的核心结构;

1. String

基于sds,没啥好说的

2. Hash

在这里插入图片描述
使用dict不难理解,本身Hash类型就是一个哈希表;
在小数据量使用listpack是为在空间与时间上做平衡,listpack使用两个entry为一组分别存储kv:
在这里插入图片描述

特性listpackdict(哈希表)
内存占用低(连续存储,无指针开销)高(指针、元数据、哈希表桶开销)
100个值内存占用2.2KB)12KB
查询效率O(n)(需遍历)O(1)(哈希直接定位)
插入/删除效率中等(需内存重排)高(直接操作节点,但扩容有抖动)
适用场景小数据(字段数少,值长度短)大数据(字段多,查询频繁)
自动转换阈值hash-max-listpack-entries(默认512)hash-max-listpack-value(默认64字节)超出阈值时自动转为 dict
内存碎片少(连续内存块)多(动态扩容、指针分散)

3. List

在这里插入图片描述

基于上文对listpack的介绍,它是一个紧凑(节省内存)、小数据量性能有保障(大数据量性能不好)的数据结构,为了应对大数据量使用quicklist分段listpack进行管理,但只有到达阈值才会从单个listpack升级到quicklist(也就是一开始List里面只有一个listpack),同时达到阈值也会降级为一个listpack。

4. Set

在这里插入图片描述

set两个核心操作: 值唯一、取差集并集交集;
值唯一实现内部使用的三种数据结构(intset、listpack、hasht),intset和dict都是可以轻松实现set属性(值唯一),listpack在插入前做查询检查后再插入也可以实现set属性,但listpack的查询效率是O(n)略显差劲,好再listpack升级到dict的阈值不高;
取差集并集交集这实现基于遍历筛选,没有很复杂的点(源码:t_set.c#sinterGenericCommand);

5. ZSET

zset是一个有序值唯一的集合,内部使用了listpack和skiplist;
在这里插入图片描述
以下文指令切入

127.0.0.1:6379> ZADD zsetKey 1 "apple" 2 "banana" 3 "orange"
(integer) 3

根据score(1、2、3)作为排序的优先级,也就是要存储值和对应的score;
其中listpack与上文介绍的数据存储上有些不同:
在这里插入图片描述
两个条目一组分别存储实际值与score,同时listpack也支持查询步长+1的跨越条目查询
同时listpack本身是无序的,但默认最多只会存储64条所以每次获取时才扫描顺序;

而超过64条后会转换为skiplist(跳表);

6. Bitmap

布隆过滤器,内部存储结构是基于sds申请的一大块内存char[],根据客户端给的槽位(bit)并标记1
在这里插入图片描述
Bitmap限制最大sds为512M,51210241024*8= 4,294,967,296位(即 42.9 亿个bit);

  SETBIT key 7 1 #第八位设置为1

以上指令在第8bit设置为1,Bitmap申请内存并非一口气申请最大512M,而且根据当前要设置的最大逐步申请新的sds;

bitmap实现并不复杂:

指令时间复杂度补充
SETBITO(1)
GETBITO(1)
BITCOUNTO(N)遍历
BITPOSO(N)扫描
BITFIELDO(N)扫描

7. HyperLogLog

HyperLogLog使用快速、高效的、统计近似基数,我们直接介绍核心原理:
在这里插入图片描述
以上是三组抛筛子游戏,规则是越晚抛出正面的人获胜,换个方向理解就是:连续抛出最多反的人获胜;在大量的实验后第N次抛出正的概率会根据N的增加概率越小,而根据概率我们可以计算出大概需要多少组才能得到第N次才是正:

第N次才是正概率平均抛出次数
第二次25%4
第四次6.25%16
第六次1.56%64

带入HyperLogLog,使用MurmurHash64A计算出"user1"的64位hash值,使用后50位模拟抛硬币游戏,即末尾连续的0代表反面,从而得到所需次数(比如末尾出现了5个0那我们定义为在此之前已经抛了64次,从而得到一个基数),而我们只需要记录最大的才是正的次数就可推测出本次游戏大概进行了多少组;

PFADD "key" "user1"

在这里插入图片描述
计算出的hash值是固定的,可以理解为每个值都只有一次拔高最大连续0的机会,从而变相的去重计数;
但有个问题如果只记录一个出现的最长的连续0那只会被一个hash值顶高,比如一开始出现一个值的hash末尾连续5个0那么就会一开始把次数拔高到64次;

所以使用hash的前14位计算槽位,14位最大表示数字16,384也就是会有16,384槽位。也就是理想状态下会记录16384组,最终统计这些槽位值会得到个更贴近的基数(使用调和平均数算法计算平均数)

图解网站:http://content.research.neustar.biz/blog/hll.html

以上算法基于<伯努利试验>

而存储结构采用了两种:
在这里插入图片描述

8. Geospatial

Geospatial可以快速获取给定经纬度附近的对象, 通过对经纬度进行Geohash编码将二维数据转为一维数据:
参考文档:https://cloud.tencent.com/developer/article/1949540

Geohash计算出的hash可以排序,也就是相邻的两个经纬度转换出的hash在数值上也相邻,这个hash可以作为ZSET数据格式的Scroe,ZSET底层是跳表,跳表对范围取值时间复杂度较低;

9. Stream

Streams 是一种仅追加的数据结构。基本写入命令(称为 XADD)将新条目追加到指定的流中。
默认会使用-生成每条消息的id,生成的id向前递增,对实际的存储结构有很大的帮助(因为前置数字最大限度保持一致,使用基数树作为存储结构时能够减少内存与基于时间范围查询)

性能:

Processed between 0 and 1 ms -> 74.11%
Processed between 1 and 2 ms -> 25.80%
Processed between 2 and 3 ms -> 0.06%
Processed between 3 and 4 ms -> 0.01%
Processed between 4 and 5 ms -> 0.02%

99.9% 的请求的延迟为 <= 2 毫秒,异常值仍然非常接近平均值。

数据量数据大小占用内存
100w1KB1.1G
100W250B285.4M

实测插入100w条仅需30秒,qps3.3w

到此可以总结出redis stream对比kafka:

维度rediskafka
数量级别GPB
高可用有可能丢失可以做到不丢失
功能基础丰富
单点stream只单节点多分区
qps5w左右(受限只能在一台机器上)百万级别

Stream 的核心需求

  • 有序性:Stream 消息按时间顺序存储(ID 格式为 <时间戳>-<序列号>),需支持高效范围查询(如 XRANGE)。
  • 内存压缩:消息 ID 具有大量公共前缀(相同时间戳),适合前缀树压缩。
  • 动态扩展:Stream 可能频繁插入新消息,需低开销的动态结构调整。

采用了基数树作为存储结构
在这里插入图片描述
Stream的默认ID生成方案具有大量前缀(时间戳)、有序向前递进,stream只需删除末尾(没有随机删除的需求),只需摘除节点即可。
同时时间戳前缀可以实现基于时间定位与范围取值。

相关文章:

Redis7.0八种数据结构底层原理

导读 本文介绍redis应用数据结构与物理存储结构,共八种应用数据结构和 一. 内部数据结构 1. sds sds是redis自己设计的字符串结构有以下特点: jemalloc内存管理预分配冗余空间二进制安全(c原生使用\0作为结尾标识,所以无法直接存储\0)动态计数类型(根据字符串长度动态选择…...

Kafka 高吞吐量的底层技术原理

Kafka 之所以能够实现高吞吐量&#xff08;每秒百万级消息处理&#xff09;&#xff0c;主要依赖于其底层设计和多项优化技术。以下是 Kafka 实现高吞吐量的关键技术原理&#xff1a; 1. 顺序读写磁盘 Kafka 利用磁盘的顺序读写特性&#xff0c;避免了随机读写的性能瓶颈。 顺…...

CCFCSP第34次认证第一题——矩阵重塑(其一)

第34次认证第一题——矩阵重塑&#xff08;其一&#xff09; 官网链接 时间限制&#xff1a; 1.0 秒 空间限制&#xff1a; 512 MiB 相关文件&#xff1a; 题目目录&#xff08;样例文件&#xff09; 题目背景 矩阵&#xff08;二维&#xff09;的重塑&#xff08;reshap…...

网络工程师 (35)以太网通道

一、概念与原理 以太网通道&#xff0c;也称为以太端口捆绑、端口聚集或以太链路聚集&#xff0c;是一种将多个物理以太网端口组合成一个逻辑通道的技术。这一技术使得多个端口能够并行工作&#xff0c;共同承担数据传输任务&#xff0c;从而提高了网络的传输能力和可靠性。 二…...

O1、R1和V3模型

O1、R1和V3模型分别是不同团队或公司开发的人工智能模型&#xff0c;它们在定位、能力和应用场景上存在显著区别。以下是它们的详细对比&#xff1a; 1. 模型归属 O1模型&#xff1a;由OpenAI开发&#xff0c;属于其高性能推理模型系列。 R1和V3模型&#xff1a;由DeepSeek&a…...

Linux 安装 Ollama

1、下载地址 Download Ollama on Linux 2、有网络直接执行 curl -fsSL https://ollama.com/install.sh | sh 命令 3、下载慢的解决方法 1、curl -fsSL https://ollama.com/install.sh -o ollama_install.sh 2、sed -i s|https://ollama.com/download/ollama-linux|https://…...

docker配置国内源

配置Docker使用国内源&#xff08;也称为镜像加速器&#xff09;可以显著提高拉取Docker镜像的速度&#xff0c;特别是在中国地区。以下是如何配置Docker使用国内源的步骤&#xff1a; 1. 修改Docker配置文件 Docker的配置文件通常位于/etc/docker/daemon.json。如果该文件不…...

【leetcode】关于循环数组的深入分析

原题&#xff1a;https://leetcode.cn/problems/rotate-array/description/ 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1…...

DeepSeek 指导手册(入门到精通)

第⼀章&#xff1a;准备篇&#xff08;三分钟上手&#xff09;1.1 三分钟创建你的 AI 伙伴1.2 认识你的 AI 控制台 第二章&#xff1a;基础对话篇&#xff08;像交朋友⼀样学交流&#xff09;2.1 有效提问的五个黄金法则2.2 新手必学魔法指令 第三章&#xff1a;效率飞跃篇&…...

【力扣题解】【76. 最小覆盖子串】容易理解版

76. 最小覆盖子串 总结和复盘 这是时隔1年4个月之后&#xff0c;再次写的题解&#xff0c;比第一次要清晰很多。 我刚开始&#xff0c;就是用方法一做的&#xff0c;提交之后报超出内存限制&#xff1b; 对方法一进行优化&#xff0c;得到方法二&#xff0c;提交之后就AC了。…...

Android10 音频参数导出合并

A10 设备录音时底噪过大&#xff0c;让音频同事校准了下&#xff0c;然后把校准好的参数需要导出来&#xff0c;集成到项目中&#xff0c;然后出包&#xff0c;导出方式在此记录 设备安装debug系统版本调试好后&#xff0c; adb root adb remount adb shell 进入设备目录 导…...

在 Windows 系统中如何快速进入安全模式的两种方法

在使用电脑的过程中&#xff0c;有时我们可能会遇到一些需要进入“安全模式”来解决的问题。安全模式是一种特殊的启动选项&#xff0c;它以最小化配置启动操作系统&#xff0c;仅加载最基本的驱动程序和服务&#xff0c;从而帮助用户诊断和修复系统问题。本文中简鹿办公将详细…...

计算机网络(1)基础篇

目录 1.TCP/IP 网络模型 2.键入网址--->网页显示 2.1 生成HTTP数据包 2.2 DNS服务器进行域名与IP转换 2.3 建立TCP连接 2.4 生成IP头部和MAC头部 2.5 网卡、交换机、路由器 3 Linux系统收发网络包 1.TCP/IP 网络模型 首先&#xff0c;为什么要有 TCP/IP 网络模型&a…...

自然语言处理NLP入门 -- 第四节文本分类

目标 本章的目标是帮助你理解文本分类的基本概念&#xff0c;并通过具体示例学习如何使用 scikit-learn 训练文本分类模型&#xff0c;以及如何利用 OpenAI API 进行文本分类。 5.1 什么是文本分类&#xff1f; 文本分类&#xff08;Text Classification&#xff09;是自然语…...

【redis】数据类型之bitmaps

Redis的Bitmaps是一种基于字符串的数据结构&#xff0c;用于处理位级别的操作。虽然Bitmaps在Redis中并不是一种独立的数据类型&#xff0c;而是基于字符串实现的&#xff0c;但它们提供了高效的位操作功能&#xff0c;适用于需要处理大量布尔值或二进制数据的场景。 基本概念…...

计算机网络-MPLS转发原理

在上一篇关于 MPLS 基础的文章中&#xff0c;我们了解了 MPLS 的基本概念、术语以及它在网络中的重要性。今天&#xff0c;我们将深入探讨 MPLS 转发的原理与流程&#xff0c;帮助大家更好地理解 MPLS 是如何在实际网络中工作的。 一、MPLS 转发概述 MPLS 转发的本质是将数据…...

5. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Nacos

一、什么是Nacos Nacos 是阿里巴巴开源的一款云原生应用基础设施&#xff0c;它旨在简化微服务架构中服务治理和配置管理的复杂性。通过 Nacos&#xff0c;服务在启动时可以自动注册&#xff0c;而其他服务则可以通过名称来查找并访问这些注册好的实例。同时&#xff0c;Nacos…...

【每日关注】科技圈重要动态

时代新动态 2025 年 2 月 12 日科技圈重要动态总结全球 AI 治理新进展巴黎 AI 宣言签署&#xff0c;美英缺席 科技巨头合作与竞争苹果联姻阿里开发中国版AI功能DeepSeek生态持续扩展OpenAI拒绝马斯克收购&#xff0c;矛盾公开化 汽车行业动态小米汽车销量跃居新势力第二比亚迪智…...

【算法】用C++实现A*算法

A*算法的背景与原理 A*(A-Star)算法是一种广泛应用于路径规划和图搜索问题中的启发式搜索算法。它结合了Dijkstra算法的广度优先搜索和贪心最佳优先搜索的优点,通过引入启发式函数来估计从当前节点到目标节点的成本,从而有效地减少搜索空间。A*算法的核心思想是使用一个评…...

细胞计数专题 | LUNA-FX7™新自动对焦算法提高极低细胞浓度下的细胞计数准确性

现代细胞计数仪采用自动化方法&#xff0c;在特定浓度范围内进行细胞计数。其上限受限于在高浓度条件下准确区分细胞边界的能力&#xff0c;而相机视野等因素则决定了下限。在图像中仅包含少量可识别细胞或特征的情况下&#xff0c;自动对焦可能会失效&#xff0c;从而影响细胞…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

DAY 45 超大力王爱学Python

来自超大力王的友情提示&#xff1a;在用tensordoard的时候一定一定要用绝对位置&#xff0c;例如&#xff1a;tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾&#xff1a; tensorboard的发展历史和原理tens…...

python打卡day47

昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import D…...