Redis数据结构SDS,IntSet,Dict
1.字符串:SDS
SDS的底层是C语言编写的构建的一种简单动态字符串 简称SDS,是redis比较常见的数据结构。
由于以下几种缺点,Redis并没有直接采用C语言的字符串。
1.获取长度需要计算
2.非二进制安全 :中间不能有 \0,否则就中断。
3.不可修改 :char * s = "hello"
在这里Redis会在底层的创建两个SDS,一个是 “key” 的SDS ,一个是value。
由于不能直接采用C语言字符串,所以采用了一个结构体。
注意:len的比特位数每一位就是单位是字节
举例:对于name字符串来说,redis底层的SDS结构体中,长度是4字节,向内存申请的字节数是4字节,flags则表示不同的编码格式。
编码格式有什么作用?
核心目的是优化内存使用 和 操作效率 对于不同长度的字符串可以使用不同的头结构。
1.1.为什么叫做动态字符串
因为它具备动态扩容能力,好比一个 “hy”字符串的SDS
len:2 | alloc:2 | flags:1 | h | y | \0 |
如果要给它追加字符”Boy“,那么它首先会申请新的内存空间
如果新的字符串空间 < 1M,那么新空间是扩展后的2倍+1
如果新的字符串空间 > 1M,那么新空间是扩展后字符串长度 + 1M + 1
这个就是内存预分配。
len:5 | alloc:11 | flags:1 | h | y | B | o | y | \0 |
优点:
1.获取字符串的长度时间复杂度为O(1)
2.支持动态扩容
3.二进制安全(中间可以有\0存在)
4.减少内存分配次数
2.IntSet
IntSet是Redis中集合的一种实现方式,基于整数数组来实现,并且具备长度可变,有序的特征。
encoding包含三种工作模式,表示储存的整数大小不同:
分别可储存2字节整数,4字节整数,8字节整数。
如果IntSet中储存三个数那么它的储存结构应该是这样的:采用默认的encoding,每个数字2字节
length大小是元素的个数,contents数组保存元素。
2.1.inset如何保存大于当前编码的最大数字?
当encoding采用int16_t 也就是2个字节大小来存放每个数字,所以每个数字不应该超过两个字节,最大是32767。当存下99999时会升级编码的方式去找到合适大小.
如图是升级编码前后的contents数组占用空间大小的情况
1.升级编码到INT_32,每个数字占4字节
2.依次将每个元素向后拷贝到正确的位置
3.将要添加的元素放入末尾
4.最后将encoding的属性改为INT_32,length的值更新。
源码:
intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {uint8_t valenc = _intsetValueEncoding(value);// 获取当前值编码uint32_t pos; // 要插入的位置if (success) *success = 1;// 判断编码是不是超过了当前intset的编码if (valenc > intrev32ifbe(is->encoding)) {// 超出编码,需要升级return intsetUpgradeAndAdd(is,value);} else {// 在当前intset中查找值与value一样的元素的角标posif (intsetSearch(is,value,&pos)) {if (success) *success = 0; //如果找到了,则无需插入,直接结束并返回失败return is;}// 数组扩容is = intsetResize(is,intrev32ifbe(is->length)+1);// 移动数组中pos之后的元素到pos+1,给新元素腾出空间if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);}// 插入新元素_intsetSet(is,pos,value);// 重置元素长度is->length = intrev32ifbe(intrev32ifbe(is->length)+1);return is;
}
static intset* intsetUpgradeAndAdd(intset* is, int64_t value) {// 获取当前intset编码uint8_t curenc = intrev32ifbe(is->encoding);// 获取新编码uint8_t newenc = _intsetValueEncoding(value);// 获取元素个数int length = intrev32ifbe(is->length);// 判断新元素是大于0还是小于0 ,小于0插入队首、大于0插入队尾int prepend = value < 0 ? 1 : 0;// 重置编码为新编码is->encoding = intrev32ifbe(newenc);// 重置数组大小is = intsetResize(is, intrev32ifbe(is->length) + 1);// 倒序遍历,逐个搬运元素到新的位置,_intsetGetEncoded按照旧编码方式查找旧元素while (length--) // _intsetSet按照新编码方式插入新元素_intsetSet(is, length + prepend, _intsetGetEncoded(is, length, curenc));/* 插入新元素,prepend决定是队首还是队尾*/if (prepend)_intsetSet(is, 0, value);else_intsetSet(is, intrev32ifbe(is->length), value);// 修改数组长度is->length = intrev32ifbe(intrev32ifbe(is->length) + 1);return is;
}
总结:
1.InSet确保元素唯一,有序
2.具备类型升级,可以节省空间
3.底层采用二分查找来查询元素
4.如果数组过长,扩容时移动元素效率不高
3.Dict
Redis是一种键-值型的数据库,那么键和值间关系的维护就要靠Dict维护。
Dict是由三部分组成,分别是哈希表(DictHashTable) ,哈希节点(DictEntry),字典(Dict)
当向Dict添加键值对时,Redis首先根据key计算哈希值(h),然后利用 h & sizemask(图上掩码)计算出元素应放索引的位置,假设哈希值 h = 1, 则 1 & 3 = 1, 因此储存到角标1位
一个Dict包含两个hash表,其中一个一般是空,rehash才使用,比如负载因子超过阈值,扩展,收缩,初始化时使用。
3.1Dict的扩容
DIct中的HashTable就是数组结合单项链表实现,当集合中的元素过多必然导致hash冲突,同时链表过长hash的查询效率也会越来越低。
每次新增键值都会查询负载因子(LoadFactor = used / size)
1.如果LoadFactor >= 1 同时服务器没有执行BGSAVE/BGREWRITEAOF等后台进程。
2.哈希表的LoadFactor > 5,此时就算后台执行进程也会强制扩容。
扩容的大小为used + 1,以下是扩容操源码
static int _dictExpandIfNeeded(dict *d){// 如果正在rehash,则返回okif (dictIsRehashing(d)) return DICT_OK; // 如果哈希表为空,则初始化哈希表为默认大小:4if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);// 当负载因子(used/size)达到1以上,并且当前没有进行bgrewrite等子进程操作// 或者负载因子超过5,则进行 dictExpand ,也就是扩容if (d->ht[0].used >= d->ht[0].size &&(dict_can_resize || d->ht[0].used/d->ht[0].size > dict_force_resize_ratio){// 扩容大小为used + 1,底层会对扩容大小做判断,实际上找的是第一个大于等于 used+1 的 2^nreturn dictExpand(d, d->ht[0].used + 1);}return DICT_OK;
}
首先判断是否正在rehash 是就返回ok,否则向下执行。如果哈希表是空的就会初始化4个单位,
如果负载因子 >= 1 ,并且没有进行后台进程 或者 负载因子>= 5. 开始进行扩容。
3.2Dict的收缩
DIct除扩容之外还可以 收缩,每次执行删除后如果 负载因子 < 0.1 就会执行。
3.3.rehash
不管是扩容还是收缩,每次变化都会导致size 和 sizemask(掩码)变化,而key的查询与sizemask有关。所以必须对哈希表中每一个key重新计算索引,插入新的哈希表,这个过程就是rehash。
1.重新计算hash表的realeSize,值取决于当前要做的是扩容还是收缩
扩容:则新的size是第一个 >= dict.ht[0].used + 1 的 2^n
删除:则新的size是第一个 >= dict.ht[0].used 的 2^n (不小于 4)
2.按照新的realeSize申请内存空间,创建dictht,并赋值给dict.ht[1]
3.设置dict.rehashidx = 0,标识开始rehash
4.将dict.ht[0]的每个dictEntry都rehash到dict.h1
5.将dict.ht[1]的值赋给dict.ht[0] ,给dict.ht[1]初始化为 空哈希表,释放原来的dict.ht[0]的内存。
rehash不是一次能够完成的,如果数据百万entry则需要分批次完成,否则可能导致线程阻塞
所以叫渐进式rehash
1.重新计算hash表的realeSize,值取决于当前要做的是扩容还是收缩
扩容:则新的size是第一个 >= dict.ht[0].used + 1 的 2^n
删除:则新的size是第一个 >= dict.ht[0].used 的 2^n (不小于 4)
2.按照新的realeSize申请内存空间,创建dictht,并赋值给dict.ht[1]
3.设置dict.rehashidx = 0,标识开始rehash
4.将dict.ht[0]的每个dictEntry都rehash到dict.h1
5.每次增删查改都检查dict.rehashidx是否 > -1,如果是则将dict.ht[0].table[rehashidx]的entry链表rehash到dict.ht[1],并且将rehashidx++,直到所有数据都rehsh到dict.ht[1]
6.将dict.ht[1]的值赋给dict.ht[0] ,给dict.ht[1]初始化为 空哈希表,释放原来的dict.ht[0]的内存。
7.rehashidx赋值-1,代表rehash结束
8.在rehash过程中,新增操作,则直接写入ht[1],查询、修改和删除则会在dict.ht[0]和dict.ht[1]依次查找并执行。这样可以确保ht[0]的数据只减不增,随着rehash最终为空
相关文章:
Redis数据结构SDS,IntSet,Dict
1.字符串:SDS SDS的底层是C语言编写的构建的一种简单动态字符串 简称SDS,是redis比较常见的数据结构。 由于以下几种缺点,Redis并没有直接采用C语言的字符串。 1.获取长度需要计算 2.非二进制安全 :中间不能有 \0,…...
leetcode201.数字范围按位与
找到公共前缀部分,然后后面的部分全0 class Solution {public int rangeBitwiseAnd(int left, int right) {int offset 0;while (left ! right) {offset;left left >> 1;right right >> 1;}return right << offset;} }...
云服务器 —— 公有 IP 与 私有 IP
云服务器的 公有 IP 和 私有 IP 在网络架构中扮演不同的角色,具体用途和区别如下: 目录 1. 公有 IP(Public IP) 作用: 特点: 示例场景: 2. 私有 IP(Private IP) 作用…...
北斗导航 | Transformer增强BiLSTM网络的GNSS伪距观测量误差探测
在GNSS(全球导航卫星系统)定位中,伪距观测量的误差直接影响定位精度。结合Transformer和LSTM的优势,可以设计一种混合模型以提升误差探测能力。以下是具体的技术实现方案: 1. 模型架构设计 1.1 输入特征设计 原始GNSS观测数据: 伪距观测值(C/A码、P码)、载波相位、多普…...
0803分页_加载更多-网络ajax请求2-react-仿低代码平台项目
文章目录 1 分页1.1 url与分页参数1.2 分页组件与url1.3 列表页引用分页组件 2 加载更多2.1 状态2.2 触发时机2.3 加载数据2.4优化 结语 1 分页 1.1 url与分页参数 查询问卷列表接口,添加分页参数: page:当前页码(第几页&#…...
React 与 Vue 的区别:你会选择哪个框架呢
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...
Jmeter如何取JDBC request响应参数作为下一个接口的值?
1、 功能参数说明 Variable Name:数据库连接池的名字,需要与JDBC Connection Configuration的Variable Name Bound Pool名字保持一致 Query:填写的sql语句未尾不要加“;” Parameter valus:参数值,对查询条件进行参数化 Paramete…...
【C++】14.容器适配器 | stack | queue | 仿函数 | priority_queue
1. 容器适配器 什么是适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设 计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。 在C中,容器适配器(Container Adapters&…...
论文阅读:2025 arxiv Aligning to What? Limits to RLHF Based Alignment
Aligning to What? Limits to RLHF Based Alignment https://arxiv.org/pdf/2503.09025 https://www.doubao.com/chat/3871529075012866 速览 这篇论文主要探讨了强化学习从人类反馈(RLHF)在对齐大型语言模型(LLMs)时的局限性…...
利用Arcgis自己绘制shp文件
1.选择自己想要创建的shp文件的位置 我是直接创建在连接文件夹中 2.右键-新建-shp 3.设置名称、要素类型、空间参考 4、点击创建要素 5、右侧选择图层、创建面 6、开始绘制,双击任意位置结束绘制 之后可以改一下shp文件的名字...
路由器重分发(OSPF+静态路由)
路由器重分发(OSPF静态路由) 静态路由充当不了翻译官 OSPF路由 OSPF路由需要宣告自己的ip, Router(config)#router ospf 1 Router(config-router)#network 10.10.10.0 0.0.0.255 area 0还要帮静态路由的也宣告一下 Router(config)#ip route…...
KTT入门
Kinetic tournament tree 简称 KTT 下文中全部简写。 KTT 用于解决类以下问题: 已知 N N N 条一次函数,求解一段区间内函数最大值。支持修改操作可以修改 x i x_i xi 或者 b i b_i bi 的值。具体做法: 我们考虑线段树来维护一个类似 Δ \Delta Δ 的东西,我们令当…...
WPF 上位机开发模板
WPF 上位机开发模板 WPF上位机开发模板,集成了基础操作菜单、海康视觉实时图像界面、串口通讯、网口通讯、主流PLC通讯、数据存储、图片存储、参数配置、权限管理、第三方webapi接口接入、数据追溯与查询等功能。 一、项目结构 WpfSupervisor/ ├── Models/ …...
理想星环OS选择NuttX作为MCU侧OS的核心原因分析
文章目录 引言一、POSIX兼容性:降低汽车软件迁移成本二、轻量级与模块化:适配MCU资源约束三、硬实时性能:保障车辆控制确定性四、多芯片适配:加速车企供应链灵活性五、安全与可靠性:构建纵深防御体系六、社区与生态&am…...
IP数据报发送和转发的过程
1. 发送端准备数据 应用程序(比如浏览器)要发送数据,比如访问一个网站。 应用层(HTTP) → 传输层(TCP/UDP) → 网络层(IP)。 IP层负责把数据包打包,加上必要…...
Pinia 详细解析:Vue3 的状态管理利器
一、Pinia 概述 Pinia 是 Vue 3 的官方推荐状态管理库,由 Vue 核心团队维护。它是对 Vuex 的改进和简化,提供了更简洁的 API 和更好的 TypeScript 支持。 Pinia 的核心优势 更简单的 API:相比 Vuex 减少了概念和模板代码完美的 TypeScript…...
pytorch python常用指令
一、常用的conda指令 创建新的python环境 conda create -n env_name python3.x 查看已有的python环境 conda env list 进入已有的python环境 conda activate env_name 退出当前的python环境 conda deactivate 二、常用的pip指令 pip install -r requirements.txt 根据…...
ubantu18.04(Hadoop3.1.3)之Spark安装和编程实践
说明:本文图片较多,耐心等待加载。(建议用电脑) 注意所有打开的文件都要记得保存。 第一步:准备工作 本文是在之前Hadoop搭建完集群环境后继续进行的,因此需要读者完成我之前教程的所有操作。 以下所有操…...
Ubuntu下安装vsode+qt搭建开发框架(二)
Ubuntu下安装vsode+qt搭建开发框架(二) 上一节介绍了vsode下搭建qt环境,采用的项目构建方式是使用qt官方的qmake工具。然而从qt6之后,官方已经开始推荐使用cmake来构建项目;并且许多项目都是cmake直接构建的,用cmake来构建项目具有可以更方便的融合其他开源项目。 一、vs…...
获取房源信息并完成可视化——网络爬虫实战1
房源信息爬虫与可视化分析程序 个人程序全网一手,盗卖必究 项目介绍 本项目是一个基于Python的房源信息爬虫与可视化分析工具,可以爬取链家网的二手房源信息,并对数据进行清洗、分析和可视化展示。通过本工具,用户可以快速了解特…...
css word
介绍 CSS word-spacing 属性,用于指定段字之间的空间,例如: p {word-spacing:30px; }word-spacing属性增加或减少字与字之间的空白。 注意: 负值是允许的。 浏览器支持 表格中的数字表示支持该属性的第一个浏览器版本号。 属…...
[mysql]约束(上)
约束 道德约束,法律约束,这个约束在表里面是狭义的. 约束广义的,比如数值型你就不能录入’abc’.字符,定义了varchar(15)范围不能超过数量15. 我们这个章节要说的约束是狭义的,是具体的我们设定的约束, 为什么我们需要约束呢 我们是为了数据的精确性和可靠性,我们了为了防…...
Eclipse 插件开发 2
Eclipse 插件开发 2 1 插件配置 1 插件配置 <?xml version"1.0" encoding"UTF-8"?> <?eclipse version"3.4"?> <plugin><extension point"org.eclipse.ui.commands"><category id"com.xu.learn.…...
用go从零构建写一个RPC(仿gRPC,tRPC)--- 版本1
希望借助手写这个go的中间件项目,能够理解go语言的特性以及用go写中间件的优势之处,同时也是为了更好的使用和优化公司用到的trpc,并且作者之前也使用过grpc并有一定的兴趣,所以打算从0构建一个rpc系统,对于生产环境已…...
树莓派(Raspberry Pi)入门建议
树莓派(Raspberry Pi)是一个低成本、信用卡大小的微型电脑,它的核心价值在于高度灵活的可编程性和丰富的硬件扩展能力。根据你的兴趣和需求,它可以用来做各种有趣且实用的项目,以下是常见的应用场景和实例:…...
SpringBoot物资管理系统 | JavaWeb项目设计与实现
概述 基于JavaWeb技术实现了一套完整的物资管理解决方案。该系统适用于企业、学校、医院等机构,提供高效的物资入库、申报、公告管理等功能,帮助用户实现物资管理的数字化与智能化。 主要内容 1. 管理员功能实现 5.1.1 物资管…...
《P1950 长方形》
题目描述 小明今天突发奇想,想从一张用过的纸中剪出一个长方形。 为了简化问题,小明做出如下规定: (1)这张纸的长宽分别为 n,m。小明将这张纸看成是由nm个格子组成,在剪的时候,只能沿着格子的…...
SpringCloud微服务架构
Spring Cloud是一个广泛使用的微服务框架,它基于Spring Boot构建,旨在帮助开发者构建复杂的分布式系统。Spring Cloud提供了多种工具和库,使得开发人员可以轻松地构建和部署微服务架构。以下是一些关键组件和概念,帮助你理解Sprin…...
网络管理知识点
1.传统网络管理:Web网管方式,CLI方式,基于SNMP集中管理 2.SNMP简单网络管理协议 SNMPV1实现方便,安全性弱 SNMPV2支持更多错误 SNMPV3认证加密,访问控制 3.SNMP,UDP传输效率较高,报文容易丢失…...
【Web应用服务器_Tomcat】二、Tomcat 核心配置与集群搭建
在企业级 Java Web 应用的部署场景中,Tomcat 作为主流的 Servlet 容器和 Web 服务器,其核心配置的优化以及集群搭建对于保障应用的高性能、高可用性至关重要。 一、Tomcat 核心配置优化 1.1 server.xml 配置文件解析 Tomcat 的核心配置文件server…...
模板引擎语法-算术运算
模板引擎语法-算术运算 文章目录 模板引擎语法-算术运算[toc]1.加法运算2.减法运算3.乘法与除法运算4.四则运算5.整除运算 在Django框架模板中,没有专门定义关于算术运算的语法。不过,通过一些标签和过滤器的配合使用,可以模拟实现类似“加减…...
MySQL 联合查询教程
MySQL 联合查询教程 在 MySQL 中,联合查询用于从多个表中检索数据,常用于关联表中的信息。联合查询(JOIN)通过将两个或更多表根据一定条件连接起来,从而形成一个虚拟的结果集。MySQL 支持多种类型的联合查询ÿ…...
罗技Flow跨电脑控制
Windows 下载适用于 Windows 10 或更高版本的应用程序 macOS 下载适用于 macOS 12 或更高版本的应用程序 Flow 让您可以在两台电脑之间甚至 Windows 和 macOS 之间畅快办公。 只需将支持 Flow 的鼠标的光标移动到屏幕边缘即可在电脑和操作系统之间切换。支持 Flow 的键盘会…...
Unity网络编程入门:掌握Netcode for GameObjects实现多人游戏基础(Day 39)
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
LeetCode100题
LeetCode100 两数之和 遍历数组,以哈希表存数与下标,边存边查,速找和为目标值的两数下标 class Solution {public int[] twoSum(int[] nums, int target) {int[] ansnew int[2];HashMap<Integer,Integer> mapnew HashMap<>();…...
鸿蒙代码@Builder
#代码如下: Entry Component struct CardExample {State title: string "欢迎使用鸿蒙";State content: string "这是一段自定义内容";build() {Column() {this.MyCard({ title: this.title, content: this.content })}.padding(20)}BuilderM…...
Gewechat启动启动报错
Centos7,测试连接时发现这个错误。 [rootxin ~]# curl -i -X POST http://127.0.0.1:2531/v2/api/tools/getTokenId curl: (56) Recv failure: Connection reset by peer 1、删除原容器,重新构建。 docker run -itd \--name gewe \--privileged \-v /ro…...
硅谷甄选41集-71集
第四十三集:完全按照视频敲代码的话会发现左侧顶部tabbar的display:flex失效了,是因为拆分开的子组件里面多了一个div,去掉就好了,vue3不需要再额外包裹元素。因为路径变化了,所以找不到图片的话在前面再加一个…。 第四十五集&am…...
PyQt6实例_消息工具_使用与完整代码分享
目录 使用 每日消息 全局查询 更新数据库 代码 数据库表创建 代码-数据库相关操作 代码-界面与操作逻辑 视频 使用 工具有三个面板:每日消息、全局查询、更新数据库 “每日消息”和“全局查询”,数据源:同花顺7x24小时快讯 “更新…...
docker配置mysql遇到的问题:网络连接超时、启动mysql失败、navicat无法远程连接mysql
目录 1.网络超时 方式1. 网络连接问题 方式2. Docker镜像源问题 方式3.使用国内镜像源 2.启动mysql镜像失败 3.navicat无法远程连接mysql 1.网络超时 安装MySQL时出现超时问题,可能由多种原因导致: 方式1. 网络连接问题 原因:网络不稳定…...
【虚幻C++笔记】碰撞检测
目录 碰撞检测参数详情示例用法 碰撞检测 显示名称中文名称CSphere Trace By Channel按通道进行球体追踪UKismetSystemLibrary::SphereTraceSingleSphere Trace By Profile按描述文件进行球体追踪UKismetSystemLibrary::SphereTraceSingleByProfileSphere Trace For Objects针…...
SpringBoot集成WebSocket,单元测试执行报错
问题描述 SpringBoot集成了WebSocket,单元测试启动后会报如下错误:javax.websocket.server.ServerContainer not available 这是因为SpringBootTest启动时不会启动服务器,所以WebSocket会报错。 解决方案 在注解中添加 webEnvironmen…...
Git基本操作
1. 安装与配置 安装:你可以从 Git 官方网站 下载 Windows 版本的安装程序。运行安装程序,在安装过程中,你可以按照默认设置进行安装,也可以根据自己的需求进行调整。配置:安装完成后,打开 Git Bash&#x…...
C++异步并发支持库future
future: 1.利用共享状态来异步的获取提供者的值 2.future处于共享状态就绪时才是有效的 3.future不能拷贝构造,只能移动构造,并且移动构造后共享状态失效 std::future::get 1.当共享状态就绪时,返回存储在共享状态中的值。 2…...
c++学习小结
内存分配 空间 栈区(stack)。编译器⾃动分配与释放,主要存放函数的参数值,局部变量值等,连续的内存空 间,由⾼地址向低地址扩展。 堆区(heap) 。由程序员分配与释放;不…...
Pygame物理模拟:实现重力、弹跳与简单物理引擎
Pygame物理模拟:实现重力、弹跳与简单物理引擎 大家好,欢迎来到本期的技术分享!今天我们将一起探讨如何使用Python和Pygame库来实现一个简单的物理模拟系统,其中包括重力、弹跳以及一个基础的物理引擎。如果你对游戏开发或者物理仿真感兴趣,那么这篇文章一定会让你受益匪…...
Python dotenv 使用指南:轻松管理项目环境变量
一、为什么要使用环境变量管理? 很多开发者容易把自己开发的项目上传到Github上,但偶尔会忘记把数据库密码、支付接口密钥等敏感信息和谐掉,当代码提交上去时,这些信息就像裸奔一样暴露在所有人面前。更糟糕的是,不同…...
网络攻防第一~四集
来源于一下 【小迪安全】红蓝对抗 | 网络攻防 | V2023全栈培训_哔哩哔哩_bilibili 目录 第一集 第二集 第一集 web架构包括系统、中间件、程序源码、数据库 系统 windows、linux、windows server 中间件 是前端语言和数据库是当做一个桥梁,当做解析作用&…...
TI---sysconfig生成宏
核心内容概览 1. 宏定义的总体作用 SysConfig生成的宏定义是硬件配置的符号化映射,将图形化界面的配置参数转化为可直接引用的编译时常量,核心价值包括: 免硬编码:避免手动写入硬件参数(如引脚号、波特率࿰…...
【C】初阶数据结构13 -- 快速排序
本篇文章主要讲解经典的排序算法 -- 快速排序算法 目录 1 递归版本的快速排序 1) 算法思想 (1) hoare 版本 (2) 双指针版本 (3) 挖坑法 2) 代码 3) 时间复杂度…...