这句话在哪里?我怎么没有找到?
我读的是这个 raft extended https://pdos.csail.mit.edu/6.824/papers/raft-extended.pdf
另外,这说的是接受 request 端吧?我问的是拿到 reply 端的情况,reply 端估计应该也检查 term
对的 1.改了 3.还是要检查的,比如现在 term 8 我是 server,发出去的一个 AppendEntries rpc delay 了,然后经过一些奇怪的超时,我现在是 term 10 的 leader 了,然后 term 8 的 reply 回来, 我如果更新 nextIndex/matchIndex,就不对了。 同样 If last log index ≥ nextIndex for a follower: send AppendEntries RPC with log entries starting at nextIndex • If successful: update nextIndex and matchIndex for follower (§5.3)
If successful 这个分支忘记问了,但是我感觉也是同样,必须检查是否仍然为同 term 时候的 leader,跟
If AppendEntries fails because of log inconsistency 需要的检查是一样的。
然后想了一下,那么同样 Candidates 的 Rule:
If votes received from majority of servers: become leader
同样也要对 reply 检查是否同一 term,
否则我 term 8 选举一个 reply delay 了,然后我 term 9 选举收了 majority-1 个 reply,
然后突然 term 8 的 reply 到了,这样我 succcesful vote + 1 还以为变成了 majority vote,
这就不对了,所以同样也要对 reply 检查是否同一 term
目前我 lab 2 的所有 test 都能 pass 1.确实如你所说,new server 意思是本 term 之后的所有 term,不包括那些老的 server 发过来的 AppendEntries rpc,我的实现虽然没有 bug,但是不 performant, 有可能需要新一轮的选举
2.我的 code 是有 heartbeat() 函数和 AppendEntries() 函数,heartbeat() 中,如果 prevLogIndex/prevLogTerm,马上就会在 heartbeat() 中进行重试,送一些 entries 出来,其实按照你说的,定义就是普通的带 Entries 的 AppendEntries RPC,只不过我是写在 heartbeat() 中而已
3.All leader 的 Rule 我肯定是执行的: All Servers:
• If commitIndex > lastApplied: increment lastApplied, apply log[lastApplied] to state machine (§5.3)
• If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower (§5.1)
这两条我都有执行,我问的是 Leaders 下面的 Rule:
• If AppendEntries fails because of log inconsistency: decrement nextIndex and retry (§5.3)
• If there exists an N such that N > commitIndex, a majority of matchIndex[i] ≥ N, and log[N].term == currentTerm: set commitIndex = N (§5.3, §5.4).
这两条,在拿到 reply 的时候,是否需要检查我自己仍然为 Leader,
我猜是需要的,我是加了 if term == rf.currentTerm 的 check
这样老的 reply 不会更新 nextIndex/matchIndex 和 commitIndex,
我觉得这是正确的语义
做到 raft 2d 部分,还是很开心的,distributed system 还是很容易出一些奇奇怪怪的 bug 的, 改了好久才好。paper 中算法有几个有歧义的地方,1.Candidates: If AppendEntries RPC received from new leader: convert to follower. 这个 new leader 的定义是什么?Leader Term>=Candidate's Term 么?我实际做的时候不管, 看见有 leader 来的 AppendEntries RPC 就从 Candidates Convert 成 follower,反正如果 Leader Term currentTerm: set currentTerm = T, convert to follower, 所以 Leader 也会在这次 reply 被 convert 成 Follower,无非是多一次选举。 2.heartbeat 头一次是送 empty entries,但是如果 prevLogIndex/prevLogTerm 导致 nextIndex[i] 减了,那么 heartbeat 是否送 entries? 还是说 heartbeat 只管 heartbeat,而送 entries 的只由 normal AppendEntries RPC 不断重试? 目前我的实现是 heartbeat 一旦发现 prevLogIndex/prevLogTerm 导致 nextIndex[i] 减了,是会送出 entries 的。 这样比较简单,反正都是幂等操作。 3.Leaders Rule:If AppendEntries fails because of log inconsistency: decrement nextIndex and retry 和 If there exists an N such that N > commitIndex, a majority of matchIndex[i] ≥ N, and log[N].term == currentTerm: set commitIndex = N 这个检查在 leader 接收到 reply 的时候检查,但是接收到 reply 是否要重新检查自己还为 Leader, 因为如果网络延时,reply 时可能都新 term 了,leader 可能变成新 term 的 follower,当然也可能仍然是新 term 的 leader 目前他这个 Rule 在 Leaders section 下面,所以我猜他是要检查的,我的检查 比较简单,判断仍然 term==rf.currentTerm,也就是一旦新 term,所有老 term 的 request 都失效, 我不会再用它来更新 nextIndex/matchIndex,也不会更新 commitIndex
code review
共享一下,抄作业~
兄弟你作业做了没有?我看了第一集,上来就要求写一个 mapreduce.
支持一下
感觉还是很奇怪的需求。有多种方式解决,你能写文件系统就写个文件 require, 要不然建个 model DynamicCode,然后后台系统弄个 textarea 填代码, 然后 console 里头 eval DynamicCode.first.code
为什么需要粘贴大段代码?写个 rake task 不行么? 或者写个文件,console 里头 require 就行
厉害,一般 Developer 的美感都不足, 要 Design 还是有些困难的
ruby 以前到有个 opal,这么多年了不知道怎么样了
@Stephanie 之前不是说要求会广东话么?
对了,那个 apollo 的搭建,也有运维人员的帮忙。
@lanzhiheng 前后端分离挺好用的啊,后端只需要写好逻辑就好了,很 focus,很符合经济学原理 里头的分工理论,即甲乙产出 A,B 产品,即使甲 A,B 产出效率都比乙高,分工也效率更好, 让甲专心做 A,已专心做 B,出来的效率也比甲乙都混合做 A,B 高 (经济学原理第一章)。目前实践下来挺方便的, 除了后期调试 bug 要复现他们所说的 bug 的时候不太方便以外,其他都还好。至于之前有个人说什么 前端莫名奇妙做缓存导致改 api 变动出问题,那是前端程序员的问题吧,依赖一个不存在的约定。
另外,部署为什么要用 Etcd,我们用 apollo.另外 docker 部署确实快,现在一个改动 push 下去, 都是几 s 就好,最近几次都是 7-8s, 比 cap,mina 什么的快多了。得益于 docker 的 layer 机制。
其次,你们运维就简单的搭了 k8s 么,其他都不管的么。那这怎么实践最佳实践啊。我们运维 负责把环境全部搭好,我们只需要把 builder 好的 docker image 给他就行了,做 CI/CD。
所以,没有做最佳实践,估计还是做最佳实践的各个组件,或者一部分组件 (指人) 没有做好吧。 那我这边再好的插头,没有插座也没用啊。国外那帮推最佳实践的,总体的实力都比较强啊。 就像之前的敏捷,传着传着就变形了。很难做到 copy 不走样。
@jasl 那就看看要支持到什么程度了,或者自己实现一套。跟 MRI 做交互的话,序列话反序列化类似 [:bigdecimal,value,scale] ,虽然不知道 msgpack 啥样,反正一个值表示类型,然后再把值和精度 表示上,就可以跟 MRI 做交互了。查了一下 mruby bigint, 一个是https://github.com/chasonr/mruby-bignum, 一个是https://github.com/chasonr/mruby-gmp-bignum/ , 有 gmp support 的。
@jasl 是 Decimal 类么?稍微试了一下, x = Decimal.new("1515") * Decimal.new("1515") x=x*x*x*x x=x*x*x*x x=x*x*x*x puts x
123827471039368400410635789691185425627549561183592154304459242100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 数字一大就错了。
另外 integer,乘着乘着就变浮点数了,这是 mruby 的特性么?
ps,感觉接下去就比较 specific 了,要不然我去 github 上开个 issue 讨论?
@jasl 我看你说 mruby 没有 bigdecimal? 据我所知,bigdecimal 就是 bigint+ 精度,比如 (a,4) 就是 a/10000.0, 那么+,-实现只要对齐就行了,实现就是 bigint 相乘,精度相加,比如 (a,4)(b,2) 就是 (a*b, 4+2),/实现也是类似。mruby 有 bigint 么?
@jasl 如果 spawn 一个 ruby,然后 remove 一些 unsafe 的东西,比如 undef File, IO, remove `等等, 会不会更简单一些?
挺不错的,顶一下。
我也要入群 @wangshu
@DerekZhang 你不是在区块链么?怎么又变成供应链了?
我在写 Perl 时的效率太高,去写别的语言短时间内根本达不到同等水平。毕竟这是十六年积累下来的经验。毕竟这是两万小时的练习成果。哈哈,我写 ruby 也是这样啊,估计也有两万小时了吧 。解决问题写很 elegant 的方法 (method),方法搞不定的用 meta-programming,再搞不定还可以用 ast 语法树。(可以叫做 super meta-programming 吗哈哈), 其他语言根本达不到同等效率。即使之前用了 python,但是感觉对于 python 也就是调调 api,解决解决算法问题这样的程度,根本达不到得心应手的程度。
@ForrestDouble 目前为止这些东西以 python 居多,历史原因吧,ruby 还没有。 如果你有兴趣可以弄弄,首先肯定是基础框架,就是对应于 python 的 numPy 和 sciPy 库, 这些基础计算库出来以后,在上层才可以弄数据分析,deep learning 等等
感觉很屌的样子,不知道这样会不会迎来 Ruby(或者 Crystal) 的一个爆发式增长。
@huacnlee 有没有像 HoneyBadger 或者 NewRelic 一样,手动调记录异常的? (因为有时候我们业务会自己捕获异常做一些处理), 类似于 HoneyBadger.notify_exception(e) NewRelic::Agent.notice_error(e)
我需要一个一本正经打表情符号的程序,哈哈哈:)
@liangjingyang 别上当,要用就用 Go
@freefishz 你的微信或者邮箱是多少,我加了你交流一下。