精华内容
下载资源
问答
  • 我们现在不仅仅在信息流和故事流排名上使用机器学习:我们你关注的标签收集并推荐文章,将不同类型的内容混合在一起,并为智能应用预抓取提供动力。 Instagram 使用机器学习方法的所有不同方式都值得一贴,...

    自从我们在 2016 年宣布信息流排名以来,Instagram 机器学习有了显著的提高。我们的推荐系统定期为超过 10 亿的用户提供服务。我们现在不仅仅在信息流和故事流排名上使用机器学习:我们从你关注的标签中收集并推荐文章,将不同类型的内容混合在一起,并为智能应用预抓取提供动力。

    Instagram 使用机器学习方法的所有不同方式都值得一贴,但是我们想讨论一些在构建机器学习流水线时得到的一些教训。

    模型选择

    我们在这里对如何建模做一些决定,这些决定对我们很有帮助,要么可以提高模型的预测能力和提供顶线改进,要么可以在维持精度的情况下降低内存消耗。

    首先我们选择 caffe2 作为我们的基础模型框架,这意味着我们通过这个平台来编写和设计模型。相比于其它选项,Caffe2 对我们的工作流提供了明显的优化,并且它在推理时为每个 CPU 周期的模型权重提供了最大空间。“堆栈占用”在机器学习团队中是一个很重要的度量标准,因为我们在网络中使用了多个 CPU 密集型统计技术(池,等)。

    我们也使用带有排序损失的模型和 point-wise 模型(例如对数损失)。这让我们在最终的价值函数中拥有更多的控制权,这样我们就可以在关键的投入指标中进行微调。

    在核心机器学习中,通过考虑我们模型中的位置偏差,我们可以得到一些非常好的准确性。我们在最后的全连接层添加了一个稀疏位置特征,以此避免过多的影响模型。一般来说,共同学习稀疏嵌入是另外一个有影响力的领域,它以多种方式来恰当地捕捉用户的兴趣。。

    通过拟合高斯过程,我们定期调整最终的价值函数,以了解通过一系列 A/B 测试测量的价值函数参数对顶线指标的影响。

    图 1:一个我们用来进行预测的经典模型结构的例子

    数据新鲜度和趋势

    用户习惯会随着时间而改变。同样,生态系统也会受到趋势效应的影响(比如在超级碗这种季节性事件中)。正因为如此,数据新鲜度是很重要的。陈旧的模型不能捕捉到用户行为的变化或者理解新的趋势效应。

    量化数据新鲜度的影响对我们是有帮助的。我们监测关键行为分布之间的 KL-散度偏移,来告知我们的流水线的“不稳定性”。

    保持我们的模型新鲜的一个方法是有一个在线学习模型或者至少进行周期性的训练。在这种设定中,我们面临的最大挑战之一是提出一个合理的自适应学习率策略,因为我们希望新的例子在梯度更新中仍然有用(即使对那些已经在数月的数据上进行了训练的模型)。

    新颖效应

    新颖效应是我们面临的另外一个难题。我们经常进行 A/B 测试,在早期对照组表现出正向的作用,并且逐渐趋向于中性。

    一方面,可以明确的是,一些细微的变化可以暂时提高参与程度。我们相信这源于一个事实,即长期运行模型会倾向于“挖掘”的过多,并且这些测试会带来一些新的探索领域。

    这些影响的时间尺度也很有趣。我们已经看到了一些变化,这些变化需要持续一个多月的时间后才能趋于平稳(参与度呈上升或下降趋势)。

    另一方面, 我们艰难地认识到,新颖效应可以是很微妙的,所以在推出可能会产生影响的新体验时,应该小心控制。我们最近进行了一次严重的事后分析,发现两个容易产生新颖效应的实验在启动后的几个小时内相互作用,变得非常糟糕。

    虽然这并不完美,我们现在有了一些模型可以预测容易新颖的实验的数量和长度。借此我们可以通过减缓风险和提前终止测试来更快的进行迭代。

    图 2:在我们运行的 A/B 测试之一上观察新颖性

    实验(A/B)小影响

    大规模机器学习和 A/B 测试有许多不同的复杂性。除了上述提到的新颖性之外,我们也面临统计学上的问题。想象一下有 10 个排名工程师每人启动一个新的测试 everyday:很有可能这其中的一些测试提高了参与度指标,这很有统计意义。

    最重要的是,这些实验中的一些可能只是为了一些特定目标的用户,因此这个测量结果不是对所有用户起到同样的重要性的。这就使得测试结果很难评估。

    我们当前的最佳实践是在工程师的迭代速度和我们启动的变化置信区间之间做出权衡。在我们批准进行 A/B 测试之前,这些最佳实践需要在大量用户中进行严格的复制。

    学习作为影响和科学方法

    根据定义,机器学习是一种随机过程。当我们进行性能评估时,我们的工程师和科研人员根据在稳定项目上的传统软件工程师来进行校准。做所有正确的事情都是有可能的,但是在底线方法方面会让人失望。

    在 Instagram 上,我们热衷于坚持科学的实验方法。即使 A/B 测试不会直接导致产品发布,我们也可以经常利用它在未来提供有趣的产品洞察力。

    这也防止了在训练流水线中进行超参数随机遍历以寻找局部最优解的糟糕的科学模式。我们现在称这种模式为“人类梯度下降”。有了这一点,我们需要在启动测试之前验证原则假设。

    作为一个机器学习工程师,我们并非仅仅盯着特征看,我们还想要学习。每个实验都有其特定的输出,我们并不是随机游走。

    正则化

    混合不同类型的内容是我们面临的另外一个挑战。例如,一个视频和一张照片有不同可能操作的分布。例如你可以想象“喜欢”一张照片和“评论”一张照片或者“完成”一部视频是三种不同的行为,并且有着不同的分布(如喜欢比评论更常见,等)。

    简单来说,它就像是对照片用 P[喜欢](一个观众喜欢这个照片的概率)和对视频 P[完成](一个观众观看一部视频超过其 X% 长度的概率)来进行排序一样。当我们想要合并这个列表来完成对观众的最终排序时,机器学习工程师就处在一个很为难的位置。

    我们通过拟合一个映射来解决这个问题,即从一个价值函数分布(如 P[喜欢])映射到一个合理的分布如高斯分布。在那样的输出空间中,列表现在是可比较的,并且我们可以清楚的说出一部分内容优于另外一部分。

    图 3:我们的价值模型在归一化前的对数分数,分布很不均匀

    迭代速度 - 离线分析

    我们添加适当的后验框架已经太晚了。对非常大规模且有影响的机器学习系统来说,工程师和科研人员真的需要去打开模型并且仔细的理解他们实验产生的效果。在没有可靠的工具下这是很难做到的。我们开发了一个重播工具来接收你想要测试的新模型/排名配置,并且输出一组有用的测量结果来帮助理解你的改变对整个生态系统的影响。

    我们的目标是尽量减少在线实验,尽可能减少给用户暴露糟糕的实验结果的风险并且加速我们的迭代速度。

    图 4:我们的离线分析工具在模型指标上的表现(每个点表示了一个不同的训练模型)

    工具和基础设施

    所有大规模系统都需要严格的基础设施,幸运的是,在 Instagram 中我们有一个稳定的机器学习基础设施团队(他们最初建立了反馈排名并从其分离出来)。所有模型推理、特征提取、训练数据生成和监控都由其基础设施负责。

    不必去担心规模问题,全神贯注于统计模型对我们工程师而言是最有效的提高之一。最重要的是,机器学习基础团队创建了工具让我们更加深入的理解我们的模型,从而帮助我们提高用户体验。

    个性化

    另外一个有利的特征是精调我们的最终价值函数的能力。将我们的模型作为输入,添加我们的业务逻辑,然后返回每个媒体的最终得分。个性化价值函数兼具了有效性和复杂性。我们选择对那些从我们的推荐系统中获益较少的用户群体进行高层次的启发式分析,并专门为他们调整价值函数。

    另一个显示早期结果的个性化策略是在一些用户亲和力模型中进行因子分解。试图量化一个用户与其他用户/内容类型之间的亲和力有多大,这有助于我们专门为观众定制和适应我们的功能。

    价值模型

    最后,我们有了我们的价值模型:公式化描述,它将不同的信号组合成一个分数,并且合并我们的业务逻辑。这是一个复杂的代码,产品启发法满足统计预测。

    过去这些年通过调整这个价值模型,我们看到了显著的增长。我们经常使用高斯处理和贝叶斯优化来跨越模型的超参数空间,并且找到一个适合我们的区域。有一篇在这里详细的描述了这个过程。

    图 5:我们怎样调节不同的归一化价值模型并且测量不同的影响程度

    后记

    我们希望对我们的机器学习管道和我们面临的问题的总结是有帮助的。在未来的文章中,我们将更深入的讨论上述的一些问题。

    无论我们是在预测用户行为,构建内容理解卷积神经网络,还是创建潜在的用户模式,这些课程都有助于我们减少错误并更快地迭代,这样我们就可以不断地为 Instagram 上的每个人改进机器学习!

    如果你很高兴应用机器学习技术为我们的全球化社区提供价值,我们一直在寻找更多优秀的人才来加入我们

    如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。


    掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

    转载于:https://juejin.im/post/5c683dfce51d45164c7599fb

    展开全文
  • 希望阅读有关我自己教自己如何编码的经验,这可以帮助您反思自己的过去,并激励您继续前进。 第1课:关注流程 (Lesson 1: Focus on the Process) When I first started learning to program, I never had the ...

    自学成才翁

    The path of the self-taught developer is tough and filled with uncertainty. There is no straight line from newbie to career programmer. Because of this, I believe all self-taught developers have a unique story to tell.

    自学成才的开发者之路艰难而充满不确定性。 从新手到职业程序员都没有直线。 因此,我相信所有自学成才的开发人员都有一个独特的故事要讲。

    In this article, I’ll share my coding journey through a series of lessons I learned along the way. Hopefully reading about my experience teaching myself how to code will help you reflect on your own past, and motivate you to keep moving forward.

    在本文中,我将通过在此过程中学到的一系列课程来分享我的编码之旅。 希望阅读有关我自己教自己如何编码的经验,这可以帮助您反思自己的过去,并激励您继续前进。

    第1课:关注流程 (Lesson 1: Focus on the Process)

    When I first started learning to program, I never had the intention of making a career out of it. I just wanted to make a specific app.

    当我刚开始学习编程时,我从来没有打算以此来从事职业。 我只是想制作一个特定的应用程序。

    My journey started when I was a senior in college. I just finished Richard Branson’s biography and I was probably reading too much TechCrunch. I was pumped full of entrepreneurial energy.

    我的旅途始于我上大学时。 我刚刚读完Richard Branson的传记,可能读了太多TechCrunch。 我充满了创业精神。

    I was constantly reading about how college kids were receiving massive amounts of investment for their mobile app ideas. I thought I could be one of those college kids.

    我一直在阅读有关大学生如何通过其移动应用程序创意获得大量投资的信息。 我以为我可以成为那些大学生中的一个。

    One day, while walking in between classes, an app idea hit me. I quickly became convinced that I’d found the next big thing.

    有一天,在上课之间走动时,一个应用程序的主意击中了我。 我很快就确信自己找到了下一件大事。

    I was consumed by the idea and stopped paying attention to lectures. My excitement for the app idea quickly grew to the point where I felt I needed to take action.

    我被这个主意迷住了,不再关注讲座。 我对应用程序创意的兴奋很快上升到我认为需要采取行动的地步。

    There was one big problem. My idea was a mobile app and I didn’t know anyone who could build mobile apps.

    有一个大问题。 我的想法是移动应用程序,但我不认识任何人可以构建移动应用程序。

    So I thought, "what the hell, how hard could programming be?" I was losing interest in my major and I was spending a lot of time playing Xbox. I could put some of my free time towards building out my mobile app idea.

    所以我想,“到底是什么,编程有多难?” 我对自己的专业失去了兴趣,花了很多时间玩Xbox。 我可以将一些空闲时间用于建立自己的移动应用创意。

    Sometimes being naive helps you take action when you normally wouldn’t.

    有时候,天真可以帮助您采取通常不会采取的行动。

    I was a college student with no programming, business, or design experience trying to learn Android so I could build a complex mobile app. I guess that’s what you get when you mix a big idea with the Silicon Valley hype machine.

    我是一名没有编程,业务或设计经验的大学生,试图学习Android,因此可以构建一个复杂的移动应用程序。 我想这就是将大创意与硅谷炒作机相结合所得到的。

    I wish I could tell you things went well from here.

    我希望我能告诉你,从这里开始一切顺利。

    I bought a few books on Android development and spent countless hours in my room trying to duct-tape my app together. I didn’t care how the app worked, I just wanted a finished product.

    我买了几本有关Android开发的书,在房间里花了无数个小时试图共同整理我的应用程序。 我不在乎该应用程序如何工作,我只想要一个成品。

    Time went on and the app turned into a Frankenstein of copy and pasted code. The app didn’t have many features and it barely ran without crashing.

    随着时间的流逝,该应用程序变成了复制和粘贴代码的科学怪人。 该应用程序没有很多功能,几乎没有崩溃就可以运行。

    It wasn’t until I accidentally got into a Computer Science class that I realized that I should focus more on actually trying to learn software development.

    直到我不小心上了计算机科学课,才意识到我应该更加专注于实际尝试学习软件开发。

    My inability to program lead me to abandon my initial app idea. I'd come to the realization that I wasn’t going to make the next big thing, at least not yet.

    由于无法编程,我放弃了最初的应用程序创意。 我意识到,我不会做出下一件大事,至少现在还没有。

    Over time I corrected my behavior and took learning more seriously. I started to enjoy programming and eventually started a career as a software developer.

    随着时间的流逝,我纠正了自己的行为,并认真学习了。 我开始喜欢编程,最终开始了自己的软件开发生涯。

    My big app idea consumed me for a long time. It put my focus on the end result rather than the process of getting there.

    我的大型应用程式创意让我很久不知所措。 它使我着重于最终结果,而不是到达目标的过程。

    When you get too focused on the end result, you start taking shortcuts. Shortcuts might lead some short-term progress but in the long run, your lack of knowledge will always catch up to you.

    当您过于关注最终结果时,您就会开始采用捷径。 捷径可能会带来一些短期进展,但从长远来看,您缺乏知识将永远追上您。

    It’s important to remember that learning anything big, like programming, requires many small steps. Each step will need to be treated with care.

    重要的是要记住,学习任何大东西(例如编程)都需要许多小步骤。 每个步骤都需要谨慎对待。

    Learning new things is like building a house. You start with the foundation and build up. If the foundation is faulty the whole thing will crumble down sooner or later.

    学习新事物就像盖房子。 您从基础开始,逐步建立。 如果基础有问题,整个事情迟早都会崩溃。

    Sometimes building a strong foundation requires you to slow down. There’s no shame in going slow. The people who understand the basics the first time will end up getting ahead of the people who have to go back and relearn them.

    有时建立坚实的基础需要您放慢脚步。 放慢脚步没有什么可耻的。 第一次了解基础知识的人最终将领先于必须回去重新学习的人。

    There’s an old Chinese proverb that goes:

    有句老话说:

    "It is better to take many small steps in the right direction than to make a big leap forward only to stumble backward."
    “向正确的方向迈出许多小步,比向前迈出一大步而后退才更好。”

    It's not how fast you can do something, it's how slowly you can do it correctly.

    您做某事的速度并不快,而正确完成它的速度却很慢。

    I was a perfect example. From the outside, it might’ve looked like I was a programming whiz kid. In reality, I couldn’t build an app to save my life.

    我是一个完美的例子。 从外部看来,我好像是一个编程天才小子。 实际上,我无法构建用于挽救生命的应用程序。

    Focus on the process and you will surprise yourself with how much progress you make each day.

    专注于过程,您会惊讶于每天取得的进步。

    第2课:堆栈溢出很棒(但很危险) (Lesson 2: Stack Overflow is Awesome (But Dangerous))

    As I was building my killer app, Stack Overflow became my best friend.

    在构建杀手级应用程序时,Stack Overflow成为了我最好的朋友。

    Anytime I got stuck I would try to craft together a perfect question to ask the Stack Overflow community. I averaged a few questions a day.

    每当我遇到困难时,我都会尝试提出一个完美的问题,向Stack Overflow社区提问。 我平均每天要问几个问题。

    Not only would I post questions, but I would also treat the answers on Stack Overflow as Gospel. I would spend a crazy amount of time scouring the site to try to find an exact chunk of code that would fix my problem.

    我不仅会发布问题,而且还会将Stack Overflow上的答案视为福音。 我会花大量的时间搜索站点,以尝试找到可以解决我的问题的确切代码。

    When I found a suitable answer, I would copy and paste it right into my codebase and try to make it work with my existing code. I spent little time trying to understand the code I was adding.

    找到合适的答案后,我将其复制并粘贴到我的代码库中,并尝试使其与现有代码一起使用。 我花了很少的时间来理解我要添加的代码。

    I made brute-force trial and error a new art form.

    我把蛮横的尝试和错误变成了一种新的艺术形式。

    This process went on for a while until eventually, I wised up and realized the flaws of my approach.

    这个过程持续了一段时间,直到最终,我明智地意识到了我方法的缺陷。

    Stack Overflow is a blessing and a curse. It’s great at helping you solve problems – however, if you aren’t careful, you can quickly become dependent on the website.

    堆栈溢出既是福也是祸。 很好地帮助您解决问题-但是,如果您不小心,则会很快变得依赖该网站。

    Sometimes the website is too good at solving problems. It creates a false sense of confidence that can lead to more headaches down the road.

    有时,网站太擅长解决问题。 这会产生一种虚假的自信感,可能导致日后出现更多头痛问题。

    Stack Overflow shows you how to get something to work but it doesn't usually explicitly tell you why it works.

    堆栈溢出向您展示了如何使某些东西起作用,但通常不会明确告诉您它为什么起作用。

    Understanding the how is important. Bugs need to be fixed and code needs to run.

    了解其重要性。 错误需要修复,代码需要运行。

    However, understanding why something works is what's going to help you apply the knowledge again in the future.

    但是,了解某些事情起作用的原因将帮助您将来再次应用该知识。

    It's like the quote...

    就像报价...

    "Give a man a fish, and you feed him for a day. Teach a man to fish, and you feed him for a lifetime."
    “给男人一条鱼,你就给他喂一天。教一个男人鱼,你就给他喂一辈子。”

    Copy and pasting code from Stack Overflow is like giving someone a fish. Understanding why a snippet of code works is like teaching them to fish.

    从Stack Overflow复制和粘贴代码就像给别人一条鱼。 理解为什么一段代码有效,就像教他们钓鱼一样。

    There's nothing wrong with copying and pasting code. We all do it. It's only a problem when it becomes a crutch and stunts our growth as a developer.

    复制和粘贴代码没有错。 我们都做。 当它变成拐杖并阻碍我们作为开发人员的成长时,这只是一个问题。

    The thing I had to learn the hard way was that it's impossible to learn anything if the answers are constantly given to you. There are no short-cuts in the learning process.

    我必须努力学习的一件事是,如果不断地给您答案,就不可能学到任何东西。 学习过程中没有捷径。

    When you're stuck, attempt to solve your coding problem at least a few times before going to Google.

    当您陷入困境时,请尝试至少解决几次编码问题,然后再上Google。

    When you find yourself copying and pasting code, spend a little time trying to understand the code snippet before moving on.

    当您发现自己要复制和粘贴代码时,请花一些时间尝试理解代码片段,然后再继续。

    第3课:学习如何找到有经验的帮助 (Lesson 3: Learn How to Find Experienced Help)

    The first thing I did after I decided I wanted to learn programming was buy two Android development books.

    在我决定学习编程之后,我要做的第一件事就是买了两本Android开发书籍。

    At the start, I followed the exercises in the books closely and worked through the example projects. However, I quickly got frustrated with the progress I was making following the book and decided to go off and figure out how to program on my own.

    开始时,我密切关注了书中的练习并通过示例项目进行了工作。 但是,我很快对跟随本书所取得的进展感到沮丧,并决定继续研究如何自行编程。

    As you’ve read above, that slowly resulted in disaster.

    如您在上面所读,这慢慢导致了灾难。

    I spent countless hours isolated in my room trying to figure out simple programming problems. I was getting stuck on every new line of code and it didn't feel like I was making much progress.

    我在房间里呆了无数个小时,试图找出简单的编程问题。 我被困在每行新代码上,感觉好像没有什么进步。

    I was helplessly stuck and my life was a cocktail of doubt, frustration, and an overwhelming feeling of being lost.

    我被无助地困住了,我的生活充满了怀疑,沮丧和失落的压倒感。

    To make matters worse, I had the bright idea to start using a massive C library called FFMPEG. My app needed to edit videos, so I thought it was a good idea to utilize the library’s robust functionality.

    更糟糕的是,我有一个聪明的主意,开始使用一个名为FFMPEG的大型C库。 我的应用程序需要编辑视频,因此我认为利用库的强大功能是个好主意。

    It wasn’t my smartest move, considering at the time, I could barely get my Android app working.

    这不是我最明智的举动,考虑到当时,我几乎无法使我的Android应用程序正常运行。

    I wasted a lot of time trying to read the C code and figuring out how I could use it in my app. I struggled to even get the library imported into my Android project. The Android code and C code didn't want to play nice.

    我浪费了很多时间试图阅读C代码并弄清楚如何在应用程序中使用它。 我甚至很难将库导入到我的Android项目中。 Android代码和C代码不想玩的很好。

    After many hours of getting nowhere, I eventually became frustrated and abandoned the library.

    经过无数小时的漫长跋涉,我最终感到沮丧并放弃了图书馆。

    Around the same time as the FFMPEG debacle, I signed up for an Object Oriented Programming class. I'm honestly not sure how I got in. I later found out that I was the only non-Computer Science major in the class. I think there was a bug in the enrollment software.

    在FFMPEG崩溃的同时,我报名参加了面向对象编程类。 老实说,我不确定自己是如何进入的。后来我发现我是班上唯一的非计算机科学专业。 我认为注册软件中存在错误。

    The first assignment was to build a Blackjack program. I’d been teaching myself programming for 5-6 months at this point, and I felt somewhat confident with my skills.

    第一个任务是建立一个二十一点程序。 在这一点上,我一直在教自己编程5-6个月,我对自己的技能有些自信。

    I finished the assignment and felt good about my work.

    我完成了作业,对我的工作感觉很好。

    It didn't take long for that feeling to fade.

    这种感觉很快就消失了。

    My whole program was written in one huge method. Just about everyone else in the class was able to pick up on the fact that the program needed to be separated into classes.

    我的整个程序是用一种巨大的方法编写的。 班上几乎所有其他人都可以理解该程序需要分成几类的事实。

    Not good.

    不好。

    Luckily, the classwork and guidance from the teacher allowed me to take a step back from my Android app and reflect on my programming abilities. I started to value learning and reigned back my desires to make a completed app.

    幸运的是,老师的课堂教学和指导使我能够从Android应用程序退后一步,并反思自己的编程能力。 我开始重视学习,并重新表达了制作完整应用程序的愿望。

    I've now come to realize that if I would've spoken to just one experienced developer in those early days, they would’ve seen what I was doing. I could have set my priorities straight, and talked some sense into me. They would’ve helped me correct my path when I was going down useless dead ends (like trying to work with FFMPEG).

    现在,我意识到,如果在那些早期只与一位经验丰富的开发人员交谈,他们就会知道我在做什么。 我本可以设定优先顺序,然后对我说一些话。 当我陷入无用的死胡同(比如尝试使用FFMPEG)时,它们会帮助我纠正我的道路。

    Instead, I isolated myself from the world partially because I felt like there wasn’t anyone who could help me.

    相反,我部分地将自己与世界隔离了,因为我觉得没有人可以帮助我。

    Isolation is a double-edged sword. On one side, it helps you focus on the task at hand. On the flip side, it removes you from the world, starving you of crucial feedback.

    隔离是一把双刃剑。 一方面,它可以帮助您专注于手头的任务。 另一方面,它使您与世隔绝,使您无法获得重要的反馈。

    There were a lot of ways I could’ve found help. I could’ve tried to find a professor/student at the university with Android experience or looked to the local community for help. I also could’ve tried finding an online Android community.

    我有很多方法可以找到帮助。 我本可以尝试在大学里找到具有Android经验的教授/学生,或者向当地社区寻求帮助。 我也可以尝试找到在线Android社区。

    Experienced developers are like a compass. They won’t get you to your destination but they will make sure you are pointed in the right direction. Their help can often be the difference between success and failure.

    经验丰富的开发人员就像指南针。 他们不会把您带到目的地,但是他们会确保您的方向正确。 他们的帮助通常是成功与失败之间的区别。

    Make sure you seek out guidance wherever you can find it. It will save you time and frustration down the road.

    确保在任何可以找到的地方寻求指导。 这将节省您的时间和麻烦。

    第4课:打造环境 (Lesson 4: Craft Your Environment)

    This might be the only thing I felt like I did right when I was teaching myself programming.

    当我自学编程时,这也许是我唯一做对的事情。

    Throughout my life, I’ve been really bad at studying for tests or doing my homework at home. There are just too many distractions at any given moment. I would often try to find refuge in libraries or coffee shops.

    在我的一生中,我真的很不擅长学习测试或在家中做作业。 在任何给定的时刻都有太多的干扰。 我经常会尝试在图书馆或咖啡厅寻找避难所。

    Luckily I applied this rule when I was teaching myself programming.

    幸运的是,在我自学编程时,我应用了此规则。

    I ended up becoming a regular at a few local coffee shops. I preferred coffee shops over other study locations because they provided some variety and it’s easy to hide (easy access to caffeine doesn’t hurt either).

    我最终成为当地几家咖啡店的常客。 与其他学习地点相比,我更喜欢咖啡店,因为它们提供了一些种类,而且很容易藏起来(轻松获取咖啡因也不会造成伤害)。

    If I was studying at home, I made sure my door was shut and my roommates knew not to disturb me for a certain period of time.

    如果我在家学习,请确保我的门已关上,并且室友知道在一段时间内不会打扰我。

    Regardless of where I was, I would make sure my music was loud enough so I couldn’t hear what was going on around me.

    无论我身在何处,我都会确保我的音乐足够响亮,这样我就听不到周围发生的一切。

    I can’t say I was perfect at finding a distraction-free work environment but I was able to succeed a majority of the time.

    我不能说我很完美地找到一个无干扰的工作环境,但是大部分时间我都能成功。

    Having the right work environment is often an overlooked part of learning.

    拥有正确的工作环境通常是学习的一部分。

    Focus is a foundational component of memory and skill acquisition. When you try to learn something new, the strength of the learning is directly linked to the intensity of your focus. When your focus is weak, new information will be less sticky which will result in slower learning and more time studying.

    专注是记忆和技能获得的基本组成部分。 当您尝试学习新事物时,学习的强度与专注的强度直接相关。 当您的注意力不足时,新信息的粘性会降低,这将导致学习速度变慢和学习时间增加。

    Your work environment should be distraction-free and should allow for long uninterrupted stretches of focus. Even with COVID-19 making it necessary to work remotely, there are still actions you can take to design your learning environment.

    您的工作环境应无干扰,并应保持长时间不间断的关注。 即使COVID-19使得必须进行远程工作,您仍然可以采取一些措施来设计学习环境。

    Here are a few things you can do:

    您可以执行以下操作:

    • Find a location where people won’t interrupt you

      找到人们不会打扰您的位置
    • Put your phone in airplane mode

      将手机置于飞行模式
    • Use some sort of timed website blocker for social media and news sites

      对社交媒体和新闻网站使用某种定时的网站拦截器
    • Wear headphones and listen to non-distracting music (preferably a long playlist so you don’t have to constantly switch songs)

      戴上耳机并收听无干扰的音乐(最好是较长的播放列表,这样您就不必不断切换歌曲)
    • Avoid TV or other highly stimulating surroundings

      避免电视或其他刺激性强的环境
    • Have a notebook nearby to write down any tasks or ideas that pop into your head

      在附近有一个笔记本,记下突然出现的所有任务或想法
    • Make it known to the people around you that you don't want to be disturbed

      让周围的人知道您不想被打扰

    Only you can decide where and how to craft your environment. But make sure you do, because it’s worth it.

    只有您可以决定在何处以及如何创建环境。 但是请确保您这样做,因为这是值得的。

    第5课:走进世界与人见面 (Lesson 5: Get Out Into the World and Meet People)

    Landing my first programming job was sort of a random occurrence.

    登陆我的第一份编程工作是随机发生的。

    I just moved to Omaha, Nebraska and I had around a year of self-taught development under my belt.

    我刚搬到内布拉斯加州的奥马哈,在自己的指导下进行了大约一年的自学发展。

    I knew very few people in Omaha, so I searched Meetup.com to try and find other people interested in Android development. I found a Meetup focused on mobile development which covered both iOS and Android development and I decided to go.

    我在奥马哈认识的人很少,因此我搜索了Meetup.com尝试寻找对Android开发感兴趣的其他人。 我找到了一个专注于移动开发的Meetup,涵盖了iOS和Android开发,因此我决定去。

    Going to that first meeting was nerve-racking. I spent around 10 minutes in my car at the venue deciding if I should go in or drive off.

    参加第一次会议真是令人费解。 我在会场里开车花了大约10分钟的时间,决定应该进还是开车。

    I was intimidated. I wasn’t confident of my programming skills and I knew everyone at the Meetup had much more experience than I did.

    我被吓到了。 我对自己的编程技能不自信,而且我知道Meetup上的每个人都比我拥有更多的经验。

    I finally said, screw it and went inside.

    我终于说了,拧紧它,走进去。

    I’m glad I did.

    我很高兴我做到了。

    I started to attend regularly and during one Meetup, not too long after I moved to Omaha, I met a recruiter who was looking for an Android contractor. We talked for a while and I got an interview for the job later that week.

    我开始定期参加会议,在一次聚会中,就在搬到奥马哈后不久,我遇到了一个正在寻找Android承包商的招聘人员。 我们聊了一会儿,那周晚些时候我接受了这份工作的面试。

    Before the interview, I felt confident. During the interview, I was a deer in the headlights.

    面试前,我有信心。 在采访中,我是头鹿。

    The interviewer was talking about the project I’d be working on and it all went right over my head. I tried to stay engaged but they could tell it was out of my range.

    面试官在谈论我将要从事的项目,一切都浮现在我头上。 我试图保持订婚,但他们可以说这超出了我的范围。

    After the interview, they asked me to hang-out for an hour so I could talk to someone else. Knowing I blew it, I walked around downtown trying to clear my head.

    面试后,他们要求我出去玩一个小时,以便我可以和其他人聊天。 知道自己炸死后,我在市区走来走去,试图清理自己的头。

    I ended up interviewing with someone else at the company, and shortly after, they offered me an internship.

    我最终在公司里采访了其他人,不久之后,他们给了我实习机会。

    I was so shocked that after I signed all the paperwork and got my work laptop running, I went over to the CEO and asked if it was a paid internship or not.

    我非常震惊,以至于我签署了所有文件并运行了我的笔记本电脑后,我去找CEO询问是否是带薪实习。

    The internship turned into a full-time job and I started my career as a software developer.

    实习变成了全职工作,我以软件开发人员的身份开始了我的职业生涯。

    When you are self-taught, people are not going to come and seek you out. You will need to find opportunities for yourself.

    当您自学成才时,人们不会来找您。 您将需要为自己找到机会。

    Graduates of four-year universities and code schools have the advantage of leveraging their school's network when finding a job. Self-taught developers don’t have this luxury.

    四年制大学和法学院的毕业生在找工作时具有利用学校网络的优势。 自学成才的开发人员没有这种奢侈。

    Self-taught developers will need to go out into the world and build their networks themselves.

    自学成才的开发人员将需要进入世界并自己构建网络。

    Cold calling employers and sending out resumes can work. However, I've found people like hiring people who are close to them in their social network.

    冒昧地打电话给雇主并发送简历可以奏效。 但是,我发现人们喜欢在其社交网络中雇用与他们关系密切的人。

    Websites like Meetup.com are great for finding monthly programming-specific groups. Even in a pandemic, there are still many virtual Meetups that are very informative and beneficial.

    Meetup.com这样的网站非常适合查找每月特定于节目的组。 即使在大流行中,仍然有许多虚拟的聚会非常有益且有益。

    There are also other Slack channels or Discord communities that you can leverage to make meaningful relationships. You can also try reaching out to various people in your area and ask to have a quick 15-minute virtual coffee with them.

    您还可以使用其他Slack渠道或Discord社区来建立有意义的关系。 您还可以尝试与您所在地区的各个人联系,并要求他们与他们一起快速喝15分钟的虚拟咖啡。

    Do what you can to build up the nerve to reach out and talk with people. Be friendly and talk to them about your experiences. Make sure people know of your long-term goal of finding a job.

    尽您所能建立联系和与人交谈的神经。 友好并与他们谈论您的经历。 确保人们知道您找到工作的长期目标。

    Put yourself in situations where something positive might happen. You can’t win a raffle if you never buy a ticket.

    将自己置于可能发生积极事情的情况下。 如果您不买票,就无法中奖。

    Consider any opportunity that comes your way, because even if it looks like a dead-end, it has the potential to lead to something bigger.

    考虑一下您遇到的任何机会,因为即使它看起来像是死路一条,它也有可能带来更大的潜力。

    My internship was a huge pay-cut to the other offers I had at the time. However, I knew if I worked hard it would be an opportunity for me to break into the tech industry.

    我的实习是我当时其他职位的大幅减薪。 但是,我知道如果我努力工作,那将是我进入科技行业的机会。

    The key is to think of job opportunities in the long-term. Internships or part-time jobs might not give you your desired salary upfront but they might open up doors in the future.

    关键是要长期考虑工作机会。 实习或兼职工作可能不会给您预想的薪水,但将来可能会打开大门。

    我希望你能从我的错误中学到东西,并自己激发新的错误 (I Hope You Learn From My Mistakes and Make Exciting New Mistakes of Your Own)

    As you can see, I made a lot of mistakes in my journey of becoming a self-taught developer.

    如您所见,在成为一名自学成才的开发人员的过程中,我犯了很多错误。

    Teaching yourself to code is never a straight road. All our stories are unique.

    自学编码从来都不是一条直路。 我们所有的故事都是独一无二的。

    The key is to keep going and to avoid getting discouraged when things aren't going your way.

    关键是要继续前进,避免在事情进展不顺利时灰心丧气。

    I encourage other self-taught developers to share their stories. Not only will they provide valuable insights, but they will also help shine a light on the unique paths we’ve taken.

    我鼓励其他自学成才的开发人员分享他们的故事。 它们不仅可以提供宝贵的见解,而且还有助于阐明我们所采取的独特路径。

    Hopefully, my story and the lessons I learned will help you moving forward.

    希望我的故事和所学到的课程将帮助您前进。

    Thanks for reading. If you want to hear about other insights I've learned along the way, follow my account Zero to Programmer on Twitter. My goal is to help you learn programming more efficiently.

    谢谢阅读。 如果您想了解我在此过程中学到的其他见解,请在Twitter上关注我的帐户Zero to Programmer 。 我的目标是帮助您更有效地学习编程。

    翻译自: https://www.freecodecamp.org/news/lessons-learned-from-my-journey-as-a-self-taught-developer/

    自学成才翁

    展开全文
  • 支持这一功能的后端系统在过去的几年经历了几次架构迭代: Kafka 客户端处理单个 Kafka 主题开始,最终演变为具有更复杂处理逻辑的 Lambda 架构。 然而,为了追求更快的产品迭代和更低的运维开销,我们最近把它...

    Lambda 架构已经成为一种流行的架构风格,它通过使用批处理和流式处理的混合方法来保证数据处理的速度和准确性。但它也有一些缺点,比如额外的复杂性和开发/运维开销。

    LinkedIn 高级会员有一个功能,就是可以查看谁浏览过你的个人资料(Who Viewed Your Profile,WVYP),这个功能曾在一段时间内采用了 Lambda 架构。支持这一功能的后端系统在过去的几年中经历了几次架构迭代:从 Kafka 客户端处理单个 Kafka 主题开始,最终演变为具有更复杂处理逻辑的 Lambda 架构。

    然而,为了追求更快的产品迭代和更低的运维开销,我们最近把它变成无 Lambda 的。在这篇文章中,我们将分享一些在采用 Lambda 架构时的经验教训、过渡到无 Lambda 时所做的决定,以及经历这个过渡所必需的转换工作。

    这个系统是如何运作的?

    WVYP 系统依靠一些不同的输入源向会员提供最近浏览过其个人资料的记录:

    · 捕获浏览信息并进行除重;

    · 计算浏览源(例如,通过搜索、资料页面浏览等);

    · 浏览相关性(例如,一位高级人员查看了你的资料);

    · 根据会员的隐私设置查看模糊信息。

    下图显示了使用 Lambda 架构的系统简化图。

    首先,我们有一个 Kafka 客户端,可以近实时地处理并提供会员资料视图活动。当一个会员查看另一个会员的个人资料时,会生成一个叫作 ProfileVieweEvent 的事件,并发送到 Kafka 主题。

    处理作业将消费这个 ProfileVieweEvent 并调用大约 10 个其他在线服务来获取额外的信息,如会员概要数据、工作申请信息、会员网络距离(一度、二度连接)等。

    然后,该作业将处理后的消息写入另一个 Kafka 主题,这个主题的消息将被 Pinot(一个分布式 OLAP 数据存储,https://pinot.apache.org)消费。Pinot 将处理后的消息追加到实时中。Pinot 可以处理离线和实时数据,所以非常适合被用在这个地方。

    与此同时,还有一组离线的 Hadoop MapReduce 作业在不同的技术栈中执行上述操作,使用的是 ETL 过的 ProfileViewEvent 和上述服务处理过的相应数据集。这些作业每天加载这些数据集,并执行数据转换操作,如过滤、分组和连接。此外,如上图所示,离线作业还将处理实时作业不处理的 NavigationEvent,这个事件可以告诉我们浏览者是如何找到被浏览资料的。处理后的数据集被插入到 Pinot 的离线表中。

    Pinot 数据库负责处理来自实时表和离线表的数据。中间层服务通过查询 Pinot 获取处理过的会员资料信息,并根据前端 API 的查询参数(如时间范围、职业等)对数据进行切片和切块。

    这就实现了 Lambda 架构:

    · 实时作业侧重速度,进行不完整信息的快速计算;

    · Hadoop 离线作业侧重批处理,旨在提高准确性和吞吐量;

    · Pinot 数据存储是服务层,将批处理和实时处理的视图合并起来。

    Lambda 架构为我们带来了很多优势,这要得益于实时处理的快速和批处理的准确性及可再处理性。然而,这也伴随着大量的运维开销。随着我们不断迭代产品并增加更多的复杂性,是时候做出改变了。

    我们的挑战

    众所周知,Lambda 架构带来了饱受诟病的运维开销,违反了“不要重复你自己”(DRY)原则。更具体地说,WVYP 系统面临以下几个挑战:

    · 开发人员必须构建、部署和维护两个管道,这两个管道产生数据大部分是相同的;

    · 这两个处理管道需要在业务逻辑方面保持同步。

    上述的两个挑战占用了开发人员大量的时间。

    导致系统的演化有很多不同的原因,包括特性增强、bug 修复、合规性或安全性的变更、数据迁移等。WYVP 的所有这些变更都需要付出双倍的成本,部分原因是因为 Lambda 架构。更糟糕的是,Lambda 架构还带来了额外的问题,因为我们是基于两个不同的技术栈实现大部分的特性,所以新的 bug 可能会在批处理或实时处理中出现。

    此外,随着 LinkedIn 工具和技术栈的不断演化,我们需要不断地跟进,以便能够保持在最新状态。例如,在最近的一次 GEO 位置数据迁移过程中,我们发现了一些不必要的复杂性。Lambda 架构的分层带来了运维上的负担。例如,实时作业在处理消息是会出现延迟,离线作业有时会失败——这两种情况我们都太熟悉了。最终我们发现,这种开销是不值得的,因为它显著降低了开发速度。因此,我们开始努力重新改造 WVYP 的 Lambda 架构。

    无 Lambda 架构

    我们开始简化架构,移除全部离线批处理作业,并使用 Samza 开发新的实时消息处理器。我们之所以选择移除离线作业并保留实时处理,主要原因是产品需要近实时的会员资料浏览通知。批处理更适合用在其他一些场景中,例如在 A/B 测试中计算业务指标影响。

    新架构如下图所示。

    新架构的两个主要变化:

    · 创建了一个新的 Samza 作业,用来消费 ProfileVieweEvent 和 NavigationEvent,旧的消费者客户端只消费 ProfileVieweEvent。

    · 所有的离线作业都被移除,并创建了一个单独的作业,我们稍后将讨论这个作业。

    Samza 作业

    Samza 最初由 LinkedIn 开发,是 LinkedIn 的分布式流式处理服务,现在是 Apache 的一个项目。我们选择将现有的实时处理器作业迁移到 Samza 有很多原因。

    首先,Samza 支持各种编程模型,包括 Beam 编程模型。Samza 实现了 Beam API(https://beam.apache.org):我们可以用它轻松地创建数据处理单元管道,包括过滤、转换、连接等。例如,在我们的例子中,我们可以很容易地加入 PageVieweEvent 和 NavigationEvent,近乎实时地计算出视图的来源——这在旧处理器中是不容易做到的。

    其次,在 LinkedIn 部署和维护 Samza 作业非常简单,因为它们运行在由 Samza 团队维护的 YARN 集群上。开发团队仍然需要处理伸缩、性能等问题,但在定期维护方面确实有很大帮助(例如,不需要担心机器发生故障)。

    最后,Samza 与 LinkedIn 的其他工具和环境进行了很好的集成。

    新的离线作业

    有些人可能会问,为什么我们仍然在无 Lambda 架构使用离线作业。事实上,从架构转换的角度来看,这并不是必要的。但是,如上图所示,离线作业会读取 HDFS 里经过 ETL 的数据,这些数据是由 Samza 作业通过 Kafka 主题间接产生的。离线作业的唯一目的是将所有写入 Pinot 实时表的数据复制到离线表。

    这样做有两个原因:

    (1)由于数据的组织方式,离线表有更好的性能(离线表的数据段比实时表要少得多,查询速度更快)。

    (2)处理过的视图数据将保留 90 天,而实时表只保留几天的数据,并通过自动数据清除功能进行清除。新离线作业与旧离线作业的一个关键区别是,新作业在处理逻辑上与实时作业没有重叠,它没有实现 Samza 作业中已经实现的逻辑。当 Pinot 能够自动支持从实时表到离线表的文件整合时,我们就可以移除这个作业。

    消息再处理

    天底下没有无 bug 的软件,一切事物仍然会以不同的方式出错。对于 WVYP,使用错误的逻辑处理过的事件会一直保留在数据库中,直到被重新处理和修复。

    此外,一些意想不到的问题会在系统可控范围之外发生(例如,数据源被破坏)。批处理的一个重要作用是进行再处理。如果作业失败,它可以重新运行,并生成相同的数据。如果源数据被损坏,它可以重新处理数据。

    在进行流式处理时,这个会更具挑战性,特别是当处理过程依赖其他有状态的在线服务提供额外的数据时。消息处理变成非幂等的。WVYP 在状态方面依赖在线服务,在消息被处理时需要向会员发送通知(但我们不想发送重复的通知)。如果所选择的数据存储不支持随机更新,比如 Pinot,那么我们就需要一个重复数据删除机制。

    我们意识到,要解决这个问题,并没有什么灵丹妙药。我们决定以不同的方式对待每个问题,并使用不同的策略来缓解问题:

    · 如果我们要对处理过的消息做一些微小的改动,最好的方法是写一个一次性离线作业,读取 HDFS 中已处理的消息(就像新架构中的离线作业那样),进行必要的处理,再推送到 Pinot,覆盖掉之前的数据文件。

    · 如果出现重大的处理错误,或者 Samza 作业处理大量事件失败,我们可以将当前的处理偏移量倒回到前一个位置。

    · 如果作业只在某段时间内降级,例如视图相关性的计算失败,我们将跳过某些视图。对于这种情况,系统将在这段时间内降低容量。

    去重

    重复处理发生在各种场景中。一个是上面提到的,我们显式地想要重新处理数据。另一个是 Samza 固有的,为了确保消息的至少一次处理。当 Samza 容器重新启动时,它可能会再次处理一些消息,因为它读取的检查点可能不是它处理的最后一条消息。我们可以在两个地方解决去重问题:

    · 服务层:当中间层服务从 Pinot 表中读取数据时,它会进行去重,并选择具有最新处理时间的视图。

    · 通知层:通知基础设施确保我们不会在指定的时间段内向会员发送重复的通知。

    价值

    Lambda 架构已经存在了很多年,并得到了相当多的赞扬和批评。在迁移 WVYP 的过程中,我们获得了以下这些好处:

    · 通过将大部分的开发时间减半,开发速度得到了显著的提升,维护开销也减少了一半以上(实时流程的维护开销比批处理流程少)。

    · 提升了会员的用户体验。现在在开发过程中引入错误的可能性降低了。我们也有了更好的实时计算(例如,视图源的快速计算,这在以前是不可用的),可以更快地为会员提供 WVYP 信息。

    通过释放开发人员的时间,我们现在能够进行更快的迭代,并将精力放到其他地方。在这篇文章中,我们分享了 WVYP 系统的开发、运行和重新改造过程,希望我们的一些收获能够帮助那些在使用 Lambda 架构时面临类似问题的人做出更好的决策。

    推荐阅读:

    小米集团信息化思考

    微信好友突破10000人,节跳动即将取消饮料补贴福利!!

    66页PPT腾讯数据湖技术分享

    阿里达摩院《机器学习算法学习指南》火了,限时开放下载!

    浅显易懂的700页的机器学习笔记完整版(附下载)

    不是你需要中台,而是一名合格的架构师(附各大厂中台建设PPT)

    小米用户画像实战,48页PPT下载

    展开全文
  • 支持这一功能的后端系统在过去的几年经历了几次架构迭代: Kafka 客户端处理单个 Kafka 主题开始,最终演变为具有更复杂处理逻辑的 Lambda 架构。然而,为了追求更快的产品迭代和更低的运维开销,我们最近把它...

    作者 | Xiang Zhang、Jingyu Zhu

    策划 | Tina

    Lambda 架构已经成为一种流行的架构风格,它通过使用批处理和流式处理的混合方法来保证数据处理的速度和准确性。但它也有一些缺点,比如额外的复杂性和开发 / 运维开销。

    LinkedIn 高级会员有一个功能,就是可以查看谁浏览过你的个人资料 (Who Viewed Your Profile,WVYP),这个功能曾在一段时间内采用了 Lambda 架构。支持这一功能的后端系统在过去的几年中经历了几次架构迭代:从 Kafka 客户端处理单个 Kafka 主题开始,最终演变为具有更复杂处理逻辑的 Lambda 架构。然而,为了追求更快的产品迭代和更低的运维开销,我们最近把它变成无 Lambda 的。在这篇文章中,我们将分享一些在采用 Lambda 架构时的经验教训、过渡到无 Lambda 时所做的决定,以及经历这个过渡所必需的转换工作。

    1这个系统是如何运作的

    WVYP 系统依靠一些不同的输入源向会员提供最近浏览过其个人资料的记录:

    • 捕获浏览信息并进行除重;

    • 计算浏览源 (例如,通过搜索、资料页面浏览等);

    • 浏览相关性 (例如,一位高级人员查看了你的资料);

    • 根据会员的隐私设置查看模糊信息。

    下图显示了使用 Lambda 架构的系统简化图。

    首先,我们有一个 Kafka 客户端,可以近实时地处理并提供会员资料视图活动。当一个会员查看另一个会员的个人资料时,会生成一个叫作 ProfileVieweEvent 的事件,并发送到 Kafka 主题。处理作业将消费这个 ProfileVieweEvent 并调用大约 10 个其他在线服务来获取额外的信息,如会员概要数据、工作申请信息、会员网络距离 (一度、二度连接) 等。然后,该作业将处理后的消息写入另一个 Kafka 主题,这个主题的消息将被 Pinot(一个分布式 OLAP 数据存储) 消费。Pinot 将处理后的消息追加到实时中。Pinot 可以处理离线和实时数据,所以非常适合被用在这个地方。

    与此同时,还有一组离线的 Hadoop MapReduce 作业在不同的技术栈中执行上述操作,使用的是 ETL 过的 ProfileViewEvent 和上述服务处理过的相应数据集。这些作业每天加载这些数据集,并执行数据转换操作,如过滤、分组和连接。此外,如上图所示,离线作业还将处理实时作业不处理的 NavigationEvent,这个事件可以告诉我们浏览者是如何找到被浏览资料的。处理后的数据集被插入到 Pinot 的离线表中。

    Pinot 数据库负责处理来自实时表和离线表的数据。中间层服务通过查询 Pinot 获取处理过的会员资料信息,并根据前端 API 的查询参数 (如时间范围、职业等) 对数据进行切片和切块。

    这就实现了 Lambda 架构:

    • 实时作业侧重速度,进行不完整信息的快速计算;

    • Hadoop 离线作业侧重批处理,旨在提高准确性和吞吐量;

    • Pinot 数据存储是服务层,将批处理和实时处理的视图合并起来。

    Lambda 架构为我们带来了很多优势,这要得益于实时处理的快速和批处理的准确性及可再处理性。然而,这也伴随着大量的运维开销。随着我们不断迭代产品并增加更多的复杂性,是时候做出改变了。

    2我们的挑战

    众所周知,Lambda 架构带来了饱受诟病的运维开销,违反了“不要重复你自己”(DRY) 原则。更具体地说,WVYP 系统面临以下几个挑战:

    1. 开发人员必须构建、部署和维护两个管道,这两个管道产生数据大部分是相同的;

    2. 这两个处理管道需要在业务逻辑方面保持同步。

    上述的两个挑战占用了开发人员大量的时间。

    导致系统的演化有很多不同的原因,包括特性增强、bug 修复、合规性或安全性的变更、数据迁移等。WYVP 的所有这些变更都需要付出双倍的成本,部分原因是因为 Lambda 架构。更糟糕的是,Lambda 架构还带来了额外的问题,因为我们是基于两个不同的技术栈实现大部分的特性,所以新的 bug 可能会在批处理或实时处理中出现。此外,随着 LinkedIn 工具和技术栈的不断演化,我们需要不断地跟进,以便能够保持在最新状态。例如,在最近的一次 GEO 位置数据迁移过程中,我们发现了一些不必要的复杂性。Lambda 架构的分层带来了运维上的负担。例如,实时作业在处理消息是会出现延迟,离线作业有时会失败——这两种情况我们都太熟悉了。最终我们发现,这种开销是不值得的,因为它显著降低了开发速度。因此,我们开始努力重新改造 WVYP 的 Lambda 架构。

    3无 Lambda 架构

    我们开始简化架构,移除全部离线批处理作业,并使用 Samza 开发新的实时消息处理器。我们之所以选择移除离线作业并保留实时处理,主要原因是产品需要近实时的会员资料浏览通知。批处理更适合用在其他一些场景中,例如在 A/B 测试中计算业务指标影响。

    新架构如下图所示。

    新架构的两个主要变化:

    • 创建了一个新的 Samza 作业,用来消费 ProfileVieweEvent 和 NavigationEvent,旧的消费者客户端只消费 ProfileVieweEvent。

    • 所有的离线作业都被移除,并创建了一个单独的作业,我们稍后将讨论这个作业。

    Samza 作业

    Samza 最初由 LinkedIn 开发,是 LinkedIn 的分布式流式处理服务,现在是 Apache 的一个项目。我们选择将现有的实时处理器作业迁移到 Samza 有很多原因。

    首先,Samza 支持各种编程模型,包括 Beam 编程模型。Samza 实现了 Beam API:我们可以用它轻松地创建数据处理单元管道,包括过滤、转换、连接等。例如,在我们的例子中,我们可以很容易地加入 PageVieweEvent 和 NavigationEvent,近乎实时地计算出视图的来源——这在旧处理器中是不容易做到的。其次,在 LinkedIn 部署和维护 Samza 作业非常简单,因为它们运行在由 Samza 团队维护的 YARN 集群上。开发团队仍然需要处理伸缩、性能等问题,但在定期维护方面确实有很大帮助 (例如,不需要担心机器发生故障)。最后,Samza 与 LinkedIn 的其他工具和环境进行了很好的集成。

    新的离线作业

    有些人可能会问,为什么我们仍然在无 Lambda 架构使用离线作业。事实上,从架构转换的角度来看,这并不是必要的。但是,如上图所示,离线作业会读取 HDFS 里经过 ETL 的数据,这些数据是由 Samza 作业通过 Kafka 主题间接产生的。离线作业的唯一目的是将所有写入 Pinot 实时表的数据复制到离线表。这样做有两个原因:1) 由于数据的组织方式,离线表有更好的性能 (离线表的数据段比实时表要少得多,查询速度更快)。2) 处理过的视图数据将保留 90 天,而实时表只保留几天的数据,并通过自动数据清除功能进行清除。新离线作业与旧离线作业的一个关键区别是,新作业在处理逻辑上与实时作业没有重叠,它没有实现 Samza 作业中已经实现的逻辑。当 Pinot 能够自动支持从实时表到离线表的文件整合时,我们就可以移除这个作业。

    消息再处理

    天底下没有无 bug 的软件,一切事物仍然会以不同的方式出错。对于 WVYP,使用错误的逻辑处理过的事件会一直保留在数据库中,直到被重新处理和修复。此外,一些意想不到的问题会在系统可控范围之外发生 (例如,数据源被破坏)。批处理的一个重要作用是进行再处理。如果作业失败,它可以重新运行,并生成相同的数据。如果源数据被损坏,它可以重新处理数据。

    在进行流式处理时,这个会更具挑战性,特别是当处理过程依赖其他有状态的在线服务提供额外的数据时。消息处理变成非幂等的。WVYP 在状态方面依赖在线服务,在消息被处理时需要向会员发送通知 (但我们不想发送重复的通知)。如果所选择的数据存储不支持随机更新,比如 Pinot,那么我们就需要一个重复数据删除机制。

    我们意识到,要解决这个问题,并没有什么灵丹妙药。我们决定以不同的方式对待每个问题,并使用不同的策略来缓解问题:

    • 如果我们要对处理过的消息做一些微小的改动,最好的方法是写一个一次性离线作业,读取 HDFS 中已处理的消息 (就像新架构中的离线作业那样),进行必要的处理,再推送到 Pinot,覆盖掉之前的数据文件。

    • 如果出现重大的处理错误,或者 Samza 作业处理大量事件失败,我们可以将当前的处理偏移量倒回到前一个位置。

    • 如果作业只在某段时间内降级,例如视图相关性的计算失败,我们将跳过某些视图。对于这种情况,系统将在这段时间内降低容量。

    去重

    重复处理发生在各种场景中。一个是上面提到的,我们显式地想要重新处理数据。另一个是 Samza 固有的,为了确保消息的至少一次处理。当 Samza 容器重新启动时,它可能会再次处理一些消息,因为它读取的检查点可能不是它处理的最后一条消息。我们可以在两个地方解决去重问题:

    • 服务层:当中间层服务从 Pinot 表中读取数据时,它会进行去重,并选择具有最新处理时间的视图。

    • 通知层:通知基础设施确保我们不会在指定的时间段内向会员发送重复的通知。

    4价值

    Lambda 架构已经存在了很多年,并得到了相当多的赞扬和批评。在迁移 WVYP 的过程中,我们获得了以下这些好处:

    • 通过将大部分的开发时间减半,开发速度得到了显著的提升,维护开销也减少了一半以上 (实时流程的维护开销比批处理流程少)。

    • 提升了会员的用户体验。现在在开发过程中引入错误的可能性降低了。我们也有了更好的实时计算 (例如,视图源的快速计算,这在以前是不可用的),可以更快地为会员提供 WVYP 信息。

    通过释放开发人员的时间,我们现在能够进行更快的迭代,并将精力放到其他地方。在这篇文章中,我们分享了 WVYP 系统的开发、运行和重新改造过程,希望我们的一些收获能够帮助那些在使用 Lambda 架构时面临类似问题的人做出更好的决策。

    原文链接:https://engineering.linkedin.com/blog/2020/lambda-to-lambda-less-architecture

    推荐阅读:

    kappa和lambda对比

    大数据:简述 Lambda 架构

    展开全文
  •  把失败转变为经验,快速失败反馈教训走向好的一面,并且保持好奇心。最坏的就是处于一个自责或无助的学习状态,你不知道如何进展,或者开始思考为什么不管你怎么努力也不管用。只是因为你不能获得你期望的结果...
  • 挫折和失败中吸取教训,每周从教训中反思改善你的方法    在 30天敏捷结果:开篇 中说到接下来我们将进行敏捷结果练习,前一篇学习了 20:好的问题可以获得好的结果 ,通过问对问题,我们能够清晰的发现...
  • When I let go of what I am, I ... 孩子是最不怕犯错的,他们大胆尝试,从错误中获得成长体验,本篇讲的就是如何面对失败。  Failing Forward一书作者是一个领导学专家,他写了20多本书籍,每年至少给超过250,...
  • 在本文,我会和大家分享本人职业生涯步入歧途的故事以及中学到的教训:牢记著名作曲家约翰.鲍威尔的话“真正的错误,你是无法从中学习任何东西的”。 错误#1:将流程凌驾与项目(和人)之上
  • 转眼间,距离《魔兽世界:争霸艾泽拉斯》最后的8.3版本上线已经过去了几个月的时间,整个系列的下一部资料片《魔兽世界:暗影国度》上线的日子也逐渐接近,在那之前玩家们能做的事情也仅仅是不断进行硬件上的调整...
  • 全文共2047字,预计学习时长6分钟图源:unsplash我曾经多次参加面试,却总是与offer失之交臂,后来我才发现,我在面试过程反复地犯了几个关键错误。我从中吸取教训,最终获得了...
  • 最初的教程到最后的会议,人们在他们的博客讨论了QCon的许多方面。 您还可以在Flickr上看到众多与会者拍摄的QCon照片。 这次QCon是InfoQ的第九届会议,也是伦敦的第四届年会。 该活动是与在丹麦举办JAOO会议...
  • 人是不完美的,我们经常在程序错误。有时这些错误很容易发现:你的代码根本不能工作,你的应用程序崩溃等等。但是有些bug是隐藏的,这使得它们更加危险。 在解决深度学习问题时,由于一些不确定性,很容易出现...
  • 3月17消息,美国知名IT杂志《微电脑世界》(PCWorld)今日发表了署名为罗布-恩德勒(RobEnderle)的文章,该文章认为谷歌不善于IBM、苹果、微软和雅虎等企业的错误中汲取教训,完全丧失了自己应有的专注度,必将会...
  • 每当我接触这个问题的时候,我就会面对同样的担心和犹豫不决,那就是:我不能确定我就一定能够我自己的工作经历中吸取出别人可以应用在他们的实践的任何基本的真理性认识。某种程度上说,我自己的工作经验在我...
  • 【导读】强化学习之父Richard Sutton总结AI研究“苦涩教训”,认为利用算力才是王道,不应依靠人类知识。对此,著名机器人专家Rodney Brooks 撰文反驳,阐述了Sutton观点错误的六大原因。 The Bitter Lesson还...
  • 二战浙大失利+调剂科大教训

    万次阅读 多人点赞 2018-04-18 00:45:12
    本打算调剂结果出了就总结下备战考研一路走来的经验教训,无奈拖延症发作,直至今日才静下心来认真总结一番。 先说说自己的基本情况,供各位学弟学妹参考。 我本科南京一所普通211,机械工程及自动化专业,结构...
  • 如果运气好的话,这次事件中吸取教训可以帮助这个流程在下一次工作得更好。 全文完 LWN 文章遵循 CC BY-SA 4.0 许可协议。 欢迎分享、转载及基于现有协议再创作~ 长按下面二维码关注,关注 LWN 深度文章以及...
  • Web 应用程序的演变 最初在 Future Insights Live: Las Vegas 2014 上发表的演讲 URL: : (使用箭头键导航)... 我们将回顾这些历史转变,并从过去错误中吸取教训。 毕竟,不能历史中吸取教训的人注定要重蹈覆辙。
  • intro-to-firebase-源码

    2021-06-26 09:51:47
    Web 应用程序的演变 最初在 Future Insights Live: Las Vegas 2014 上发表的演讲 URL: : (使用箭头键导航)... 我们将回顾这些历史转变,并从过去错误中吸取教训。 毕竟,不能历史中吸取教训的人注定要重蹈覆辙。
  • 在本节,我们将讨论尝试构建过去由专家构建的事物的经典错误。 在我们的项目,我们意识到我们花了太多时间尝试重新设计一个众所周知的有效解决方案:提供年龄识别的神经网络模型。 Image by Alan O’Rourke. ...
  • 程序员在编程的时候难免会犯错误,但如果不从错误中吸取教训,那么习惯成自然,你会经常犯错的。从错误中不断的学习,锻炼好的行为习惯有助于事业上的稳定。 程序员在编程的时候难免会犯错误,但如果不从错误中吸取...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,339
精华内容 1,735
关键字:

从过去的错误中吸取教训