MapReduce 阅读笔记

1. 引言(Introduction) 我们意识到,我们的大部分计算都涉及对输入中的每个逻辑 “记录” 应用 map 操作,以便计算一组中间键 / 值对,然后将 reduce 操作应用于共享同一键的所有值,以便适当地组合派生数据。我们使用具有用户指定 map 和 reduce 操作的函数模型,使我们能够轻松地并行化大型计算,并使用重新执行作为容错的主要机制。 这项工作的主要贡献是一个简单的和强大的接口,可实现自动并行化和大规模计算的分布,结合起来使用此接口的实现大型商用PC集群上的高性能。 2. 编程模型(Programming Model) Map 和 Reduce 的定义与功能 Map(映射):是由用户编写的函数,它接受一个输入键值对,然后对输入数据进行处理,产生一组中间键值对。例如在单词计数的例子中,Map 函数会读取文档内容(值),将文档中的每个单词作为键,“1” 作为值,输出一系列 < 单词,“1”> 这样的中间键值对,表示每个单词出现了一次。其作用是将大规模数据的处理分解为对每个独立数据块(逻辑 “记录”)的操作,为后续的合并处理提供基础数据。 Reduce(归约):同样由用户编写,它接受一个中间键以及与该键相关联的一组值。Reduce 函数的主要任务是将具有相同键的值进行合并处理,通常是将这些值进行某种计算(如求和、连接等),最终生成可能更小的一组值,一般每个 Reduce 调用产生零个或一个输出值。以单词计数为例,Reduce 函数会接收一个单词(键)和该单词对应的所有计数(值的列表),然后将这些计数相加,得到该单词的总出现次数,输出 <单词,总次数> 这样的键值对。Reduce 操作实现了对中间数据的合并和聚合,从而得到最终想要的结果形式。 Map 和 Reduce 函数共同构成了 MapReduce 编程模型的核心,通过这种分而治之的方式,能够在大规模集群上高效地处理海量数据。 典型使用案例(如单词计数) 大型文档集合中每个单词的出现次数的问题 // key: document name // value: document contents map(String key, String value): for each word w in value: EmitIntermediate(w, "1"); // key: a word // values: a list of counts 迭代器,用于遍历与该单词相关联的所有计数 reduce(String key, Iterator values): int result = 0; for each v in values: result += ParseInt(v); Emit(AsString(result)); map: 遍历文档内容中的每个单词w。对于每个单词,使用EmitIntermediate(w, "1")发出一个中间键值对,其中键是单词w,值是字符串"1"。这表示该单词在当前文档中出现了一次(以简单的计数为 1 来表示每次出现)。...

December 29, 2024 · 4 min · 792 words · Similarityoung

解决问题的思路

总体纲领 在coding之前 我们需要先有个draft(草案) 包含 背景 约束条件 设计的目的与折中 存在的问题以及改进这四个部分 背景 目标: 精准复现、定位并理解技术问题的本质、影响范围及业务上下文。 关键活动: 问题复现与场景描述 (Reproduce & Describe): 复现路径: 明确稳定复现问题的具体步骤、输入和环境(开发、测试、生产环境;特定用户/数据)。 异常表现: 清晰描述“不符合预期”的具体行为,包括错误日志、监控指标异常(延迟、错误率、资源使用率)、UI/API 表现等。 预期行为: 明确在同样场景下,系统 应该 表现出什么样的行为。 根因分析 (Root Cause Analysis - RCA): 信息收集: 收集相关日志、Metrics、Traces、Dump 文件、配置信息、代码版本、变更历史。 关联分析: 分析时间线,将问题现象与系统变更、流量波动、依赖服务异常等进行关联。 假设与验证: 提出可能的根因假设,并通过调试、日志分析、实验等手段进行验证或排除。 影响评估 (Impact Assessment): 业务影响: 评估问题对用户、业务流程、收入、SLA/SLO 的具体影响。 技术影响: 评估问题对系统其他模块、数据一致性、安全性的潜在影响。 现状审视 (Review Current State): 审视当前代码库、架构设计、技术文档中与问题相关部分。 了解是否存在已知的类似问题或临时的 Workaround。 产出: 一份详尽的 技术问题分析报告 (Technical Problem Report / RCA Report),包含复现步骤、根本原因、影响范围和相关证据。 约束条件 目标: 明确解决方案必须遵守的技术边界和需要达成的技术/业务指标。 关键活动: 识别技术约束 (Identify Technical Constraints): 平台/语言/框架: 必须使用的编程语言、框架、操作系统、云平台等。 架构/兼容性: 必须兼容的现有系统架构、API 接口、数据格式、老版本等。 资源限制: CPU、内存、存储、网络带宽、预算等硬性限制。 规范/安全: 必须遵守的编码规范、安全标准、合规要求。 定义技术目标 (Define Technical Goals): 功能性目标: 解决方案需要实现的核心功能。 非功能性目标 (NFRs): 明确性能(延迟、QPS)、可用性 (Availability)、可靠性 (Reliability)、可伸缩性 (Scalability)、可维护性 (Maintainability)、可测试性 (Testability) 等方面的具体指标要求。 明确核心假设 (Identify Technical Assumptions): 方案设计所依赖的底层库行为、第三方服务承诺、网络环境稳定性等假设。 产出: 一份 技术规格与约束清单 (Technical Specifications & Constraints List),作为设计方案的输入和评判标准。...

