Celery任务阻塞问题排查
笔者在工作中经常用到Celery,遇到了2个任务阻塞的问题,分享经验如下。
1 Celery原理
Celery是基于Python开发的分布式任务调度框架,可以将任务发送到若干台机器上,实现多并发调度和计算。Celery的架构主要包含生产者(Producer)、消费者(Worker)、中间人(Broker)、任务结果(Backend)。
生产者一般是计算程序的入口,负责发送任务。
中间人一般是Rabbitmq消息队列或Redis,负责接收生产者发送的任务。
消费者中包含主要的算法业务逻辑,从中间人取走任务,执行相应计算任务,最后存到数据库中。
任务结果一般是Redis,保存消费者任务执行的结果,例如任务执行是否成功、任务执行时间等。
生产者通过任务结果获取任务执行状态,当所发送所有任务全部执行完毕,代表当前任务结束。
2 问题一排查
2.1 故障现象
Celery运行任务时卡住,表现在Flower里的Active一直不动(Flower是一个监控Celery任务执行情况的工具)。
并且消息队列里Unacked任务数一直不变。Unacked表示Worker未确认。
生产者也一直获取不到结果,导致跑批暂停。
2.2 排查过程
找到任务暂停的机器,使用docker logs XXX(XXX为docker名称),发现报错如下
抛出的异常不是固定的,但都与数据库的连接池有关。因此分析的重点放在数据库连接池与Celery的结合使用上。
某worker卡住以后,其处理的任务会停留,且已经预取(prefetch)的任务也执行不下去。其他任务被其他worker卡住,因此表现出上述现象。flower中体现的是worker正在处理的任务卡住,消息队列中unacked体现的是预取的任务卡住。
2.3 故障分析
Celery默认使用多进程fork实现并发。例如并发度设置为4,则根据ps命令可以看到有1个父进程,4个子进程。在父进程fork出子进程时,会将数据库连接完整传给子进程。
数据库连接体现为文件描述符(file descriptors),一般文件描述符在不同进程之间应该是独立的。由于Celery的fork机制,导致多个子进程同时操作同一个文件描述符,进而导致数据库连接异常。
而且出现故障的任务执行很快,程序处理时间集中在读取数据库的步骤。因此在大量任务发送情况下,很容易造成fork出的4个子进程同时连接数据库现象,从而产生异常。这也说明此问题的发生是有概率的,程序中读取数据库的时间比重越大,出现问题的概率会增大。本例中其他worker没有出现问题,说明其fork出的4个子进程没有同时读取数据库。
2.4 解决方案
2.4.1 解决方案1:修改Celery并发模式
修改Celery启动命令中的并发模式,将--pool为threads、gevent、solo,分别代表多线程、协程、单机模式。Celery默认为多进程模式prefork。
优势:代码不需要改动
劣势:(1)线程和协程不适合计算密集型任务,但计算密集型任务恰恰是项目中耗时最久的任务;(2)多线程、协程方式无法配置worker_max_tasks_per_child,即无法避免内存溢出;(3)发现有重复计算问题;(4)Python存在GIL锁,多线程的效果将大打折扣。
2.4.2 解决方案2:修改Celery的并发度为1
Celery依然使用多进程启动,但修改并发度为1。从故障原因可知,父进程fork的子进程如果只有1个,则只有1个子进程操作文件描述符,避免冲突。
优势:代码不需要改动
劣势:运行速度较慢。若因为降低并发度而增大docker数量,由于docker本身也要占用内存、硬盘空间,会导致服务器性能压力较大。
2.4.3 解决方案3:数据库的连接池修改为空
在建立数据库连接时使用nullpool,即不建立连接池。
优势:完全避免不同worker之间的连接池互相影响。
劣势:单个worker每次取到新任务都要重新创建连接,无法从连接池中复用数据库连接
2.4.4 解决方案4:在定义数据库单例时即清除连接
劣势:如果在执行dispose之后、父进程fork子进程之前程序需要连接数据库(例如需要从数据库中获取相关单例),则父进程继承给子进程的连接依然非空,故障依然存在。
2.4.5 解决方案5:在Fork子进程时清除连接池(SQLAlchemy官方推荐方案)
官方建议子进程在启动时清除连接。可以使用Celery的signal功能,每次父进程fork出子进程时,将连接池中的连接清除,防止父进程中的连接继承到子进程中。此外由于只在fork子进程时做这样的操作,因此同一个worker子进程处理前后任务时,使用同一个连接池,即上一个任务使用的连接会留到下一个任务继续执行,直到此子进程被销毁,从而避免额外的开销。
2.4.6 解决方案6 比上一条更优美的解决方案
与上一条解决方案同样的思路,但是不必把所有连接显式地列出,而是在创建连接时,定义一个连接的基类,将所有实例化的连接存入到列表中。在Celery的signal处取此列表中所有的连接执行dispose。
3 问题二排查
3.1 故障现象
使用多进程模式启动Celery,生产者发送任务后,消费者接收到任务卡住。在消费者单机启动Python进程运行任务不会卡住,Celery使用多线程模式运行任务也不会卡住。
3.2 排查过程
查看Celery的进程,使用strace命令,查找当前任务卡在哪里。
如上图所示,ps查看Celery进程,共有5个进程。其中1个是父进程,其余4个进程是父进程fork出来的子进程,子进程是实际工作的进程。
对其中1个子进程执行strace,发现卡在futex这里。通过查找资料得知,Futex是一种用户态和内核态混合的同步机制,是一种轻量级的锁。
此外,在程序中打印日志,发现卡在读取数据库的步骤。
结合以上2部分线索可知,任务卡住与锁有关,与数据库有关。笔者突然想到在读取OceanBase数据库时使用了jar包,作为jdbc驱动的输入。读取jar包文件很有可能造成了锁。
3.3 事件还原
由于笔者是Python开发人员,对系统底层逻辑不熟悉,猜测的具体过程如下:
在启动Celery时,在本项目业务场景下,父进程需要从数据库读取相关数据,使用了jar包。主进程在读取时加了锁且未将锁释放,而当fork出4个子进程时,将未释放锁的文件同时复制给子进程,导致子进程一直在等待获取锁,最终表现为程序卡住。
在主进程中将读取数据库的代码注释掉后,worker正常执行。
3.4 解决方案
3.4.1 解决方案1:Celery使用多线程模式
与上一项目类似,解决方案也可以选择在Celery启动时使用多线程模式,但其优劣势在上一项目中已有说明,并不合适。
3.4.2 解决方案2:Celery的多进程改成用spawn模式
通过查找资料,在遇到Python多进程卡住时,可以将多进程模式切换成spawn模式解决,原因是spawn启动的子进程是新的python解释器,而不是从父进程中完全复制。
Celery中与spawn模式相关的配置是CELERYD_FORCE_EXECV,在旧版本中可以配置,但在后来的版本中已不建议配置,在新版本中甚至删掉了此配置。如果强行换成旧的版本,不仅会造成适配上的问题,更可能会复现官网所说的潜在问题。
如上图所示,官网在3.1.17版本提示不要启用此配置,在5.0版本中移除此配置。
3.4.3 解决方案3:在主进程中不再读取OceanBase数据库(最终的解决方案)
通过梳理业务逻辑,在主进程中,读取OceanBase数据库主要是为了获取部分配置数据。但实际上这部分配置数据是常量,因此直接在代码中定义好,不再从数据库中获取。
修改以后,worker成功执行,不再卡住。
4 经验总结
以上2个问题都遇到了Celery任务卡住的问题,其原因十分类似,但具体细节又不相同。它们都是在多进程模式下产生的,问题1是因为子进程之间数据库连接池的冲突,问题2是因为子进程之间数据库驱动文件的冲突。
Celery中多进程只支持fork,不支持spawn,因此使用多进程非常容易导致任务卡住。在解决此类问题时,一方面在代码中多打些日志,具体定位程序在哪里卡住,另一方面使用strace等命令,查看程序最后一次进行调用的资源。
5 参考资料
Connection Pooling — SQLAlchemy 2.0 Documentation
https://celeryproject.readthedocs.io/zh-cn/latest/history/whatsnew-4.0.html?highlight=CELERYD_FORCE_EXECV%20#features-removed-for-lack-of-funding
https://celeryproject.readthedocs.io/zh-cn/latest/history/changelog-3.1.html?highlight=CELERYD_FORCE_EXECV%20#version-3-1-17
https://github.com/celery/celery/issues/6036
https://devpress.csdn.net/cloudnative/66d58c512045de334a5698fe.html
相关文章:

