作者回复: 谢谢你的答案!这个答案很新颖啊,我觉得光从年龄这个问题上来讲,你的思路是可以把20多岁变成12、22、32、42等等。希望你能在以后遇到问题时也能保持这样创新思维,也希望你继续留言,我们一起学习进步!
作者回复: 谢谢你的答案!应该是一个很有经验的高级工程师了吧。使用Consistent hashing是可以很好地解决平均分配和当机器增减后重新hashing的问题。
作者回复: 你好王伟!首先感谢你的提问!
我不确定你所说的实时同步是想表达Eventual Consistency还是Strong Consistency,那我就争对两个都说说自己的愚见吧。
因为会员信息都会保存在商家库中,所以这里我假设商家库的信息可以作为source of truth。
如果你指的是Eventual Consistency的话,可以在会员更新商家库的同时将会员信息利用Pub/Sub发送给会员库去更新。考虑到Pub/Sub中间有可能会丢包,我们可以再建立一个定时任务每隔一段时间将全部商家库中的信息扫描一遍再更新到会员库中。当然具体的实现可以再作优化,因为商家库是按商家编号分库的,我们可以记录下哪些商家编号的表最近有更新我们就只扫描那些表,而不用扫描全局的表。
如果你指的是Strong Consistency的话,我们可以在中间再创建一个State Machine,记录是否两个库都同时更新了。在读取会员信息的时候,我们需要查询这个State Machine,只有当两个库同时都更新的时候才将会员信息返回。根据第九讲的CAP理论,这样的做法其实会牺牲掉Availability,也就是你的服务可用性。
当然具体的需求你会比我更了解,所以相信你能够从中做出设计上的取舍。也欢迎你继续留言提问,我们可以一起讨论学习进步!
作者回复: 😄 很多问题确实很有思考价值,我也学到了很多之前没考虑到的。
作者回复: 你好Maye,谢谢你的留言与提问!
第一问我也说说我的愚见吧。关于流处理和批处理的关系我更倾向于批处理可以算是流处理的一个子集吧。我们可以这么抽象地看,流计算所处理的都是无限数据集,而我们从中按照时间窗口抽取一小段出来的话,这一小段有边界的数据集其实也就是批处理所处理的数据集了。所以说批处理算是流处理的一个子集吧。但是现在流计算中两大问题:1)Exactly once delivery 2)message order,还没有非常完美的解决方案,但是我相信可以攻克的。所以未来趋势还是趋于统一。现在Google所推出的Apache Beam项目其实也是想解决这样一个问题,统一批处理和流处理的编程接口。更详细的内容我会在后面的章节展开讲解。
思考题你也看到了问题的本质,就是能找到趋于平均分配的分片处理方式。
欢迎你继续留言提问,一起交流学习进步!
作者回复: 再次看到了你的提问,感谢!
以下纯属个人愚见。
无论是MapReduce的partitioning,还是GFS的chunkservers,它们的设计思想都是将文件分割成固定大小的chunks来维护,而每一个chunk都会有一个deterministic的64位唯一标识符。这种设计思想是和consistent hashing不一样的,可以称为是Central Coordinator。
而历史原因也是存在的,GFS和MapReduce是分别在2003年和2004年公开论文的,而Distributed Hash Table这种思想,也就是Consistent hashing,是在2007年Amazon发表了Dynamo: Amazon's Highly Available Key-value Store这篇论文后被大家所广泛认同的。
最后我想说的是,设计一个通用架构给所有开发者使用和根据自身应用场景所设计出来的架构,它们的侧重点会有所不同。如果只是自身业务需要并且不需要太考虑时间复杂度,那当然可以自己去实现consistent hashing,毕竟hashing后取模和consistent hashing时每次都要计算环节点的时间复杂度肯定是不一样的。
希望这对你有所帮助,如果有所收获的话也欢迎你分享给朋友,谢谢!
作者回复: Round robin确实能保证均匀但是有个很大的问题是没有容错。因为在分布式处理的时候数据处理顺序是“随机”的,可能是shard 1/2/3也可能是 shard 1/3/2,如果发现shard 2所有任务挂了(机器坏了)需要重试,如果有确定的sharding function很容易找出shard 2的任务,round robin的话就无法还原shard 2任务了。当然你可以说我再搞个数据库把round robin结果保存,但那样就更复杂了。
作者回复: 谢谢你的答案!这个答案不错。不过取余运算在机器有增减的时候会遇到麻烦,所有的用户必须重新取余运算一遍。Consistent Hashing可以很好地解决这个问题。欢迎你继续留言,我们一起学习进步!
作者回复: 谢谢你的答案!你在每个答案里都分别给出这个答案所存在的不足,这一点我是非常赞赏的。在开发设计中没有哪个答案是特别完美的,我们能做的是分析哪一个才是最符合自身应用需求,进而改善。
1. 是的,倒置年龄的digit可以改善均分的问题,但是也存在hot spot的问题。
2. 我在其它的留言也回复过,随机分区的话还有一个缺点是当分区任务失败需要重新分区的时候,分区结果不再是deterministic的。
3. 总结得不错。
欢迎你继续留言,我们一起学习进步!
作者回复: 哈哈有收获就好
作者回复: 线下做了研究了很好啊。这三个看起来都可以吧。一般场景我觉得可以选择复杂度低的第一种,后面的对于普通场景可能都有点overkill。
作者回复: 是的,我觉得你总结的很好!
作者回复: 是对的思路!随机前缀这个我在另一个回复上也提到了,“真”随机会影响错误重试,因为没法还原当时的随机数,比如分片2的任务全部失败,找不到哪些是分片2了。
作者回复: 看来你很有经验!确实是很经常出现的问题
作者回复: 再次看到了你的留言,谢谢!
就像我之前的回答一样,Beam的诞生更多是想抽象出一个统一的编程模型来处理批处理和流处理,使不同的平台相互兼容,让开发者有能力在不同的平台中转移。无论是Spark还是Flink,它们都可以选择根据Dataflow Model来编写自己的底层实现。
关于调优的话Beam有根据不同平台来编写专门的API去编写配置。当然了,因为需要统一编程接口,你对底层的控制就没有原生Spark或者Flink那么好。
关于是否采用Beam的问题,历史因素也占了很大比重。很多时候进行平台的转移可能对开发者来说是一个overkill。就像我之前所说,现在越来越多的平台开始采用Dataflow Model来编写自己的底层实现。所以理论上,在未来开发者或者公司就可以不必过于担心转移数据处理平台时的迁移成本了
希望对你有帮助,如果有收获也请分享给朋友!
作者回复: 第一个问题hive和MR是apple and orange,不太好对比吧。hive更类似于SQL。
第二个问题恰恰是这个专栏的重点,会教会大家怎么解析框架的设计思路。
作者回复: 看到“30天速成”字样的资料可以直接扔掉
作者回复: 你的问题都很实际啊。job和job的互相抢占并不是spark独有的问题,都需要一些优先级系统,哪些job优先级高。还有异常处理,错误重试,任何数据处理系统都需要解决。这也是为什么这篇文章里提到多任务状态机,很多时候为了异常处理免不了这些系统以至于增加了复杂度。
作者回复: 这个思路看起来是做了很多课后研究了!希望后面也能继续参与讨论!