December 28, 2024 · 2 min · 233 words · Similarityoung

Dubbo 集成 Spring Security 和 OAuth2

定义与基本概念 Spring Security 是一个基于 Spring 框架的安全框架,为 Java 企业级应用提供了全面的安全解决方案,涵盖了身份验证(用户登录)、授权(访问控制)、加密和防止常见的安全漏洞等功能。它可以集成到各种类型的 Spring 应用中,包括 Web 应用(如 Spring MVC、Spring Boot)和非 Web 应用。 OAuth2(开放授权 2.0)是一个开放标准的授权框架,旨在解决不同应用之间的授权问题,允许用户在不向第三方应用透露自己的用户名和密码的情况下,授权第三方应用访问他们存储在另一个服务提供商上的资源。它通过使用令牌Token来代表用户的授权,使得资源服务器能够验证请求是否被授权。 核心角色与流程 资源所有者:通常是用户,拥有受保护的资源。 资源服务器:存储资源的服务器,需要对请求进行授权验证。 客户端:请求访问资源的应用程序。 授权服务器:负责验证资源所有者的身份,并发放令牌给客户端 客户端请求资源所有者授权,资源所有者同意后,授权服务器向客户端发放令牌,客户端携带令牌访问资源服务器,资源服务器验证令牌的有效性后提供资源。 与 Dubbo 的协同 同时低版本 javax 和高版本 jakarta servlet API ,jakarta API 优先级更高,只需要引入jar即可使用HttpServletRequest和HttpServletResponse作为参数 使用 Filter 扩展: 实现 Filter 接口和 org.apache.dubbo.rpc.protocol.tri.rest.filter.RestExtension 接口,然后注册SPI 主要流程 由于 OAuth2 需要授权服务器,资源服务器,客户端,为了简化案例,就写授权服务器和资源服务器。 AuthorizationServer 采用默认配置 @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); return http.build(); } 1. 端点访问控制 授权端点(/authorize): 要求进行身份验证,只有已认证的用户才能发起授权请求。默认情况下,通常会使用 Spring Security 的标准身份验证机制,如基于表单的登录或 HTTP Basic 认证。 限制对该端点的请求方法,一般只允许 GET 和 POST 方法,以防止恶意的请求操作。 令牌端点(/token): 此端点用于发放访问令牌和刷新令牌,安全要求更高。默认配置会要求客户端进行身份验证,通常通过客户端 ID 和客户端密钥进行认证。 同样限制请求方法,一般只允许 POST 方法,以确保只有合法的请求才能获取令牌。 2....

December 26, 2024 · 4 min · 660 words · Similarityoung

一些较好的文章收藏

go 的代码风格 git commit 规范 git 教程 The Uber Go Style Guide

