diff --git "a/\345\205\245\351\227\250/\347\273\217\345\205\270\347\256\227\346\263\225TS\345\256\236\347\216\260.md" "b/\345\205\245\351\227\250/\347\273\217\345\205\270\347\256\227\346\263\225TS\345\256\236\347\216\260.md" index 4bdb992..db68628 100644 --- "a/\345\205\245\351\227\250/\347\273\217\345\205\270\347\256\227\346\263\225TS\345\256\236\347\216\260.md" +++ "b/\345\205\245\351\227\250/\347\273\217\345\205\270\347\256\227\346\263\225TS\345\256\236\347\216\260.md" @@ -110,8 +110,8 @@ const mergeSort = (nums: number[], left: number, right: number) => { ```tsx const quickSort = (nums: number[], start: number, end: number) => { - let left = start, - right = end + let left = start + let right = end const pivot = nums[start] while (left < right) { while (left < right && nums[right] > pivot) { @@ -123,7 +123,7 @@ const quickSort = (nums: number[], start: number, end: number) => { if (nums[left] === nums[right] && left < right) { left++ } else { - ;[nums[left], nums[right]] = [nums[right], nums[left]] + [nums[left], nums[right]] = [nums[right], nums[left]] } } if (start < left - 1) { diff --git "a/\345\237\272\347\241\200\347\256\227\346\263\225\347\257\207/\345\212\250\346\200\201\350\247\204\345\210\222.md" "b/\345\237\272\347\241\200\347\256\227\346\263\225\347\257\207/\345\212\250\346\200\201\350\247\204\345\210\222.md" index 6a7ca77..ac55938 100644 --- "a/\345\237\272\347\241\200\347\256\227\346\263\225\347\257\207/\345\212\250\346\200\201\350\247\204\345\210\222.md" +++ "b/\345\237\272\347\241\200\347\256\227\346\263\225\347\257\207/\345\212\250\346\200\201\350\247\204\345\210\222.md" @@ -79,7 +79,7 @@ console.log(minimumTotal(tringle)); //11 `f(i,j)=min(f(i+1,j),f(i+1,j+1))+triangle[i][j]` -```js +```tsx var minimumTotal = function(tringle){ let row = tringle.length; let dp = new Array(row+1).fill(0); @@ -90,6 +90,20 @@ var minimumTotal = function(tringle){ } return dp[0]; } + +function minimumTotal(triangle: number[][]): number { // 时间、空间复杂度O(n2) + const len = triangle.length + const ans: number[][] = new Array(len).fill(0).map(() => new Array(len).fill(0)) + ans[0][0] = triangle[0][0] + for (let i = 1; i < len; i++) { + ans[i][0] = ans[i - 1][0] + triangle[i][0] + for (let j = 1; j < triangle[i].length; j++) { + ans[i][j] = Math.min(ans[i - 1][j], ans[i - 1][j - 1]) + triangle[i][j] + } + ans[i][i] = ans[i - 1][i - 1] + triangle[i][i] + } + return Math.min(...ans[len - 1]) +}; ``` ## 递归和动规关系 @@ -104,7 +118,7 @@ Function(x) { } ``` -动态规划:是一种解决问题的思想,大规模问题的结果,是由小规模问 题的结果运算得来的。动态规划可用递归来实现(Memorization Search) +动态规划:是一种解决问题的思想,大规模问题的结果,是由小规模问题的结果运算得来的。动态规划可用递归来实现(Memorization Search)。 ## 使用场景 @@ -127,7 +141,7 @@ Function(x) { 2. 方程 Function - 状态之间的联系,怎么通过小的状态,来算大的状态 3. 初始化 Intialization - - 最极限的小状态是什么, 起点 + - 最极限的小状态是什么, 起点 4. 答案 Answer - 最大的那个状态是什么,终点 @@ -299,14 +313,6 @@ function jump(nums: number[]): number { //从前往后推 给你一个字符串 `s`,请你将 `s` 分割成一些子串,使每个子串都是回文。返回符合要求的 最少分割次数 。 -```tsx - -``` - -##### [300. 最长递增子序列](https://leetcode-cn.com/problems/longest-increasing-subsequence/) - -给你一个整数数组 `nums` ,找到其中最长严格递增子序列的长度。 - ##### [300. 最长递增子序列](https://leetcode-cn.com/problems/longest-increasing-subsequence/) 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 diff --git "a/\350\256\272\346\226\207/image/baas+faas.png" "b/\350\256\272\346\226\207/image/baas+faas.png" deleted file mode 100644 index bd44cfc..0000000 Binary files "a/\350\256\272\346\226\207/image/baas+faas.png" and /dev/null differ diff --git "a/\350\256\272\346\226\207/image/serverless\351\200\202\347\224\250\347\211\271\345\276\201.png" "b/\350\256\272\346\226\207/image/serverless\351\200\202\347\224\250\347\211\271\345\276\201.png" deleted file mode 100644 index 703913a..0000000 Binary files "a/\350\256\272\346\226\207/image/serverless\351\200\202\347\224\250\347\211\271\345\276\201.png" and /dev/null differ diff --git "a/\350\256\272\346\226\207/image/workflows.png" "b/\350\256\272\346\226\207/image/workflows.png" deleted file mode 100644 index 7697972..0000000 Binary files "a/\350\256\272\346\226\207/image/workflows.png" and /dev/null differ diff --git "a/\350\256\272\346\226\207/image/\345\206\267\347\203\255\345\220\257\345\212\250.png" "b/\350\256\272\346\226\207/image/\345\206\267\347\203\255\345\220\257\345\212\250.png" deleted file mode 100644 index cd7b80c..0000000 Binary files "a/\350\256\272\346\226\207/image/\345\206\267\347\203\255\345\220\257\345\212\250.png" and /dev/null differ diff --git "a/\350\256\272\346\226\207/image/\345\256\271\345\231\250\351\205\215\347\275\256\345\215\217\350\256\256.png" "b/\350\256\272\346\226\207/image/\345\256\271\345\231\250\351\205\215\347\275\256\345\215\217\350\256\256.png" deleted file mode 100644 index ecc0180..0000000 Binary files "a/\350\256\272\346\226\207/image/\345\256\271\345\231\250\351\205\215\347\275\256\345\215\217\350\256\256.png" and /dev/null differ diff --git "a/\350\256\272\346\226\207/serverless\347\254\224\350\256\260.md" "b/\350\256\272\346\226\207/serverless\347\254\224\350\256\260.md" deleted file mode 100644 index 7240609..0000000 --- "a/\350\256\272\346\226\207/serverless\347\254\224\350\256\260.md" +++ /dev/null @@ -1,166 +0,0 @@ -## 1.1 what - -Serverless定义 - -> Serverless(无服务器架构)是指服务端逻辑由开发者实现,运行在无状态的计算容器中,由事件触发,完全被第三方管理,其业务层面的状态则存储在数据库或其他介质中。 -> -> Serverless 是云原生技术发展的高级阶段,可以使开发者更聚焦在业务逻辑,而减少对基础设施的关注。 - -狭义上:Serverless = FaaS + BaaS - -![baas+faas](./image/baas+faas.png) - -**BaaS** - -BaaS(Backend as a Service)后端即服务,一般是一个个的API调用后端或别人已经实现好的程序逻辑,比如身份验证服务Auth0,这些BaaS通常会用来管理数据,还有很多公有云上提供的我们常用的开源软件的商用服务,比如亚马逊的RDS可以替代我们自己部署的MySQL,还有各种其它数据库和存储服务。 - -**FaaS** - -FaaS(Functions as a Service)函数即服务,FaaS是无服务器计算的一种形式,当前使用最广泛的是AWS的Lambada。FaaS本质上是一种事件驱动的由消息触发的服务,FaaS供应商一般会集成各种同步和异步的事件源,通过订阅这些事件源,可以突发或者定期的触发函数运行。 - -广义上:Serverless = 服务端免运维 = 具备 Serverless 特性的云服务 - -## 1.2 why - -云计算的基础设施外包带来五大好处: - -- 降低人工成本 -- 降低风险 -- 降低基础设施成本 -- 扩展性 -- 交付时间 - -Serverless 同样也有这五大优点, 前四个都或多或少是关于成本节约的。但是,Serverless最大的好处是,它减少了从新的想法到实施上线的时间,换句话说,它能够让你更快地创新。 - -### 降低人力成本 - -不需要再自己维护服务器,操心服务器的各种性能指标和资源利用率,而是关心应用程序本身的状态和逻辑。而且serverless应用本身的部署也十分容易,不需使用Puppet、Chef、Ansible或Docker来进行配置管理,降低了运维成本。同时,对于运维来说,也不再需要监控那些更底层的如磁盘使用量、CPU使用率等底层和长期的指标信息,而是监控应用程序本身的度量,这将更加直观和有效。 - -### 降低风险 - -对于组件越多越复杂的系统,出故障的风险就越大。使用BaaS或FaaS将它们外包出去,让专业人员来处理这些故障,比自己来修复更可靠,利用专业人员的知识来降低停机的风险,缩短故障修复的时间,让系统稳定性更高。 - -### 减少资源开销 - -在申请主机资源一般会评估一个峰值最大开销来申请资源,往往导致过度的配置,这意味着即使在主机闲置的状态下也要始终支付峰值容量的开销。对于某些应用来说这是不得已的做法,比如数据库这种很难扩展的应用,而对于普通应用这就显得不太合理了,虽然都觉得即使浪费了资源也比当峰值到来时应用程序因为资源不足而挂掉好。 - -解决这个问题最好的办法就是,不计划到底需要使用多少资源,而是根据实际需要来请求资源,当然前提必须是整个资源池是充足的(公有云显然更适合)。根据使用时间来付费,根据每次申请的计算资源来付费,让计费的粒度更小,将更有利于降低资源的开销。这是对应用程序本身的优化,例如让每次请求耗时更短,让每次消耗的资源更少将能够显著节省成本。 - -### 增加缩放的灵活性 - -以AWS Lamba为例,当平台接收到第一个触发函数的事件时,它将启动一个容器来运行你的代码。如果此时收到了新的事件,而第一个容器仍在处理上一个事件,平台将启动第二个代码实例来处理第二个事件。AWS lambad的这种自动的零管理水平缩放,将持续到有足够的代码实例来处理所有的工作负载。 - -但是,AWS仍然只会向您收取代码的执行时间,无论它需要启动多少个容器实例要满足你的负载请求。例如,假设所有事件的总执行时间是相同的,在一个容器中按顺序调用Lambda 100次与在100个不同容器中同时调用100次Lambda的成本是 一样的。当然AWS Lambada也不会无限制的扩展实例个数,如果有人对你发起了DDos攻击怎么办,那么不就会产生高昂的成本吗?AWS是有默认限制的,默认执行Lambada函数最大并发数是1000。 - -### 缩短创新周期 - -小团队的开发人员正可以在几天之内从头开始开发应用程序并部署到生产。使用短而简单的函数和事件来粘合强大的驱动数据存储和服务的API。完成的应用程序具有高度可用性和可扩展性,利用率高,成本低,部署速度快。 - -## 1.3 how - -### 适用特征 - -Serverless框架的适用特征有以下几方面: - -![](./image/serverless适用特征.png) - -### 应用场景 - -1. 应用程序后端 - 小程序 -2. 计划任务 - 定时备份 -3. 数据处理操作 - 图文转换、AI学习 -4. 强弹性计算 - 电商促销、社交直播 - -### 应用示例 - -#### 1、社交/电商类应用中压缩图片 - -场景介绍 - -用户通过客户端或移动设备上传图片,图片进行不同分辨率的压缩已适应不同设备,亦或需要增加水印,生成缩略图等。通过事件触发处理函数执行,无需为函数保留资源。 - -主要处理步骤为: - -- 将图片上传到指定的对象存储桶中 -- 将用户上传的每个图像的尺寸进行压缩或者图片打水印 -- 将处理完后的图像上传到另一个指定的对象存储桶中 - -#### 2、简易中文信息过滤 - -场景介绍: - -用分布式消息服务来存储一些重要信息。需要对消息进行处理,判断消息是否适合发布(有些消息不适合发布,例如政治敏感、广告等)。业务爆发时可以自动调度资源运行更多函数实例以满足处理需求。 - -主要处理步骤为: - -- 使用DMS服务,在其中创建消息队列,同时在队列中创建消费组,并生产消息。 -- 在函数服务中,创建函数,为函数创建DMS触发器,通过轮询的方式,获取DMS队列中的信息。 -- 在函数中,通过对读取信息进行处理,判断信息是否敏感,是否符合发布 - -#### 3、由事件触发的批量数据处理 - -场景介绍: - -间隔执行或定时触发的ETL任务。或机器学习训练数据集预处理,例如游戏AI训练。只有对函数处理文件数据的时间进行计费,无需购买冗余的资源用于非峰值处理 - -主要处理步骤为: - -- 数据汇集到指定的对象存储桶中 -- 将处理过程的mapreduce按照角色拆分成多个函数 -- 处理完后的结果存储至缓存数据库供聚合 -- 使用函数服务聚合结果后传到另一个指定的对象存储桶中 - -图片:serverless实践一文 - -## 1.4 weakness - -### 状态管理 - -要想实现自由的缩放,无状态是必须的,而对于有状态的服务,使用serverless这就丧失了灵活性,有状态服务需要与存储交互就不可避免的增加了延迟和复杂性。 - -### 延迟 - -应用程序中不同组件的访问延迟是一个大问题,我们可以通过使用专有的网络协议、RPC调用、数据格式来优化,或者是将实例放在同一个机架内或同一个主机实例上来优化以减少延迟。 - -而serverless应用程序是高度分布式、低耦合的,这就意味着延迟将始终是一个问题,单纯使用serverless的应用程序是不太现实的。 - -### 本地测试 - -Serverless应用的本地测试困难是一个很棘手的问题。虽然可以在测试环境下使用各种数据库和消息队列来模拟生产环境,但是对于无服务应用的集成或者端到端测试尤其困难,很难在本地模拟应用程序的各种连接,并与性能和缩放的特性结合起来测试,并且serverless应用本身也是分布式的,简单的将无数的FaaS和BaaS组件粘合起来也是有挑战性的。 - -# 二、常见平台框架 - -平台和框架的多样性导致Serverless没有形成标准化,平台商一般根据自己理解来实现,就会造成了迁移成本很大,存在厂商锁定等问题。 - -2018.7月,谷歌站了出来,携手IBM、RedHat 等各大佬发布起了开源**Kantive项目**,**目标将Severless 标准化,与云平台无关,他提供搭建Severless的能力**,而不是提供Severless平台。 - -推荐本书:[Knative 入门.pdf](https://gw.alipayobjects.com/os/basement_prod/6fb694c1-9637-4caf-a64b-01271e919a98.pdf) - -在Knative构建Severless 生态由哪些组成? 分别是 - -- 底层的kubernetes,即k8s ( 中间8个字母), 是**容器编排的标准**,即管理docker容器部署的 -- 在上层即Knative, 将定义**源码到构建到部署到管理的标准**,下层通过k8s进行容器部署管理 -- 在上层是Istio, 它定位为**服务网格标准**,它的目标将服务治理之间的网络通信变成底层的基础设施,与语言无关 - -Knative内部生态有三大组件组成,分别是: - -- [Build](https://github.com/knative/build) **负责提供标准模板,从源码仓库到镜像构建到镜像仓库(PS:在v0.8.0后由Tekton Pipelines项目替代)** -- [Eventing](https://github.com/knative/eventing) **服务事件驱动,将服务绑定到事件,对发布/订阅进行抽象** -- [Serving](https://github.com/knative/serving) **动态调整工作负载流量版本切分,还有log/metrics/tracing/monitor模块** - - - - - - - - - -## FaaS 运行机制 - -代码下载-->启动容器-->初始化环境(前三个阶段冷启动)-->运行代码(热启动) - -热启动执行上下文重用(实例复用),需要保证云函数无状态性,即当前运行的函数不能依赖上个函数运行时的残留信息。 - -![](./image/冷热启动.png) - diff --git "a/\350\256\272\346\226\207/\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\346\232\202\345\255\230\357\274\211.md" "b/\350\256\272\346\226\207/\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\346\232\202\345\255\230\357\274\211.md" deleted file mode 100644 index d9a2bdc..0000000 --- "a/\350\256\272\346\226\207/\345\255\246\344\271\240\347\254\224\350\256\260\357\274\210\346\232\202\345\255\230\357\274\211.md" +++ /dev/null @@ -1,7 +0,0 @@ -rpc(远程过程调用),服务不是都在一个服务器上,如果使用不同的网络请求过于复杂。通过 RPC 可以帮助我们调用远程计算机上某个服务的方法,这个过程就像调用本地方法一样简单。 - -https://snailclimb.gitee.io/javaguide/#/docs/system-design/distributed-system/rpc/Dubbo - - - -serverful --> serverless diff --git "a/\350\256\272\346\226\207/\350\256\272\346\226\207FaaSNet-ali.md" "b/\350\256\272\346\226\207/\350\256\272\346\226\207FaaSNet-ali.md" deleted file mode 100644 index e69bf92..0000000 --- "a/\350\256\272\346\226\207/\350\256\272\346\226\207FaaSNet-ali.md" +++ /dev/null @@ -1,83 +0,0 @@ -### 1、介绍 - -无服务器计算允许开发人员将传统的基于服务器的单体应用程序分解为更细粒度的云功能,从而实现了一种构建和扩展应用程序和服务的新方法。程序员编写业务逻辑,云服务提供商提供配置、扩展、管理运行功能。 - -目前流行的打包部署云函数是使用自定义镜像,它极大的增强了可用性、可移植性和工具支持。(1)机器学习、数据分析、视频处理,限制他们的包大小是不现实的(aws lambda 限制上传的包大小为250m)(2)docker容器(3)DevOps功能,增量更新等。 - -FaaS平台最具吸引力的是资源弹性,允许用户程序在几秒内按需扩展到几万个云功能,者对基于自定义容器的FaaS基础设施提供快速容器配置的挑战很大。当前的FaaS提供商在应对突发流量时,扩展容器要复制当前容器几百上千个,工作负载导致网络贷款瓶颈,高弹性时噱头。其次,docker容器大,从后备存储提取会有明显的冷启动延迟,处于高争用状态。 - -现在的解决方案不行,Kraken,DADI使用点对点 (P2P) 方法来加速大规模容器配置,然而,它们需要一个或多个专用的、强大的服务器作为根节点来进行数据播种、元数据管理和协调。 - -阿里的方案行,FAASNET是一种用于加速无服务器容器配置的轻量级自适应中间件系统。FAASNET 通过将容器配置过程分散到以基于功能的树状结构组织的主机 VMs 之间来实现高可扩展性。功能树(FT)是一个逻辑的、基于树的网络覆盖。 FT 由多个主机 VM 组成,并允许以可扩展的方式跨所有 VM 分配容器运行时的代码包。FAASNET 通过动态适应 FT 拓扑的树平衡算法实现高适应性,以适应 VM 的加入和离开。 - -一个典型的FaaS VM池有数千个小型VM实例。FaaSNet很快,在8.3秒内完成2500个功能容器的配置(仅比配置单个容器的时间长1.6倍),比目前P2P注册中心快十几倍。 - -### 2、背景及意义 - -2.1 工作流 - -![](./image/workflows.png) - -2.2 工作负载分析 - -2.2.1 工作负载激增 优势:按需收费。分析吞吐量峰值。 - -2.2.2 冷启动 需要获取镜像数据,延迟很长,分析了北京上海的容器下载成本日志 - -### 3、FaaSNet 设计 - -3.1 设计 - -FAASNET 分散和并行化了跨 VM 的容器配置。FAASNET 引入了一种称为功能树 (FT) 的抽象,以实现高效的大规模容器配置。FAASNET将一个FT管理器组件和一个工作器组件集成到我们现有的FaaS调度程序和 VM 代理中,以进行协调的FT管理。 - -调度器通过FT的插入和删除API来管理功能树。FT是一个二叉树,连接多个主机VM形成一个容器配置网络。每个VM运行一个FaasVM代理,负责VM本地功能管理。将一个FaaSNet工作线程集成到VM代理中执行容器配置任务。 - -在函数调用路径中,有空闲的VM就分配,没有的话调度程序查询其本地FT元数据并发送RPC对FT的faasnet的请求,以启动容器配置过程 。 - -函数部署路径上,从容器注册表中提取常规图像,逐块压缩图像层,创建包含格式相关信息的元数据文件。 - -3.2 函数树 - -1)一个函数有一个单独的FT,2)FTs解耦数据平面和控制平面,3)FaaSNet采用平衡二叉树,动态适应工作负载。 - -以函数粒度管理树。平衡二叉树,每个树节点都有一个传入边和两个传出边,可以有效地限制每个VM的并发下载操作次数。高度log2N,高度会影响数据传播效率,FT管理器调用插入和删除API动态增长或缩小FT。 - -3.3 函数树集成 - -将FT方案集成到阿里云FaaS平台,FaaSNet worker负责:1)服务调度程序的命令执行镜像下载和容器供应。2)管理虚拟机功能容器。 - -FT元数据管理:内存映射表,FT数据结构管理功能和VM的信息。 - -函数运行在VMs上:FaaSNet允许一个虚拟机保存同一个用户多个函数。函数计算使用装箱启发式算法,该试验限制了vm上放置的function数量为20。 - -容器配置协议:在调用请求中,如果调度器检测到没有足够的VM服务请求,或者是当前所有的VMs都很忙,会在空闲的VM池里启动一个或者多个VMs进入容器配置流程。假定VM1是新建的,需要下载配置信息及镜像,VM2是给VM1提供的容器。 - -![](./image/容器配置协议.png) - -FT容错:如果VM关闭了,调度器会通知FT管理器去调整FT的结构拓扑。 - -3.4 FT设计讨论 - -FaaSNet将繁重的元数据管理任务卸载到现有的FaaS调度程序,使每个单独的FT节点都充当从其父节点获取数据的相同角色(如果有子节点)。FaaSNet设计至少有一个活动VM。 - -现在的容器分布技术依赖强大的根节点来完成任务,包括数据采集,元数据管理和P2P拓扑管理,FaaSNet设计的FT,保持VM工作的简单,将所有的函数流程卸载到调度器。这种设计消除了网络I/O瓶颈和跟节点瓶颈。 - -3.5 优化 - -I/O高效数据格式:常规的镜像拉取和启动时低效耗时的,本文设计了一种基于块的图像获取机制,将原始数据分割成固定大小的块并进行压缩,偏移表记录块的偏移量,一个code packages被压缩成二进制文件,由VM代理提取并装入函数容器中。 - -按需IO:按需加载,从元数据中下载图像压缩清单,解压缩算法比块存储和网络传输好。 - -RPC和数据流:构建了一个用户级,零copy的RPC库,实现请求流水化和无序接受,类似http2的多路复用。 - -### 4、实验评估 - -4.1 实验环境 - -部署了两个规模的资源池:500vm,1000vm。每个vm实例2CPUs,4GB内存,1Gbps网络带宽,FaaSNet使用512KB的块进行按需提取和流式传输。使用Python3.8运行程序2s,程序容器镜像758MB,函数使用3008MB内存,每个VM运行一个容器化函数。 - -将FaaSNet与kraken,baseline,on-demand,DADI+P2P进行比较。 - -4.2 FaaS应用工作负载 - -进程和启动:对比物联网应用和游戏应用。