Celery任务阻塞问题排查
笔者在工作中经常用到Celery,遇到了2个任务阻塞的问题,分享经验如下。 1 Celery原理 Celery是基于Python开发的分布式任务调度框架,可以将任务发送到若干台机器上,实现多并发调度和计算。Celery的架构主要包含生产者(…...

巧用DeepSeek,编写CAPL自动化测试脚本
文章目录 前言提问及回答小结 前言 蛇年伊始,火出圈的除了《哪吒2》登顶中国影史票房第一外,科技圈的DeepSeek国产大模型引爆全球,关于在DeepSeek上的提问无奇不有。就车载通信自动化测试,本文也来蹭蹭热度。作为CAN/LIN协议一致…...

【信息系统项目管理师】第21章:项目管理科学基础 详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 21.1 工程经济学21.2 运筹学1.线性规划2.一般的运输问题3.指派问题4.动态规划法5.最小生成树6.博弈论7.决策每年管理科学在综合题里固定是5分,案例分析和论文不考。主要是科学管理相关内容,包括工程经济学、运…...

webpack配置语言之---ts
由于webpack本身不支持ts,如果需要编译ts文件,需要下载相应的loader对ts文件进行编译,以及配置tsconfig.json文件,配置ts的编译选项 1. 安装必要的依赖 首先,确保你已经安装了 Webpack 和 TypeScript。如果还没有安装…...

WPF 进度条(ProgressBar)示例一
本文讲述:WPF 进度条(ProgressBar)简单的样式修改和使用。 进度显示界面:使用UserControl把ProgressBar和进度值以及要显示的内容全部组装在UserControl界面中,方便其他界面直接进行使用。 <UserControl x:Class"DefProcessBarDemo…...

金蛇祈福,鸿运开年!广州白云皮具城2025开市大吉!
锣鼓一响,黄金万两!2月6日大年初九,广州白云皮具城举行盛大的醒狮开市仪式!象征吉祥如意的醒狮,将好运、财运传递给全体商户和八方来客。 醒狮点睛 金鼓一响黄金万两,十头醒狮登台,董事总经理刘…...

centos虚拟机迁移没有ip的问题
故事背景,我们的centos虚拟机本来是好好的,但是拷贝到其他电脑上就不能分配ip,我个人觉得这个vmware他们软件应该搞定这个啊,因为这个问题是每次都会出现的。 网络选桥接 网络启动失败 service network restart Restarting netw…...

【ESP32cam人脸识别开门及服务器端实战源码】
本项目实现了一个基于ESP32-CAM的实时人脸识别系统,能够通过WiFi进行视频流传输,并在检测到人脸时触发开门指令。系统由两个主要部分组成:video.py(后端服务器)和 ESP32-CAM.ino(ESP32-CAM固件)…...

【自开发工具介绍】SQLSERVER的ImpDp和ExpDp工具04
SQLSERVER的ImpDp和ExpDp工具演示 1、指定某些表作为导出对象外 (-exclude_table) 验证用:导出的表,导入到新的数据库 2、指定某些表作为导出对象外 (-exclude_table) 支持模糊检索,可以使用星号 以s开头的表作为导出对象外,…...

什么是中间件中间件有哪些
什么是中间件? 中间件(Middleware)是指在客户端和服务器之间的一层软件组件,用于处理请求和响应的过程。 中间件是指介于两个不同系统之间的软件组件,它可以在两个系统之间传递、处理、转换数据,以达到协…...

WebSocket connection failed 解决
WebSocket connection failed 解决 前言 这里如果是新手小白不知道 WebSocket 是什么的? 怎么使用的?或者想深入了解的 那可以 点击这里 几分钟带你快速了解并使用,已经一些进阶讲解; WebSocket,多应用于需要双向数据…...

C语言:取出32位数据的高十六位
目录 背景 目标 操作步骤 1. 右移 16 位 2. 掩码操作(可选) 代码实现 解释: 输出: 总结: 背景 假设我们有一个 32 位的无符号整数,通常它是由 4 个字节组成的。每个字节由 8 位构成,4…...

JUnit 5 条件测试注解详解
JUnit 5 条件测试注解详解 JUnit 5 提供了一系列条件测试注解,允许开发者根据运行时环境、配置或自定义逻辑动态决定是否执行测试。这些注解能有效减少误报,提升测试的灵活性和适应性。以下是所有条件测试注解的详细介绍及示例: 一、条件测试…...

1 Java 基础面试题(上)
文章目录 前言1. Java 中的序列化和反序列化是什么?1.1 序列化(Serialization)1.2 反序列化(Deserialization)1.3 serialVersionUID1.4 序列化的应用场景1.5 Transient 关键字 2. 为什么 Java 里面不支持多重继承&…...

个人笔记---关于详解threadlocal 上下文环境存储的最佳数据类型
个人原因很久没有写代码,对于一些基础的数据类型有一些忘记,可以根据gpt和我当时的问答进行复习 关于拦截器,由于在请求的到达controller处理器之前,拦截器(当然过滤器也可以实现,我感觉都差不多)就把上下文设置在了线程副本中,那么这个请求到处理器的这些代码进行查询出来的上…...

JVM监控和管理工具
基础故障处理工具 jps jps(JVM Process Status Tool):Java虚拟机进程状态工具 功能 1:列出正在运行的虚拟机进程 2:显示虚拟机执行主类(main()方法所在的类) 3:显示进程ID(PID,Process Identifier) 命令格式 jps […...

【数据结构】树哈希
目录 一、树的同构1. 定义2. 具体理解(1) 结点对应(2) 孩子相同(3) 递归性质 3. 示例 二、树哈希1.定义2.哈希过程(1)叶节点哈希(2)非叶节点哈希(3)组合哈希值 3.性质(1) 唯一性 \re…...

UE5 蓝图学习计划 - Day 12:存储与加载
在游戏开发中,存储(Save)与加载(Load) 系统至关重要,玩家需要能够保存游戏进度、角色状态、道具数据等信息,并在下次启动游戏时恢复它们。UE5 提供了 SaveGame 蓝图类,帮助开发者快速…...

18爬虫:关于playwright相关内容的学习
1.如何在python中安装playwright 打开pycharm,进入终端,输入如下的2个命令行代码即可自动完成playwright的安装 pip install playwright ——》在python中安装playwright第三方模块 playwright install ——》安装playwright所需的工具插件和所支持的…...

图解BWT(Burrows-Wheeler Transform) 算法
Burrows-Wheeler Transform (BWT) 是一种数据转换算法, 主要用于数据压缩领域. 它由 Michael Burrows 和 David Wheeler 在 1994 年提出, 广泛应用于无损数据压缩算法(如 bzip2)中. BWT 的核心思想是通过重新排列输入数据, 使得相同的字符更容易聚集在一起, 从而提高后续压缩算…...

CMake轻松实现把编译生成文件分类输出到指定路径,同时又拷贝一份到别的指定路径(Window/Linux通用)
使用CMake管理的C项目工程你是否有以下需求: 1.项目编译时将生成的文件分类自动输出到指定位置; 2.除了上面输出到指定位置以外,还要拷贝一份到指定位置(包含头文件,配置文件,第三方依赖库文件等…...

AJAX笔记原理篇
黑马程序员视频地址: AJAX-Day03-01.XMLHttpRequest_基本使用https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p33https://www.bilibili.com/video/BV1MN411y7pw?vd_sour…...

C32.【C++ Cont】静态实现双向链表及STL库的list
目录 1.知识回顾 2.静态实现演示图 3.静态实现代码 1.初始双向链表 2.头插 3.遍历链表 4.查找某个值 4.任意位置之后插入元素 5.任意位置之前插入元素 6.删除任意位置的元素 4.STL库的list 1.知识回顾 96.【C语言】数据结构之双向链表的初始化,尾插,打印和尾删 97.【C…...

【Elasticsearch】terms聚合误差问题
Elasticsearch中的聚合查询在某些情况下确实可能存在误差,尤其是在处理分布式数据和大量唯一值时。这种误差主要来源于以下几个方面: 1.分片数据的局部性 Elasticsearch的索引通常被分成多个分片,每个分片独立地计算聚合结果。由于数据在分…...

2-kafka服务端之延时操作实现原理
文章目录 背景案例延时生产实现原理延时拉取实现原理 总结 背景 上篇我们说到了kafka时间轮是延时操作内部实现的重要数据结构,这篇我们来说下kafka内部的延时操作实现原理。这里我们以延时生产和延时拉取为例说明延时操作的实现原理。 案例 延时生产 我们知道如…...

UE求职Demo开发日志#22 显示人物信息,完善装备的穿脱
1 创建一个人物信息显示的面板,方便测试 简单弄一下: UpdateInfo函数: 就是获取ASC后用属性更新,就不细看了 2 实现思路 在操作目标为装备栏,或者操作起点为装备栏时,交换前先判断能否交换(只…...

【DeepSeek论文精读】6. DeepSeek R1:通过强化学习激发大语言模型的推理能力
欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html)原创作品 【DeepSeek论文精读】1. 从 DeepSeek LLM 到 DeepSeek R1 【DeepSeek论文精读】2. DeepSeek LLM:以长期主义扩展开源语言模型 【DeepSeek论文精读】…...

顺丰大数据开发面试题及参考答案
Flink 的提交过程是怎样的? Flink 的提交过程通常包含以下步骤: 代码编写与打包:开发人员首先使用 Flink 提供的 API 编写数据处理逻辑,包括定义数据源、转换操作和数据 sink 等。完成代码编写后,将项目打包成可执行的 JAR 文件,其中包含了所有依赖的库和资源。选择提交方…...

C# 函数多个返回值
有时候需要从C#函数中返回多个返回值,而且返回值的类型又不一样,这个时候又不能用数组或者list。 其实C#函数是支持多个不同类型的返回值的,请参看下面的code. //多返回值函数定义 (string name, int age) GetNameAge(int id) {return (&qu…...

Deepseek 接入Word处理对话框(隐藏密钥)
硅基流动邀请码:1zNe93Cp 邀请链接:网页链接 亲测deepseek接入word,自由调用对话,看截图有兴趣的复用代码(当然也可以自己向deepseek提问,帮助你完成接入,但是提问逻辑不一样给出的答案是千差万…...

RabbitMQ深度探索:简单实现 MQ
基于多线程队列实现 MQ : 实现类: public class ThreadMQ {private static LinkedBlockingDeque<JSONObject> broker new LinkedBlockingDeque<JSONObject>();public static void main(String[] args) {//创建生产者线程Thread producer n…...

Baklib赋能数字内容体验个性化推荐提升用户体验的未来之路
内容概要 随着数字化时代的不断发展,用户对内容消费的需求日益多样化,个性化推荐成为提升用户体验的重要手段。Baklib以其先进的技术手段,在数字内容领域内积极推动个性化推荐的实施,从而满足用户在信息获取和内容消费中的独特需…...

使用 TensorRT 和 Python 实现高性能图像推理服务器
在现代深度学习和计算机视觉应用中,高性能推理是关键。本文将介绍如何使用 TensorRT 和 Python 构建一个高性能的图像推理服务器。该服务器能够接收客户端发送的图像数据,使用 TensorRT 进行推理,并将结果返回给客户端。 1. 概述 1.1 项目目…...

[MySQL#1] database概述 常见的操作指令 MySQL架构 存储引擎
#1024程序员节|征文# 目录 一. 数据库概念 0.连接服务器 1. 什么是数据库 口语中的数据库 为什么数据不直接以文件形式存储,而需要使用数据库呢? 总结 二. ??基础操作 三. 主流数据库 四. 基础知识 服务器,数据库&…...

WebAssembly:前后端开发的未来利器
引言 在互联网的世界里,前端和后端开发一直是两块重要的领域。而 JavaScript 长期以来是前端的霸主,后端则有各种语言诸如 Java、Python、Node.js、Go 等等。然而,近年来一个名为 WebAssembly (Wasm) 的技术正在逐渐改变这一格局。它的高性能…...

Spring Task之Cron表达式
🌟 Spring Task高能预警:你以为的Cron表达式可能都是错的!【附实战避坑指南】 开篇暴击:为什么你的定时任务总在凌晨3点翻车? “明明设置了0 0 2 * * ?,为什么任务每天凌晨3点执行?” —— 来…...

deepseek API 调用-python
【1】创建 API keys 【2】安装openai SDK pip3 install openai 【3】代码: https://download.csdn.net/download/notfindjob/90343352...

数字滤波器的分类
数字滤波器可以根据不同的标准进行分类,以下是几种常见的分类方式: 1. 按实现结构分类 FIR滤波器(有限脉冲响应滤波器) - 特点:系统的脉冲响应在有限时间内衰减到零。 - 优点:线性相位特性(保…...

iOS 老项目适配 #Preview 预览功能
前言 iOS 开发者 最憋屈的就是UI 布局慢,一直以来没有实时预览功能,虽然swiftUI 早就支持了,但是目前主流还是使用UIKit在布局,iOS 17 苹果推出了 #Preview 可以支持UIKit 实时预览,但是仅仅是 iOS 17,老项目怎么办呢?于是就有了这篇 老项目适配 #Preview 预览 的文章,…...

高等代数笔记—域与一元多项式
域与环 数域 F F F:至少包含两个元素且对加减乘除运算封闭的复数集合 F F F,其中作除运算时除数不为0。 封闭:集合 F F F中的两个元素作某一运算的结果仍属于集合 F F F,则称 F F F对该运算封闭。 Q , R , C \mathbb{Q}, \mathbb…...

【C语言设计模式学习笔记1】面向接口编程/简单工厂模式/多态
面向接口编程可以提供更高级的抽象,实现的时候,外部不需要知道内部的具体实现,最简单的是使用简单工厂模式来进行实现,比如一个Sensor具有多种表示形式,这时候可以在给Sensor结构体添加一个enum类型的type,…...

2.Python基础知识:注释、变量以及数据类型、标识符和关键字、输入函数、输出函数、运算符、程序类型转换
1. 注释 注释是用来解释代码,增强代码可读性的部分。在 Python 中,注释分为单行注释和多行注释。 单行注释:以 # 开头,后面的内容都被视为注释。 # 这是一个单行注释 print("Hello, World!") # 输出 "Hello, Wor…...

介绍10个比较优秀好用的Qt相关的开源库
记录下比较好用的一些开源库 1. Qt中的日志库“log4qt” log4qt 是一个基于 Apache Log4j 设计理念的 Qt 日志记录库,它为 Qt 应用程序提供了强大而灵活的日志记录功能。Log4j 是 Java 领域广泛使用的日志框架,log4qt 借鉴了其优秀的设计思想ÿ…...

利用Muduo库实现简单且健壮的Echo服务器
一、muduo网络库主要提供了两个类: TcpServer:用于编写服务器程序 TcpClient:用于编写客户端程序 二、三个重要的链接库: libmuduo_net、libmuduo_base、libpthread 三、muduo库底层就是epoll线程池,其好处是…...

渗透测试之文件包含漏洞 超详细的文件包含漏洞文章
目录 说明 通常分为两种类型: 本地文件包含 典型的攻击方式1: 影响: 典型的攻击方式2: 包含路径解释: 日志包含漏洞: 操作原理 包含漏洞读取文件 文件包含漏洞远程代码执行漏洞: 远程文件包含…...

高性能 :DeepSeek-V3 inference 推理时反量化实现 fp8_cast_bf16
FP8 (8 bits) & FP16 (16 bits) FP8 和 BF16 都是浮点数格式(floating-point formats),float通过科学计数法表示数据,float [符号位指数位系数位] FP8 (8 bits):SEEEMMMMFP16 (16 bits):SEEEEEMMMMM…...

kakailio官网推荐的安装流程ubuntu 22.04
https://kamailio.org/docs/tutorials/6.0.x/kamailio-install-guide-git/ # 非必须项 wget -O- https://deb.kamailio.org/kamailiodebkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/kamailio.gpg在/etc/apt/sources.list文件追加以下内容 deb [signed-by/usr/sh…...

能否通过蓝牙建立TCP/IP连接来传输数据
前言: 最近在做一个项目时,产生了一个疑问:能否通过蓝牙建立TCP/IP连接来传输数据 查阅了一些文章,可以得出结论:不行 下面是我截取的两篇个人认可的文章的回答: 文章一: 蓝牙是一种短距离无…...

git基础使用--1--版本控制的基本概念
文章目录 git基础使用--1--版本控制的基本概念1.版本控制的需求背景,即为啥需要版本控制2. 集中式版本控制SVN3. 分布式版本控制 Git4. SVN和Git的比较 git基础使用–1–版本控制的基本概念 1.版本控制的需求背景,即为啥需要版本控制 先说啥叫版本&…...

高端入门:Ollama 本地高效部署DeepSeek模型深度搜索解决方案
目录 一、Ollama 介绍 二、Ollama下载 2.1 官网下载 2.2 GitHub下载 三、模型库 四、Ollmal 使用 4.1 模型运行(下载) 4.2 模型提问 五、Ollama 常用命令 相关推荐 一、Ollama 介绍 Ollama是一个专为在本地机器上便捷部署和运行大型语言模型&…...