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;
}
暂无
点评:见分享
Basic paxos存在一些问题:
- 只有proposer知道哪一个value最终被选中
- 其proposal他servers必须发起自己的proposal才能知道
- 每一个value都需要经过prepare和accept两个阶段才能最终被选中,导致效率极其低下
现在我们看看multi paxos如何解决这些问题。
对于不同的key,更新他们的value其实是互相独立互不影响的,所以我们可以对每一个key开一个basic paxos实例来提高效率。
在basic paxos里面,任何server都可能是proposer或者acceptor,而这在并发比较高的时候会频繁出现拒绝重发。因此我们引入了leader选举。
最初的选主非常简单:server ID最大的当选。
leader会周期性地每Tms发心跳包给其他servers。
如果其他server在两个周期内没有收到leader的心跳包,他就会变成leader。
leader还会做以下事情:
- 接收客户端请求
- 既可以当proposer也可以当acceptor
而非leader角色的server行为如下:
- 拒绝客户端请求,转发给leader
- 只能当acceptor
除此之外,我们还可以做更多优化。比如去掉不必要的prepare rpc。
首先,我们思考一下,为什么需要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标记为选中
举个例子,
如果此时来了一个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