LangGraph - Open Deep Research
系统稳定性设计
系统稳定性设计
- 稳定性
- 基本原则
- 分布式:压力分散,区别于单体式
- 异步化:非核心功能异步化,提升吞吐率(单位时间可以处理的请求数)
- 简单安全:避免使用未经严格验证的公共代码、库、二方包(同组织)和三方包(组织外部)
- 数据一致:最终一致性保障,幂等、可重入
- 稳定性措施
- MQ稳定性
- 消费监控,流量突增容易
- 缓存稳定性
- 流控
- 流量预估、流量流向分析
- 扩散比:每一笔请求对下游形成多少次调用
- 峰值、热点分析
- 限流
- 多维度多举措做好限流,把流量控制在系统可承载范围内,系统就不会进入完全不可用的状态;限流可以减少诸如热点、超时、慢SQL、外部依赖、系统容量不足等问题。
- 前端限流:单用户单端登录限流
- 网关限流:Nginx
- 服务限流:Sentinel,支持集群限流,但是集群限流因为需要一个中心DB存取流量值,所以性能会差很多,不适合特别高并发的场景
- 单机限流:线程池 + Guava RateLimiter(令牌桶)
- 预留Buffer
- 依赖管理
- 强弱依赖识别
- 强弱依赖模拟演练
- 预案
- 预案类型
- 业务降级
- 限流
- 系统故障(容灾)
- 存储故障
- 中间件故障
- 预案执行时机
- 自动切换
- follow技术方案设计,比如成功率低于60%切换到备库
- 提前预案
- 业务降级,比如大促前为了应对将来的暴涨流量,将非核心业务降级
- 紧急预案
- 业务有损降级,保命用
- 故障演练
- 监控
- 日志规范
- 请求上游、RPC/MQ/DB请求源头、请求用户标识等
- 系统监控
- 机器健康状态、应用健康状态
- 流量监控
- 入口流量、服务调用流量、错误流量等,注意监控流量突增
- 业务监控、数据大盘
- 业务数据总量、分类统计等
- 一致性问题监控
- 备份
- 测试体系
- 功能回归
- 全链路压测
- 日常压测和极限压测
- 数据一致性
- 最终一致性
- 方法
- 业务实时对账
- 离线对账
- 手工或自动化数据校正
汇报
摘自:https://cloud.tencent.com/edu/learning/live-3682
- 汇报
- 为什么汇报
- 沟通手段而不是目的
- 汇报类型
- 请示型:请示和领导针对某问题的交流
- 过程型:让领导了解一个项目或事情的进展
- 研讨型:让领导或一些相关人针对某类问题进行研讨
- 审批型:针对即将进行的行动进行汇报,从而获得审批通过
- 汇报的核心要素
- 目的:通过汇报达成一个目标,汇报本身不是一个目的、而是一个沟通手段
- 内容:事情
- 问题定位清晰
- 方案阐述清晰
- 差异化突出,和其他方案、竞对的优势
- 收益可度量
- 逻辑:逻辑顺畅
- 通过严密的推导证明所选的方案是符合要求的、最优的
- 呈现:呈现清晰,观点明确
- 简单易懂,将重要观点着重标识和强调,观点之间要有关联关系,让人容易抓住重点
- 问答:汇报最后的问答环节
- 汇报的步骤
- 汇报前
- 对齐目标:开头标明背景和目标,结尾列好汇报后的行动计划(行动内容、负责人、时间)
- 准备内容
- 逻辑清晰,按金字塔结构组织内容,形成一个结构化的目录
- 重点突出,先讲结论再讲过程(节约时间提升效率,跟着领导关心的问题来做解释)
- 简洁易懂,少即是多
- 问答预案,准备可能的问题和答案
- 汇报中:声音,节奏(详略得当)
- 汇报后:纪要明确,落实跟进
- 汇报结束的时候,第一时间对会议纪要进行核实,确定自己的理解和最重要的内容、行动能落实。
MySQL_慢SQL调优总结
MySQL 慢SQL调优总结
敏捷革命
为什么需要Scrum
传统方法(主要是瀑布法)效率不足且经常引起项目最终无法交付。
Scrum团队
团队效率的提升比个人能力的提升对项目完成的影响更大
卓越团队的特点:
- 明确的目标
他们具有希望超越寻常的目标。实现这种目标的动力促使他们超越寻常,达到卓越。他们下决心拒绝平庸,出类拔萃,这种决定改变了他们看待自己的方式,扩大了他们的能力范围。 - 自主决策能力
这种团队自我组织,自我管理,有能力决定如何开展工作,并获得了根据自己决定做事的授权。 - 多功能
这些团队具备完成项目的所有技能:计划、设计、生产、销售、分销。具有这些技能的成员相互学习,相互提高。一位设计革命性新款相机的团队成员说:“当所有团队成员都在一间大房子里办公时,某个人的信息就是你的信息,并且得来全不费功夫。你会开始思考对整个团体而言,最优选择或次优选择是什么,而不再仅仅从你个人的角度考虑问题。”
每个团队成员都具备完成工作所需的各种技能,而不严格划分每个成员的角色,如果严格划分角色,不同角色间交流情报时就会容易产生误差。 - 透明度高、注重信息分享
- 团队规模
如果团队规模过大,沟通渠道增多会带来更大的沟通成本。
Scrum团队倾向于让每个成员都知道其他人在做什么,每个人正在做什么工作,正面临哪些挑战,取得了哪些进步等等,都是透明的。团队规模过大会影响沟通效果,进而导致团队分裂成小团体,以至于多功能的团队就不复存在了。 - Scrum Master
制订工作框架:冲刺、每日立会、检查与回顾。
Scrum Master负责确保整个工作流程的顺利推进,他的工作职责是召集会议,确保团队运作过程的透明度,为团队发现障碍,并持续改进。 - 工作制度
不要把问题归咎于某一个人,而是寻求制度上的解决方案。
周期
- 冲刺
冲刺指的是项目中的一个小的迭代周期,叫冲刺会比较有紧张感。
每个周期固定时间审视一下这个周期内团队成员做的成果
冲刺周期是固定的,有固定期限可以让团队成员方便评估自己的节奏在每个周期能做多少事情,并且不允许团队之外的任何人给团队内成员增加任务。 - 每日立会
了解这个冲刺周期内各项任务的进展状况,有没有障碍,需不需要其他人来帮忙;团队的一切任务都是自主决定、自主完成的,不需要汇报。
时间不宜过长,不应给团队带来负担。
Scrum Master每日问3个问题示例:
- 你昨天做了什么去帮助团队完成冲刺;
- 今天你打算做什么来帮助团队完成冲刺;
- 什么因素阻碍了团队的前进之路?
每日立会规则:
一、每天会议召开的时间是固定的,每个成员都要出席;
二、开会时间不能超过15分钟,每次开会都直击重点,如果有事情需要进一步讨论,可以先记录下来,在每日立会结束之后再做进一步的讨论;
三、每个人都要积极参与,尽量让每个人都站起来开会。
避免浪费(人力)
- 一次只做一件事
研究报告指出,哪些最喜欢同时执行多项任务的人自制能力相对较弱,没有办法让自己长时间集中精力。
同时执行多项任务一般不会加快速度,反而会拖累。 - 一次把事情做完
Scrum开发过程中的工作是有节奏的。每一个迭代期,或者说每一个冲刺期,团队都试图完成很多事情。但是“完成”意味着一款能被消费者使用的、完整的、可交付的产品。如果在迭代期的最后,事情只做了一半,你将比一点都没开始做更糟糕。你花费了资源,付出了努力和时间,最后没有得到任何成果。
一次把事情做对
如果你出了一个错误(我们都会出错),那就在发现错误时立即修改,不然就会付出代价。
生产流程应该是持续改进的,而处理问题的最佳时机是你发现问题的时候,而不是发现问题之后很久再着手解决。
出现问题不立即修复,而是放到很久之后,会浪费更多时间:当你在做一个项目的时候,大脑专注于它,你很清楚做某件事的所有原因,这时你的脑子里存在一个与之相关的复杂架构,想在几个星期后重新建立这样的架构十分困难,会花费更多时间。
工时越长,效率越低
工作时间太长的人会开始犯错,而改正错误可能会比创造新成绩花费更多的时间。工作超出负荷的员工比较不容易集中注意力,而且会影响别人也跟着分心,不久之后他们就会开始做出错误决策。
这意味着我们更应该关注完成任务的时长和质量而不是工时长短。
确保工作的合理性
有几种不合理现象:
1、目标荒谬、不切实际
2、期待过高
3、负担过重,比如繁琐的规定、没必要的汇报、会议等过多
4、情绪浪费,比如团队中某个人倾向于激怒别人、削弱团队斗志。
周期规划会
给项目划分任务
确立优先级:由产品负责人决定优先级
确定需要花费多少精力、时间和资金。怎么知道自己的速度?每个成员冲刺周期结束时复盘可以知道自己的效率如何,并且可以通过消除障碍来变得更快
让执行团队评估自己的工作
用用户故事描绘任务:角色、活动、商业价值
用户故事必须完整:独立性、可协商性(不要带太多细节)、有价值、可评估、规模小、可测试
用户故事来源:需要产品负责人拿出一半时间与购买产品的客户开展对话(了解客户对于最新产品的看法,看看自己的产品是否为客户创造了价值),还要拿出一半时间拟定待办事项清单(让团队成员知道客户重视什么、不重视什么)。
产品负责人的特点
- 第一,产品负责人需要在相关领域内掌握丰富的专业知识。
- 第二,产品负责人必须获得自主决策权。
- 第三,产品负责人必须有足够的时间与团队成员接触,向团队成员解释清楚需要做什么以及为什么要这么做。
- 第四,产品负责人必须为价值负责。
信息瀑布:人们倾向于遵从之前众人的行为 - 别人的评估意见只能拿来作为参考,以便改进自己的判断,而不是完全取代自己的判断。
光环效应:是指当认知者对一个人的某种特征形成好或坏的印象后,还倾向于据此推论该人其他方面的特征,本质上属于以偏概全的认知错误 - 评估时保证匿名性,减少互相影响
拥抱变化:一般最初的计划评估不会完美,关键在于,要在项目执行过程中及时加以调整和改进,而不是刻板地遵循计划。详细规划出能够创造出新价值的部分,至于项目中的剩余部分,计划粗略一些也无所谓。每个冲刺周期结束之际,都必须为顾客展示一些看得见、摸得着的新价值。你可以问顾客一些问题,比如,这是你要的吗?这能帮你解决一些问题吗?我们的方向是对的吗?如果答案是否定的,那么你就要修改你的计划。
二八原则
往往20%的功能可以覆盖80%的价值
1、根据产品负责人对需求优先级的排列可以确定最重要的那部分需求
2、先做最重要的MVP部分,以期快速得到市场反馈,在此基础上检查和调整产品
风险
Scrum的目的之一是降低项目研发过程中的风险,常见的风险是市场风险、技术风险和财务风险。
市场风险:Scrum注重渐进式迭代,每个周期通过show case将产品展示给客户,收集用户意见,因此可以实时对产品做出小改动,不必等到投入大量成本后再被迫做出改动。
技术风险:先做几种原型,实际加以比较。
财务风险:怎么发现自己做的产品能挣到钱?渐进式迭代+showcase
Neo4j学习
建模
图数据结构
属性图结构
- 包含节点和边,同时节点和边上又有属性property和标签label
- 边有名字和方向
图数据库查询语言
- Cypher
应用于Neo4j、GDB等 - Gremlin
应用于GDB
跨域模型
在节点和关联关系不是很复杂的情况下,我们建的图通常只有一个领域的内容,比如人与人之间的关联图谱。但是随着业务的发展,我们会觉得单一的人物关系不能满足我们的使用需求,我还希望加入企业注册数据,来进行企业与人之间的管理分析。随后,我们陆续加入了法律诉讼信息、新闻资讯信息等,这样我们的图从一张小图变成了大图,也从只有一个领域(人)的模型变成了多个领域的跨域模型。
跨域模型有助于我们理解复杂的价值链背后的关联,不仅可以联合多个领域,而且每个领域的内容又能单独区分开来。这里主要借助了图数据里的2个概念:属性图和标签。属性图模型让不同的领域很容易联系起来,这样每个域都是可达的;标签既能表示不同节点在域中扮演的角色,又可以让我们将它归属的节点和元数据结合起来。
面向查询设计
建模其实就是利用图结构来描述问题的过程,为了使我们的模型更接近业务需求,有一个方法,叫做面向查询设计:
- 将需求转化为领域问题
- 明确领域内出现的节点和关系
- 把这些节点和联系翻译成查询语言
- 使用路径表达式,描述需要解决的问题
使用图查询语言构建数据模型
1 | # 创建带有属性name和age的People节点 |
参考
RocketMQStream学习
架构
- 采用 shared-nothing 的分布式架构设计,依赖消息队列做负载均衡和容错机制,单实例可启动,增加实例实现能力扩展,并发能力取决于分片数;
其实就是stateless - 利用消息队列的分片做 shuffle,利用消息队列负载均衡实现容错;
- 利用存储实现状态备份,实现 Exactly-ONCE 的语义。用结构化远程存储实现快速启动,不等本地存储恢复;
- 重力打造过滤优化器,通过前置指纹过滤,同源规则自动归并,hyperscan 加速,表达式指纹提高过滤性能
RocketMQ Streams消费一条消息的过程
ISource
消费数据源
触发条件:
分类:
RocketMQSource
读取来自RocketMQ的消息
流程(RocketMQSource
):
1.
IStreamOperator
算子处理来自Source的数据
触发条件:
AbstractSource
处理消息AbstractSource#executeMessage
ISink
存储数据
触发条件:
SinkAction
算子触发
流程(SinkAction
):
- 默认写到cache
IMessageCache#addCache
触发时机:接收消息时SinkAction#doMessage
- 启动自动flush
ISink#openAutoFlush
触发时机:刷新配置后的处理SinkAction#doProcessAfterRefreshConfigurable
触发逻辑:把队列排空,并写入到存储中MessageCache#flush()
触发间隔:100msScheduleManager#start
shared-nothing
shared-nothing体现在RocketMQ的以下属性:
- 消息的存储采用Topic+Queue的模式;
- Consumer端消费采取pull模式而不是push;
- Consumer端负载均衡Rebalance,同时Rebalance也可以实现容错;
RocketMQ 消息的存储和查询原理
RocketMQ 如何发送一条消息
负载均衡
RocketMQ Streams在启动时会对上游的ISource拆分分片,AbstractPullSource#startSource
- 获取所有分片
IPullSource#fetchAllSplits
- 拆分分片
ISourceBalance#doBalance
- 定时监听分片的变更
AbstractPullSource#doSplitChanged