• 图文详解低压配电系统,超赞!

    图文详解低压配电系统,超赞!

    昨天 33浏览
  • 新能源汽车电池管理系统(BMS)

    在现代电池应用的广阔领域中,电池管理系统(Battery Management System,简称 BMS)发挥着至关重要的作用。从电动汽车到便携式电子设备,从大规模储能电站到各类工业应用,BMS 的身影无处不在,它全方位地呵护着电池的健康,确保电池系统高效、安全且稳定地运行。下面,我们将深入剖析电池管理系统的各个方面。 一、BMS 的定义 电池管理系统是一种用于监控、管理和保护电池系统的电子装置。它通过实时采集电池的各项参数,如电压、电流、温度等,并依据这些参数进行精确的分析和计算,进而对电池系统实施有效的控制和管理。其核心目标在于确保电池在各种复杂的工作条件下,始终处于最佳的工作状态,最大限度地发挥电池的性能优势,同时有效延长电池的使用寿命,保障电池使用过程中的安全性。简单来说,BMS 就是电池系统的 “智慧大脑”,负责协调电池系统内各个部分的工作,使其发挥出最佳效能。 二、BMS 的功能 (一)电池状态监测 电压监测:精确监测电池组中每一个单体电池的电压,以及整个电池组的总电压。通过对电压的实时监测,BMS 能够判断电池的充电状态(SOC)、健康状态(SOH)等关键信息。例如,当单体电池电压过高或过低时,可能意味着电池存在过充、过放或其他故障问题,BMS 会及时发出警报并采取相应措施。 电流监测:准确测量电池充放电过程中的电流大小和方向。电流数据对于计算电池的充放电量、评估电池的功率输出能力以及监测电池的工作状态至关重要。通过监测电流,BMS 可以实时掌握电池的能量流动情况,防止过大的充放电电流对电池造成损害。 温度监测:实时监测电池的温度分布,由于电池在充放电过程中会产生热量,温度过高或过低都会对电池的性能和寿命产生严重影响。BMS 通过在电池组中布置多个温度传感器,精确感知各个部位的温度变化,一旦发现温度异常,便会启动散热或加热装置,将电池温度控制在适宜的范围内。 (二)电池保护 过充保护:当电池充电达到满电状态时,BMS 会及时切断充电电路,防止电池过充。过充可能导致电池内部压力升高、电解液分解、甚至引发起火爆炸等严重安全事故。BMS 通过监测电池电压和充电电流等参数,精确判断电池的充电状态,一旦检测到过充迹象,立即采取保护措施,确保电池安全。 过放保护:在电池放电过程中,BMS 会实时监测电池电压,当电压降至设定的最低保护值时,BMS 会自动切断放电电路,避免电池过度放电。过度放电会导致电池容量永久性损失,缩短电池使用寿命,BMS 的过放保护功能能够有效防止这种情况发生。 过流保护:当电池充放电电流超过允许的最大值时,BMS 会迅速切断电路,以防止过大的电流对电池造成热失控、电极材料损坏等问题。过流保护功能能够在瞬间响应,保护电池免受异常电流的冲击。 过热保护:如前文所述,电池温度过高会严重影响其性能和安全性。当 BMS 监测到电池温度超过安全阈值时,会立即启动散热风扇、水冷系统等散热装置,或者降低充放电电流,减少电池产热,确保电池温度在安全范围内。 (三)电池均衡管理 在电池组中,由于单体电池在制造工艺、材料特性等方面存在细微差异,长时间使用后,各单体电池之间会出现容量、电压等不一致的情况,即所谓的 “不均衡” 现象。这种不均衡会导致部分电池过度充放电,从而加速整个电池组的老化和性能衰退。BMS 的均衡管理功能旨在通过主动或被动的方式,使电池组中各个单体电池的电量保持一致,提高电池组的整体性能和使用寿命。 主动均衡:主动均衡是指通过能量转移的方式,将电量较高的单体电池中的能量转移到电量较低的单体电池中,使各单体电池的电量趋于一致。常见的主动均衡方法包括电容均衡、电感均衡和 DC - DC 变换器均衡等。主动均衡能够快速、有效地实现电池均衡,尤其适用于对电池性能要求较高的应用场景。 被动均衡:被动均衡则是通过在单体电池上并联电阻等耗能元件,当某个单体电池电压高于其他电池时,通过电阻将多余的能量以发热的形式消耗掉,从而实现电池均衡。被动均衡方法简单、成本较低,但存在能量浪费的问题,均衡速度相对较慢。 (四)电池状态估计 剩余电量(SOC)估计:准确估计电池的剩余电量对于用户合理使用电池设备至关重要。BMS 通过多种算法,如安时积分法、开路电压法、卡尔曼滤波法等,综合考虑电池的电压、电流、温度等参数,对电池的剩余电量进行精确估算。SOC 估计的准确性直接影响用户对设备续航能力的判断,BMS 会不断优化算法,提高 SOC 估计的精度。 健康状态(SOH)估计:SOH 反映了电池的老化程度和性能衰退情况。BMS 通过监测电池的内阻变化、容量衰减等指标,结合数学模型和算法,对电池的 SOH 进行评估。准确的 SOH 估计有助于用户及时了解电池的健康状况,提前做好电池更换或维护计划,避免因电池故障导致设备无法正常使用。 三、BMS 的组成部分 (一)硬件部分 主控单元(MCU):作为 BMS 的核心处理器,主控单元负责接收来自各个传感器的数据,进行数据处理和分析,并根据预设的算法和策略,发出相应的控制指令。它具备强大的运算能力和数据处理速度,能够快速响应电池系统的各种变化,确保 BMS 的高效运行。 电压采样电路:用于采集电池单体和电池组的电压信号。电压采样电路需要具备高精度、高可靠性和良好的抗干扰能力,以确保采集到的电压数据准确无误。通常采用专用的电压采样芯片或模块,通过分压、滤波等处理后,将电压信号传输给主控单元。 电流采样电路:负责测量电池充放电电流。电流采样电路一般采用霍尔电流传感器、分流器等元件,将电流信号转换为电压信号,经过放大、滤波等处理后,输入到主控单元进行分析和计算。准确的电流测量对于电池状态监测和保护功能的实现至关重要。 温度采样电路:通过温度传感器(如热敏电阻、热电偶等)采集电池的温度信息。温度采样电路将温度传感器输出的信号进行调理和转换,使其符合主控单元的输入要求。由于电池组不同部位的温度可能存在差异,通常需要在多个关键位置布置温度传感器,以全面监测电池的温度分布。 通信接口电路:BMS 需要与外部设备(如整车控制器、充电设备、上位机等)进行数据通信,以实现信息交互和协同控制。常见的通信接口包括 CAN 总线、LIN 总线、RS485 等。通信接口电路负责将主控单元的数据进行编码和转换,通过相应的通信协议与外部设备进行数据传输。 保护电路:包括过压保护、过流保护、欠压保护等电路,用于保护 BMS 硬件本身以及电池系统免受异常电压、电流的损害。当检测到异常情况时,保护电路会迅速动作,切断相关电路,防止硬件损坏和安全事故发生。 (二)软件部分 数据采集与处理程序:负责控制硬件电路实时采集电池的电压、电流、温度等数据,并对采集到的数据进行滤波、校准、存储等处理。数据采集与处理程序需要具备高效、准确的特点,确保数据的可靠性和及时性。 电池状态估计算法:如前文所述,包括 SOC、SOH 等估计算法。这些算法是 BMS 软件的核心部分,通过对采集到的数据进行分析和计算,精确估计电池的状态。算法的优劣直接影响 BMS 的性能和精度,研发人员不断优化和改进算法,以提高电池状态估计的准确性。 保护控制策略程序:根据电池的状态信息,依据预设的保护规则和策略,生成相应的控制指令,实现过充、过放、过流、过热等保护功能。保护控制策略程序需要具备快速响应、可靠性高的特点,确保在异常情况下能够及时有效地保护电池系统。 均衡控制程序:负责实现电池均衡管理功能,根据电池的不均衡情况,控制主动或被动均衡电路的工作,使电池组中各单体电池的电量趋于一致。均衡控制程序需要根据不同的均衡方式和电池特性,采用合适的控制算法,提高均衡效率和效果。 通信协议栈程序:实现与外部设备通信所需的各种通信协议,如 CAN 通信协议、LIN 通信协议等。通信协议栈程序负责数据的打包、解包、发送和接收,确保 BMS 与外部设备之间的数据通信稳定、可靠。 四、BMS 的工作原理 BMS 的工作过程可以简单概括为数据采集、数据分析与处理、控制决策与执行三个主要环节。 数据采集:电压采样电路、电流采样电路和温度采样电路实时采集电池的电压、电流和温度等参数,并将这些模拟信号转换为数字信号,传输给主控单元。 数据分析与处理:主控单元接收到传感器采集的数据后,首先对数据进行滤波处理,去除噪声干扰,然后根据预设的算法和模型,对电池的状态进行分析和计算,如估算 SOC、SOH 等。同时,主控单元还会将当前电池的状态数据与预设的安全阈值进行比较,判断电池是否处于正常工作状态。 控制决策与执行:当主控单元判断电池出现异常情况(如过充、过放、过流、过热等)时,会根据预设的保护控制策略,立即发出相应的控制指令,通过驱动电路控制保护电路动作,切断充放电回路,或者启动散热、均衡等装置,对电池进行保护和管理。在正常工作情况下,BMS 也会根据电池的状态信息,对充电设备或负载进行合理的控制,优化电池的充放电过程,提高电池的使用效率和寿命。 五、BMS 的技术发展趋势 (一)高精度的电池状态估计技术 随着对电池性能要求的不断提高,研发更加精确的电池状态估计技术成为 BMS 的重要发展趋势。未来,BMS 将结合更多的传感器数据和先进的算法,如机器学习、深度学习算法等,对电池的 SOC、SOH 等状态进行更准确的估计,为用户提供更可靠的电池信息。 (二)高效的电池均衡技术 为了进一步提高电池组的性能和寿命,开发更高效、快速且节能的电池均衡技术是关键。新型的主动均衡技术,如基于无线能量传输的均衡技术、多端口 DC - DC 变换器均衡技术等,将逐渐得到应用和推广,以实现电池组中各单体电池的精准均衡。 (三)高可靠性和安全性设计 在电动汽车、储能电站等对安全性要求极高的应用场景中,BMS 的可靠性和安全性至关重要。未来,BMS 将采用冗余设计、故障诊断与容错控制等技术,提高系统的可靠性和安全性,降低电池系统发生故障的风险。同时,加强对电池系统的热管理和安全防护设计,确保在极端情况下电池系统的安全运行。 (四)智能化与网络化发展 随着物联网、大数据、云计算等技术的发展,BMS 将向智能化和网络化方向迈进。通过与互联网连接,BMS 可以实现远程监控、诊断和管理,用户可以随时随地通过手机、电脑等终端设备获取电池的状态信息,并对电池进行远程控制。同时,BMS 还可以将大量的电池运行数据上传至云端,通过大数据分析挖掘潜在的价值,为电池的优化设计、维护管理提供依据。 六、BMS 在不同领域的应用 (一)电动汽车领域 在电动汽车中,BMS 是确保车辆安全、高效运行的核心部件之一。它不仅能够实时监测电池的状态,保护电池免受过度充放电和过热等损害,还能通过优化电池的充放电过程,提高电池的使用效率和续航里程。此外,BMS 还与整车控制器进行通信,协调车辆的动力输出和能量回收等功能,提升电动汽车的整体性能。 (二)储能领域 在储能系统中,无论是电网储能、可再生能源储能还是家庭储能,BMS 都起着至关重要的作用。它能够对储能电池进行有效的管理和保护,确保电池在频繁的充放电循环中保持良好的性能和寿命。同时,BMS 还可以根据电网的需求和储能电池的状态,实现储能系统的优化调度和控制,提高储能系统的经济性和可靠性。 (三)便携式电子设备领域 对于智能手机、平板电脑、笔记本电脑等便携式电子设备,BMS 虽然相对简单,但同样不可或缺。它可以监测电池的状态,提供准确的电量显示,防止电池过充过放,延长电池的使用寿命,为用户提供更好的使用体验。 综上所述,电池管理系统作为电池系统的核心组成部分,在保障电池安全、提高电池性能和延长电池寿命等方面发挥着不可替代的作用。随着新能源技术的不断发展和应用领域的不断拓展,BMS 的技术水平也在不断提升,其功能将更加完善,性能将更加卓越,为推动新能源产业的发展和实现能源的可持续利用提供有力支持。

    前天 49浏览
  • RF术语与概念-4:驻波比VSWR

    引言:驻波比是无源/有源元器件中的一个重要参数,用来表征器件的前后阻抗匹配程度,广泛引用在多工器、天线等​器件中,本节简述驻波比​。

    03-07 91浏览
  • 上百种电路图,接线不求人,记得收藏……

    上百种电路图,接线不求人,记得收藏……

    03-07 206浏览
  • DeepSeek 现象级突破的技术解码

    DeepSeek 现象级突破的技术解码 DeepSeek 无疑是一个具有“国运级”意义的现象级产品。它的技术突破主要体现在三个方面:低成本训练范式革新、国产算力适配突破和场景化模型蒸馏技术。 首先, DeepSeek 采用了极简架构,能够以 3% 到 5% 的行业成本实现模型训练,大幅降低了资源占用。这种低成本训练模式加上开源的方式,极大地降低了模型开发门槛,让众多企业和研究机构能够参与其中。 其次,国产算力适配突破是 DeepSeek 带来的另一个重要影响。此前,国产芯片一直在努力适配国外框架,而 DeepSeek 的出现让国产芯片找到了用武之地。特别是华为的昇腾芯片,与 DeepSeek 的适配性非常好,推动了国内 GPU 厂商的发展。昇腾 910B 等产品与 DeepSeek 深度合作,实现了从硬件到技术链路的全面国产化,加速了国产化进程。如今,许多企业都在咨询如何私有化部署 DeepSeek 模型,这也为国产算力的发展提供了新的机遇。 最后, DeepSeek 不仅推出了 671B 的满血版模型,还通过蒸馏技术开发了多种轻量级版本,32B、18B 和 7B 等。这种从满血版到轻量版的跨越,为企业提供了灵活选择的空间,能够根据不同场景的需求进行适配。例如,企业可以根据自身业务蒸馏出投资版、制造业版、化工行业版或汽车零部件版等专属模型。同时,DeepSeek 在动态部署方面也具有优势,能够在复杂决策场景中使用满血版模型,在高并发交互场景中使用轻量级模型,实现混合式部署。 DeepSeek 爆火背后的“冷思考” 在 DeepSeek 爆火的当下,每个人似乎都在谈论它,仿佛不参与讨论就显得自己与 IT 圈脱节。朋友圈里每天都在刷屏,某某产品接入了 DeepSeek,仿佛不接入 DeepSeek 的产品都成了“垃圾产品”。而最引人注目的还是股票市场——DeepSeek 概念股的兴起确实带动了整个经济氛围的活跃。与此同时,我也发现,最近很多人在交流中对经济的信心似乎又回来了,这不得不说是一个非常积极的现象。 在 全民 AI 的时代,DeepSeek 如此火爆的背后,我们也需要进行一些“冷思考”。真正的问题是:DeepSeek 到底能用来做什么? 作为技术人,我们尤其需要避免陷入“技术自嗨”的陷阱。如今,很多人都在分享 DeepSeek 背后的技术实现逻辑,但 关键在于我们如何将它真正应用到实际场景中。 在短视频平台上,大家都在宣传如何部署 DeepSeek,搭建个人 AI 知识库。但当你在自己的电脑上搭建起这样一个知识库后,你会发现它的能力其实非常有限。因为电脑本身的性能有限,你最多只能运行 7B 或 8B 的模型,而这些小模型的能力是远远不够的。搭建一个简单的 AI 知识库并不难,但当你的文件数量超过两三千份时,多路召回的效果会变得极差。在文件数量较少时,知识库的效果可能还不错,但要让它真正产生价值、提升生产力,还有很长的路要走。 另一方面,很多新媒体人在宣传所谓的“DeepSeek+”,比如“DeepSeek+ 王炸组合”,声称可以成倍提升功能效率。确实,DeepSeek 在办公效率方面,比如写作(如 Kimi)、图像处理(如剪映、PS)等工具的使用上,确实能带来一些帮助。但对我们技术人来说,更重要的是如何将 DeepSeek 更好地应用到更多实际场景中去,而不仅仅是停留在表面的效率提升。 如何打造差异化竞争优势 在当前 AI 技术快速发展的背景下,无论是个人还是公司,都需要思考如何打造差异化竞争优势。随着 AI 的兴起,作为技术人需要结合自身优势和经验,找准定位。拿我本人来说,有近 20 年的开源经验,同时也有七八年的创业经验,因此我希望将开源与商业化相结合,分享 AI 技术的同时,探讨如何提升决策能力。于是,我将自己的公众号从“Asta 聊工业”改为“AI 进厂的 Asta”,专注于分享 AI 在编程、开源和商业化方面的内容。在内容创作上,我尝试用 AI 辅助写作,提纲和核心内容仍需自己撰写,完后再让 AI 优化,这样既能保持个人写作风格,又能提升效率。 个人工具的全面 AI 化是提升效率的关键。我目前常用的 AI 工具包括以下几种: Cursor:我每天都会用它来编写代码,尤其是前端开发,效率提升显著。 DeepSeek 和 Claude:将两者结合使用,Claude 在长文本创作上更符合我的写作风格,而 DeepSeek 则用于联网搜索技术报告。 Grok 3:其 Deep Search 功能非常强大,我正在不断尝试。 Ideogram:这是一个类似 Midjourney 的文生图工具,生成的图片设计感很强,我经常用它来生成图片。 Napkin:它可以将文档一键生成脑图或 PPT 格式的图表,非常适合快速制作 PPT。 Notion:我用它来收集各种想法和计划,同时也会将 Claude 生成的内容整理到 Notion 中。 即梦 AI:我用它生成海报,效果不错,尤其是中文显示效果很好。 创客贴:主要用于海报设计,其 AI 设计功能非常实用。 Gamma:用于快速生成 PPT,设计简洁且支持导出 PDF 和 PPT 格式。 我从 2009 年开始接触 Go 语言,而 GopherChina 也是从 2015 年开始举办,至今已经十年了。这十年间,Go 社区不断成熟,技术话题也逐渐趋同化。比如,大家讨论的大多是云计算、K8S 容器、微服务、监控等热门领域。这些内容在过去十年里已经被分享得非常充分,社区的成熟也意味着技术发展进入了一个稳定阶段。 随着 AI 时代的到来,技术人不能固步自封,必须勇敢拥抱变革。因此,我决定将 Go 社区全面升级为一个 AI 社区——ThinkIn AI。这个社区目前还处于起步阶段,但已经展现出巨大的潜力。在这个过程中,我们做了以下两件事: 第一,开发了一个 DeepSeek 模型兼容性检测工具。这个工具的灵感来源于朋友的提问:他们的电脑配置能否部署某个型号的 DeepSeek 模型,比如 1.5B、7B 或 8B 等。基于这个需求,我利用业余时间用 React 写了一个网页工具,通过显存和内存的检测,自动判断用户电脑能够部署的最大模型。这个工具开发过程非常高效,仅用了一个晚上的时间,而且完全通过对话式编程完成,我没有手写一行传统代码。推出后,这个工具受到了广泛关注,很多人反馈企业也有类似需求,希望了解服务器配置如何满足不同模型的部署要求。因此,我们又开发了一个企业部署服务器配置计算器。用户可以根据自己的需求选择模型大小(如 70B、671B 或 14B)、量化类型、序列长度、批次大小等参数,工具会计算出所需的显存、CPU 配置、模型参数占用等信息,并推荐适合的硬件配置,包括 GPU、CPU、内存和网络等。同时,我们在工具底部宣传了 ThinkIn AI 社区,目前社区已经吸引了大量用户,14 个群几乎都满了,这说明大家对 AI 的热情非常高涨。 第二,我们开始探索 DeepSeek 部署后的应用场景。目前,虽然已经有 Chatbox 和 Open Web UI 等客户端可以连接 DeepSeek,但我们认为 DeepSeek 客户端可以实现更多功能,尤其是对于企业私有化部署来说,需要更强大的智能体开发。因此,我们决定自己开发一个开源的客户端——DeepChat。这个项目完全开源,采用 Apache 协议,今天刚刚发布了 0.02 版本,支持联网功能,可以通过搜索引擎结合 DeepSeek 进行更强大的处理。我们的目标是将 DeepChat 打造成连接强大 AI 与个人世界的智能助手。未来,人们会越来越多地通过终端设备处理各种事务,包括电脑、平板和手机。我们希望在终端设备上开发更多小应用,比如下一个版本将支持文件上传和内容总结功能,用户可以上传多个文件并输出自己想要的格式。DeepChat 不仅可以连接企业的大脑,也可以连接个人电脑,用户可以选择连接本地的小 AI,也可以连接公网上的满血版 AI。我们还计划全面对接 MCP 协议,将个人智能体的功能整合进来,充分发挥终端设备的潜力。我们希望通过开源的方式,像 DeepSeek 一样,毫无保留地分享技术,打造一个全球知名的 AI 应用生态。 对于我们企业而言,从个人到社区,再到企业层面,我们的差异化优势其实非常明确。比如,我们将 Go 社区转型为以 DeepSeek 为核心的 AI 社区,这一转变本身就体现了我们的独特性。我们始终以开源项目为驱动,围绕 AI 编程、开源项目、DeepSeek 工具链以及 MCP 社区的终端应用展开工作。这种以开源为基础、以技术为核心的发展路径,是我们区别于其他社区和企业的关键所在。 在企业层面,我们面临的挑战是 如何在 DeepSeek 私有化部署这一竞争激烈的市场中找准自己的定位。如今,许多企业都在涉足 DeepSeek 的私有化部署,但我们必须思考:用户为什么选择我们?如何在众多竞争者中脱颖而出?这正是我们需要解决的问题。 我认为,实现差异化的核心在于“行业 Know-How + AI”。我们需要找到自己真正擅长的行业领域,并深入理解该行业的核心数据和业务流程。只有当我们清楚地知道行业数据的价值和业务流程的关键节点时,才能将 AI 技术精准地嵌入其中,从而发挥出我们的差异化优势。这种结合行业深度知识与 AI 技术的能力,才是我们能够在市场中立足的关键。 AI 技术商业化落地的“道”与“术” 所谓“道”,是指我们对场景选择和用户痛点的深刻理解。首先,我们必须从用户的真实痛点出发,这是商业化的基础。其次,商业模式的验证至关重要,需要从一开始就设计好盈利模式,思考如何持续赚钱。用户痛点的发现并非孤立的,而是通过与不同行业人士的交流逐渐明晰的。例如,有医院希望部署 DeepSeek 的私有化方案,但面临技术选型和硬件适配的难题;还有企业希望通过小模型解决特定业务问题,需求千差万别。这些痛点背后,反映出行业对 AI 技术的迫切需求,也凸显了我们作为技术提供方的机会。 仅仅发现痛点还不够,我们需要结合行业 Know-How 与 AI 技术,找到数据和业务流程中的关键点,将 AI 嵌入其中,实现差异化价值。比如,金融行业可以通过 AI 优化风险控制,医疗行业则可以利用 AI 提升诊断效率。这种结合行业深度知识与 AI 技术的能力,才是我们能够在市场中立足的关键。 在“术”的层面,我们则需要关注技术的成熟度和数据的积累。选择成熟的技术可以降低风险,而数据的积累和算法的优化则是持续迭代的基础。AI 技术的快速迭代要求我们不断优化模型,以适应市场的变化。 小   结 在 AI 时代,每个人都有机会成为超级个体,无论是个人创业还是小团队创业,都需要 从技术的迷恋转向技术的实用化,从产品思维转向用户价值思维。技术本身并不重要,重要的是技术与场景的结合。同时,从单打独斗转向生态协同也是必然趋势。AI 的商业化落地需要构建完整的生态,包括技术提供方、数据支持方和应用场景方。

    03-04 98浏览
  • 10kV线路故障口诀

    运行中的10kV线路,因雷、风、雪自然灾害和遭受外力、环境污染等原因,常常会发生跳闸事故。

    03-03 55浏览
  • CMOS应用有多广泛?

    CMOS是非常重要的组件,那么就目前而言,CMOS的发展现状究竟如何呢?如果大家对CMOS的研究较多,就会发现CMOS在很多领域内都有所应用。为增进大家对CMOS的认识,本文将和大家一起看看CMOS工艺在射频范畴的设计研究。...

    02-26 134浏览
  • 电机选型计算必要参数总结

    1、功率:P=FV(线性运动)      T=9550P/N(旋转运动)P——功率——WF——力——NV——速度——m/sT——转矩——N.M2、速度:V=πDN/60X1000D——直径——mmN——转速——rad/min3、加速度:A=V/tA——加速度——m/s2t——时间——s4、负载...

    02-20 26浏览
  • 三相异步电动机的结构

    三相异步电动机的结构三相交流异步电动机的主要部件,见下图所示:它主要由定子和转子两大部分组成。定子是指电动机的静止部分。它主要由机座、定子铁心、端盖、定子三相对称绕组等组成。机座通常由铸铁或...

    02-20 32浏览
  • 深入理解Redis网络模型结构及其流程

    1.0 用户空间与内核空间概述 1)用户空间: 用户空间是指运行用户应用程序的内存区域。在这一空间中,应用程序可以执行其代码并处理数据,但不允许直接访问内核空间中的资源或数据结构。 每个用户程序在其独立的地址空间中运行,彼此之间是隔离的。这意味着一个程序不能直接干扰另一个程序的内存或资源。 2)内核空间: 内核空间是操作系统内核所占用的内存区域。内核负责管理硬件资源、进程调度、内存管理、文件系统以及网络协议等核心功能。 内核空间拥有对所有硬件和系统资源的权限,应用程序无法直接访问这一空间。 2.0 Redis 网络模型 Linux 系统为了提高 IO 效率,会在用户空间和内核空间都加入缓冲区: 以上是读数据的过程: 当用户要从网络中读取数据时,首先在用户空间中执行命令来调用内核空间中的命令,因为用户空间的命令不能直接来调用或者使用硬件资源。此时,需要等待内核空间调用命令来从网卡中获取数据,接着,将从网卡中获取到的数据先是拷贝到内核空间中的缓冲区,最后再从内核空间中的缓冲区数据拷贝到用户空间缓冲区中。 简单来说: 1)写数据时:要把用户缓冲数据拷贝到内核缓冲区,然后写入设备。 2)读数据时:要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区。 这一整个过程可以分为两个小过程: 1)等待数据就绪。 2)从内核拷贝数据到用户空间。 因此,通过对以上两个过程不同的处理就演变出不同的方式:阻塞 IO、非阻塞 IO、IO 多路复用、信号驱动 IO、异步 IO 。 2.1 Redis 网络模型 - 阻塞 IO 顾名思义,阻塞 IO 就是两个阶段都必须阻塞等待。 当用户来读取数据时,此时内核还没有准备好数据,那么进程就直接 "硬等",直到内核准备好数据,所以,第一个过程是当前线程阻塞为阻塞状态。由于第一个过程还没获取到数据,还在等待数据,自然而然的,第二个过程也就没有数据拷贝到用户缓冲区中,也就是说,第二个过程同样是阻塞状态。 2.2 Redis 网络模型 - 非阻塞 IO 顾名思义,非阻塞 IO 的 recvfrom 操作会立即返回结果而不是阻塞用户进程。 可以看到,非阻塞 IO 模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高。而且忙等机制导致 CPU 空转,CPU 使用率暴增。 2.3 Redis 网络模型 - IO 多路复用 无论是阻塞 IO 还是非阻塞 IO,用户应用在一阶段都需要调用 recvfrom 来获取数据,差别在于无数据时的处理方案: 1)如果调用 recvfrom 时,恰好没有数据,阻塞 IO 会使进程阻塞,非阻塞 IO 使 CPU 空转,都不能发挥 CPU 的作用。 2)如果调用 recvfrom 时,恰好有数据,则用户进程可以直接进入第二阶段,读取并处理数据。 比如服务端处理客户端 Socket 请求时,在单线程情况下,只能依次处理每一个 Socket,如果正在处理的 Socket 恰好未就绪,线程就会被阻塞,所有其他客户端 Socket 都必须等待,性能自然会很差。 因此,可以采用 IO 多路复用的方式来解决。 IO 多路复用方式简单来说,就是通过一个用户进程来监视内核中的多个数据,并在某个数据准备好则进行读写处理。 那么用户进程如何知道内核中数据是否就绪呢? 可以通过文件描述符表(File Descriptor):简称 FD,是一个从 0 开始递增的无符号整数,用来关联 Linux 中的一个文件。在 Linux 中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。 因此 IO 多路复用:是利用单个线程来同时监听多个 FD,并在某个 FD 可读、可写时得到通知,从而避免无效的等待,充分利用 CPU 资源。 在 IO 多路复用中,获取到就绪的 FD,然后根据 FD 的信息再来调用 recvfrom 命令,此时,内核中的缓冲区一定会有相对应的数据,直接从内核中拷贝回用户缓冲区即可。 需要注意的是,如果等待数据过程中,没有监听到已就绪的 FD,仍旧是阻塞等待,所以第二个阶段也是处于阻塞状态。不过,概率很小,因为 FD 很多,总有很大可能在短时间内获取到已就绪的 FD。 在 IO 多路复用中,对于如何监听 FD 的方式、通知的方式又有多种实现,常见的有:select、poll、epoll 三种常见的方式。 select、poll、epoll 的主要差异: 1)select 和 poll 只会通知用户进程有 FD 就绪,但不确定具体是哪个 FD,需要用户进程逐个遍历 FD 来确认。 2)epoll 则会在通知用户进程 FD 就绪的同时,把已就绪的 FD 写入用户空间。 2.3.1 IO 多路复用 - select select 是 Linux 中最早的 IO 多路复用实现方案: select 的相关源码: 在源码中,可以看到有 int select() 函数,里面的主要字段: 1)int nfds:要监视的 fd_set 的最大 FD + 1,也就是集合中有多个 FD,按照顺序从 1 到 1024 存放在集合中,nfds 表示监视的范围从 0 到最大的 FD + 1 之内。 2)fd_set *readfds:需要监视读事件的 FD 集合。 3)struct timeval *timeout:监听的超时时间,null 表表示永不超时、0 表示不阻塞等待、大于 0 表示等待的时间。 fd_set:表示一种类型,实际就是一个整型数组,数组大小是固定为 1024 个比特位。每一个 bit 表示一个 FD,0 表示未就绪,1 表示已就绪。 select 具体监听 FD 的过程: 在用户进程中创建一个 fd_set 集合,也就是一个 1024  比特大小的整型数组,再收集需要监听的 FD 并且存放在该数组中,接着调用 select() 方法,开始监听:首先将收集好 FD 数组拷贝到内存缓冲区中,接着在内核空间对该数组进行遍历查看是否有相对应的数据,如果一个都没有找到就绪的 FD,则休眠,直到等到的数据已就绪或者超时就会被唤醒,假设 FD = 1 数据就绪了,接着将对应的 FD 设置为 1,其他设置为 0,再拷贝回用户缓冲区中,最后再由用户空间对数组进行遍历,找到就绪的 FD,调用 recvfrom 命令获取数据。 select 模式存在的问题: 1)需要将整个 fd_set 从用户空间拷贝到内核空间,select 结束还要再次拷贝回用户空间。 2)select 无法得知具体哪个 fd 就绪,需要遍历整个 fd_set 。 3)fd_set 监听的 fd 数量不能超过 1024 。 2.3.2 IO 多路复用 - poll poll 模式对 select 模式做了简单改进,但性能提升不明显,部分关键代码如下: poll() 函数的主要字段: 1)struct pollfd *fds:是一个 pollfd 类型的数组,pollfd 的内部结构封装了要监听的 FD、events 要监听的事件类型、revents 实际发生的事件类型。该数组可以自定义大小,这解决了 select 模式中能最大监听 1024 个 FD 的问题。 2)nfds_t nfds:数组元素个数。 3)int timeout:超时时间。 poll 模式监听 FD 的具体流程: 1)创建 pollfd 数组,向其中添加关注的 fd 信息,数组大小自定义。 2)调用 poll 函数,将 pollfd 数组拷贝到内核空间,转链表存储,无上限。 3)内核遍历 fd,判断是否就绪。 4)数据就绪或超时后,拷贝 pollfd 数组到用户空间,返回就绪 fd 数量 n 。 5)用户进程判断 n 是否大于 0 。 6)大于 0 则遍历 pollfd 数组,找到就绪的 fd 。 与 select 对比: 1)select 模式的 fd_set 大小固定为 1024,而 pollfd 在内核中采用链表,理论上无上限。 2)监听 FD 越多,每次遍历消耗时间也越久,性能反而会下降。 需要C/C++ Linux服务器架构师学习资料加qun579733396获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享 2.3.3 IO 多路复用 - epoll epoll 模式是对 select 和 poll 的改进,提供了三个函数。 相关源码如下: 1)int epoll_create():会直接在内核创建 eventpoll 结构体,一颗红黑树,用来记录要监听的 FD,另一个链表,用来记录已就绪的 FD。返回对应的句柄 epfd,用来标记。 2)int epoll_ctl():该方法主要是将要监听的 FD 添加到内核中的红黑树中。 主要参数是 epfd,记录 epoll 实例的句柄;op,要执行的类型,包含:ADD、MOD、DEL;fd,要监听的 FD; 3)int epoll_wait():该方法主要是用来等待接收已就绪的 FD。 主要参数是 epfd,eventpoll 实例的句柄;*events,用来接收已就绪的 FD;maxevents,数组的最大长度;timeout,超时时间; epoll 模式监听 FD 的具体流程: 首先在内核中创建一颗红黑树,用来接收需要监听的 FD 和一个接收已就绪的链表。接着用户进程会将需要监听的 FD 直接添加到红黑树中,并且设置  ep_poll_callback,当 callback 自动触发时,就把对应的已就绪的 FD 从红黑树加入到链表中。此时,list_head 就会通知用户进程来接收链表中已就绪的 FD,将其拷贝到 events 数组中,此时的数组中为已就绪的 FD,可以直接知道已就绪的 FD,不需要遍历。最后就可以根据已就绪的 FD 来调用 recvfrom 命令来获取数据了。 小结: 1)select 模式存在的三个问题: 每监听的 FD 最大不超过 1024 。 每次 select 都需要把所有要监听的 FD 拷贝到内核空间。 每次都要遍历所有 FD 来判断就绪状态。 2)poll 模式的问题: poll 利用链表解决了 select 中监听 FD 上限的问题,但依然要遍历所有 FD,如果监听较多,性能会下降。 3)epoll 模式中如何解决这些问题: 基于 epoll 实例中的红黑树保存要监听的 FD,理论上无上限,而且增删改查效率都非常高,性能不会随监听的 FD 数量增多而下降。 每个 FD 只需要执行一次 epoll_ctl 添加到红黑树,以后每次 epol_wait 无需传递任何参数,无需重复拷贝 FD 到内核空间。 内核会将就绪的 FD 直接拷贝到用户空间的指定位置,用户进程无需遍历所有 FD 就能知道就绪的 FD 是谁。 2.3.4 epoll 的 ET 和 LT 模型 当 FD 有数据可读时,调用 epoll_wait 就可以得到通知。但是事件通知的模式有两种: 1)LevelTriggered:简称 LT 。当 FD 有数据可读时,会重复通知多次,直到数据处理完成。是 epoll 的默认模式。 具体流程: 当内核中的链表中存在已就绪的 FD,那么就会通知多次给用户进程来获取数据到 events 集合中,可能数据量比较大,一次性拷贝不了全部数据,那么就会分多次进行拷贝,在这个阶段,LT 模式会重复多次发送通知给用户来拷贝数据,这个过程中,链表中的数据是不会删除,依旧会在链表中存储,直到数据处理完成。 2)EdgeTriggered:简称 ET。当 FD 有数据可读时,只会被通知一次,不管数据是否处理完成。 具体流程: 在内核中链表已存储就绪的 FD 时,就会给用户进程发送一次通知,当用户进程来拷贝数据的时候,链表中的 FD 就会自动删除,不管数据是否处理完毕。 举个例子: 假设一个客户端 socket 对应的 FD 已经注册到了 epoll 实例中,客户端 socket 发送了 2kb 的数据,服务端调用 epoll_wait,得到的通知说 FD 就绪。服务端从 FD 读取了 1kb 数据,接着再次调用 epoll_wait,形成循环。 如果采用 ET 模式,每一次调用 epoll_wait 函数服务端都会得到通知来读取剩下的数据。 如果采用 LT 模式,只有第一次调用 epoll_wait 函数的时候服务端才会得到通知,循环再次调用 epoll_wait 函数时,不再会发送通知给服务端,那么剩下的数据就会丢失。 解决方案: 1)在第一次拷贝数据完之后,再继续调用添加 FD 的函数,则在红黑树中的已就绪的 FD 又会再次拷贝到链表中,继续下一次通知用户进程。 2)在第一次拷贝的时候,使用循环,将其数据全部拷贝完毕。 小结: ET 模式避免了 LT 模式可能出现的惊群现象。 ET 模式最好结合非阻塞 IO 读取 FD 数据,相比 LT 会复杂一些。 2.3.5 基于 epoll 的服务端流程 基于 epoll 模式的 web 服务的基本流程: 首先调用 epoll_create 函数创建实例,在内核中创建一颗红黑树,接收需要监听的 FD 和一个链表,接收已就绪的 FD。 接着创建服务端 serverSocket 并将得到的 FD 添加到红黑树中进行监听,调用 epoll_ctl 函数进行添加 FD 到红黑树中,还要给注册 ep_poll_callback,当 FD 就绪时,将就绪的 FD 记录到链表中。 再接着就是调用 epoll_wait 函数进行等到链表中已就绪的 FD,此时会进行休眠,当超时或者被通知的时候,线程就会被唤醒,如果时超时导致的唤醒,证明目前链表中还没得到已就绪的 FD,那么就需要继续调用 epoll_wait 函数继续等待;如果被通知链表中存在就绪的 FD 被唤醒的时候,就会接着判断事件类型。 此时,当服务端的 FD 已就绪时,则 serverSocket 接收到 socket 客户端,将对应的 scoket 的 FD 添加到红黑树中,并且注册 ep_poll_callback,对客户端进行监听。 对客户端进行监听,当监听到了客户端的 FD 状态已就绪了,则说明有请求发送到服务端中,接着就会通知给用户进程,得到对应的 FD,再接着调用 recvfrom 命令来读取内核中的请求数据。 这就是基于 epoll 模式的 web 服务的基本流程。 2.4 Redis 网络模型 - 信号驱动 IO 信号驱动 IO 是与内核建立 SIGIO 的信号关联并设置回调,当内核有 FD 就绪时,会发生 SIGIO 信号通知用户,期间用户应用可以执行其他业务,无需阻塞等待。直到数据就绪,递交 SIGIO 信号,也就是得到通知,告诉用户进程,数据准备好了,可以从内核缓冲区获取了。 在第一阶段,也就是等待数据是不阻塞的,进程可以执行其他业务,而第二个阶段,拷贝数据是阻塞的。 信号驱动 IO 存在的问题: 当有大量 IO 操作时,信号较多,SIGIO 处理函数不能及时处理可能导致信号队列溢出而且内核空间与用户空间的频繁信号交互性能也较低。 2.5 Redis 网络模型 - 异步 IO 异步 IO 的整个过程都是非阻塞的,用户进程调用完异步 API 后就可以去做其他事情,内核等待数据就绪并拷贝到用户空间后才会递交信号,通知用户进程。 可以看到,异步 IO 模型中,用户进程在两个阶段都是非阻塞状态。 3.0 Redis 单线程及多线程网络模型 3.1 经典面试题:Redis 是单线程还是多线程? 1)如果对于 Redis 的核心业务部分,也就是命令处理的部分,Redis 就是单线程。 2)如果对于 Redis 整体来说,那么 Redis 就是多线程。 在 Redis 版本迭代过程中,在两个重要的时间节点引入了多线程的支持: 1)Redis v4.0:引入多线程异步处理一些耗时较长的任务,例如异步删除命令 unlink。 2)Redis v6.0:在核心网络模型中引入多线程,进一步提高对于多核 CPU 的利用率。 3.2 经典面试题:为什么 Redis 要选择单线程? 1)抛开持久化不谈,Redis 是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。 2)多线程会导致过多的上下文切换,带来不必要的开销。 3)引入多线程会面临线程安全问题,必然要引入线程锁这样的安全手段,实现复杂度增高,而且性能也会大打折扣。 3.3 Redis 网络模型的结构及具体流程 1)Redis 网络模型流程:第一个阶段 创建 serverSocket 服务端,调用 aeEventLoop 在内核中创建红黑树和链表,接着将服务端的 FD 添加到内核的红黑树中进行监听,再接调用 aeApiPoll 函数进行等待数据。一旦监听到服务端的 FD 就绪,就会调用 tcpAccepthandler 连接处理器,简单来说,该处理器就是将连接到服务端的客户端的 FD 添加到内核红黑树中进行监听处理。 如果是已经添加到红黑树的客户端的 FD 已就绪了,就会将 FD 添加到链表中,且通知用户进程来获取 FD,再接着使用 recvfrom 命令来获取该客户端的请求数据。因此,readQueryFromClient 命令请求处理器的作用是:读取请求数据。 2)Redis 网络模型流程:第二个阶段 对于 readQueryFromClient 命令请求处理器的作用是请求数据,那么具体是如何读取的呢? 相关的源代码: 可以看到里面有三个函数,readQueryFromClient() 调用了 processCommand(),而 processCommand() 调用了 addReply() 。 该函数具体的任务: 1)readQueryFromClient():获取当前客户端,客户端中有缓冲区用来读和写。读取请求数据到缓冲区和解析缓冲区字符串,转为 Redis 命令参数存入到数组中。 2)processCommand():根据命令名称,寻找对应的 command,执行命令,得到结果。 3)addReply():尝试把结果写到客户端缓存区,如果 buf 写不下,则写到 reply,这是一个链表,容量无上限。再接着将客户端添加到队列中,等待被写出。 具体结构如下: 在读取客户端发送过来的请求过程中,是 IO 操作。 3)Redis 网络模型流程:第三个阶段 现在结果已经存在到队列中了,等待被读取,也就是输出到对应的客户端,该过程进行 IO 操作。 相关源码如下: 在等待数据之前,会调用 beforeSleep 函数,监听 socket 的 FD 读事件,并且绑定写处理器,可以把响应写到客户端 socket 。一旦客户端写操作 FD 就绪了,则将队列中的结果写入到客户端中。 Redis 网络模型单线程的最终形态: Redis 6.0 版本引入了多线程,目的是为了提高 IO 读写效率。因此解析客户端命令、写响应结果时采用多线程。而核心的命令执行 IO 多路复用模块依然是由主线程执行。 Redis 网络模型多线程的最终形态: 在单线程的基础上,在 IO 读写步骤中添加多线程进行操作:在读取请求数据、解析数据的步骤、将队列中的结果写入到对应的客户端中,这些步骤都是可以使用多线程进行操作。

    02-18 136浏览
正在努力加载更多...
广告