December 1, 2024 · 1 min · 12 words · Similarityoung

Zinx 框架学习笔记

函数返回接口而不是具体的结构体 Q: 为什么返回接口 IServer 而不是 server /* 创建一个服务器句柄 */ func NewServer (name string) ziface.IServer { s:= &Server { Name :name, IPVersion:"tcp4", IP:"0.0.0.0", Port:7777, } return s } A : NewServer 函数返回一个 ziface.IServer 类型的接口而不是直接返回 Server 类型的结构体,这种设计方式具有几个优点: 抽象化:返回一个接口而不是具体的结构体可以抽象化组件之间的交互。使用接口可以隐藏具体实现的细节,使得调用者只需要关心接口提供的方法。这样,如果未来需要改变具体的实现,只要新的实现符合接口的定义,调用代码不需要做任何修改。 灵活性和扩展性:使用接口使得代码更加灵活和易于扩展。比如,如果你想实现一个具有不同特性的服务器,只需创建一个新的结构体,实现相同的接口。这样你可以在不修改现有代码的情况下,为系统引入新的功能。 依赖倒置原则:这是面向对象设计原则之一,主张高层模块不应该依赖低层模块,它们都应该依赖于抽象。接口作为一种高级的抽象,确保了系统各个部分的低耦合性,增加了代码的稳定性。 测试和模拟:使用接口可以更容易地进行单元测试。你可以创建一个或多个模拟(mock)对象来实现同一接口,这样就可以在不涉及具体服务器实现的情况下测试系统的其他部分。 因此,返回 ziface.IServer 接口而不是具体的 Server 结构体,在软件工程中是一种常见且有益的做法,特别是在构建需要高度维护和扩展性的大型软件系统时。这种方式提供了更好的解耦和更灵活的代码管理策略。 函数定义的使用 函数类型的定义在编程中非常有用,尤其在Go语言这样的类型安全语言中,它提供了一系列的好处,这些好处涵盖了代码的可维护性、灵活性和可重用性等方面: 代码复用: 通过定义一种函数签名,可以创建多个遵循相同模式的函数,这有助于统一接口和减少重复代码。这意味着你可以编写高度模块化的代码,其中特定的功能可以由符合同一签名的不同函数实现。 实现抽象和封装: 函数类型的定义允许程序员封装复杂的逻辑,并通过简单的接口暴露功能,使得其他部分的代码不必了解背后的细节就能使用该功能。这有助于降低程序各部分之间的耦合度。 提高灵活性: 函数类型作为参数传递或作为返回类型使用时,可以使代码更加灵活。开发者可以根据具体的需要传入不同的函数实现,例如在处理不同类型的网络请求时,可以根据请求的类型动态选择合适的处理函数。 便于维护和扩展: 函数类型定义使得未来的修改和扩展变得更容易。如果需要修改功能,只需替换或修改实现了该函数类型的具体函数,而不需修改依赖于该类型的代码。这样做减少了对现有代码的干扰,降低了引入新错误的风险。 支持回调和高阶函数: 函数类型的定义是实现回调机制的基础。在Go中,经常会用到回调来处理异步事件、定时任务或在框架中允许用户代码介入框架运行。同时,函数类型的定义是实现高阶函数(接受函数为参数或返回函数的函数)的关键,这在功能编程风格中非常有用。 类型安全: 函数类型提供了类型安全的好处,确保函数的使用者传递正确类型的参数,返回预期类型的数据。这在编译时就能捕捉到许多可能的错误,提高程序的健壮性。 panic 具体使用方法 以下是一个使用 ProcessFunc 类型函数作为参数的示例,该函数将遍历一个字符串切片,并使用传入的 ProcessFunc 类型函数处理每个字符串,然后将结果收集并返回。 首先,我们有一个 ProcessFunc 类型定义,如之前所述: type ProcessFunc func(input string) int 现在,我们将创建一个函数 applyToStrings,它接受一个 ProcessFunc 类型的函数和一个字符串切片,应用该函数到每个字符串,并收集结果:...

September 24, 2024 · 2 min · 235 words · Similarityoung