Skip to content

Latest commit

 

History

History
132 lines (84 loc) · 4.31 KB

林浩特-20180713.md

File metadata and controls

132 lines (84 loc) · 4.31 KB

【leetcode 算法题】

func lengthOfLongestSubstring(s string) int {
    if len(s) == 0 {
        return 0
    }
    maxLen := 1
    charMap := make(map[uint8]int, 128)
    // start of sliding window
    start := 0
    for i:=0; i<len(s); i++ {
        c := s[i] - ' '
        last, ok := charMap[c]
        if ok && last >= start {
            start = last+1
        }
        charMap[c] = i
        if i - start + 1 > maxLen {
            maxLen = i - start + 1
        }
    }
    return maxLen;
}

【小技巧】

暂无

【技术文章】

paxos simple

点评:见分享

【分享】白话Multi Paxos原理

Multi Paxos

Basic paxos存在一些问题:

  • 只有proposer知道哪一个value最终被选中
  • 其proposal他servers必须发起自己的proposal才能知道
  • 每一个value都需要经过prepare和accept两个阶段才能最终被选中,导致效率极其低下

现在我们看看multi paxos如何解决这些问题。

多实例

对于不同的key,更新他们的value其实是互相独立互不影响的,所以我们可以对每一个key开一个basic paxos实例来提高效率。

在basic paxos里面,任何server都可能是proposer或者acceptor,而这在并发比较高的时候会频繁出现拒绝重发。因此我们引入了leader选举。

leader election

最初的选主非常简单:server ID最大的当选。

leader会周期性地每Tms发心跳包给其他servers。

如果其他server在两个周期内没有收到leader的心跳包,他就会变成leader。

leader还会做以下事情:

  • 接收客户端请求
  • 既可以当proposer也可以当acceptor

而非leader角色的server行为如下:

  • 拒绝客户端请求,转发给leader
  • 只能当acceptor

除此之外,我们还可以做更多优化。比如去掉不必要的prepare rpc。

优化prepare

首先,我们思考一下,为什么需要prepare?

  • 上锁:所有proposal number太老的都会被block住
  • 可以获得其他server在该位置的chosen value

如果你prepare成功,意味着你成功lock所有server该位置,如果accept也成功,说明没有正在进行的后续proposal request进来,也就是说当前的value是最新的,所以对于leader来说,可以判断该index后面的value没必要再lock了,也就是说可以跳过prepare阶段和第一个value一起直接都提交即可。

acceptor返回

  • 当前最高的acceptedProposal
  • 如果该index之后再无其他accepted proposal,则返回一个noMoreAccepted
  • 如果收到某个server的response设置了noMoreAccepted,则后续不再发prepare给该server,直到发给该server的Accept被拒绝。
  • 如果大部分的server都返回了noMoreAccepted,那么leader将不再发送prepare。

完整复制

问题还没解决完,考虑以下问题:

  • 由于某些server可能会挂,那么log可能不会被完整复制到所有的server上。
  • 只有proposer知道值被选中。其他server并不会立即知道,必须等到下一轮。

怎么办?

解决方案如下:

  • 对于那些没收到value的server,我们需要起一个线程持续发,直到它接受为止。
  • 把被选中的value标记一下, acceptedProposal[i] = 无穷大,这样其他的prepare/accept就无法覆盖。
  • 每个server记录firstUnchosenIndex
  • proposer把firstUnchosenIndex通过accept告诉其他server
  • acceptors会把小于firstUnchosenIndex的value标记为选中

举个例子,

image-20180713022335967

如果此时来了一个request Accept(proposal=3.4, index=8, value=v, firstUnchosenIndex=7),

4,6还没提交,所以对于相同proposal,并且firstUnchosenIndex<7的value,我们都可以标记为chosen,即把6标记chosen

为什么?

  • 所有这些value都是来自同一个proposer
  • 该value已经被proposer选中,因为firstUnchosenIndex<7。
  • value的proposal number和请求的proposal一样,说明是最新的。

而那些roposal number和当前不一样的value,由于他来自其他proposer,我们不知道是否被选中。可能是无效的。

对于这些value,我们需要第三个rpc:success

解决步骤如下:

  • acceptor返回firstUnchosenIndex
  • proposer发送success(index, v),强行更新该value