如何高效编写可维护代码?

原文:How to make your code self-documenting?
淡忘~浅思 翻译 如何高效编写可维护代码?

在代码中找到一个放错地方并且没有用的注释是不是很有趣呢?
怎么样才能做到写很少的注释但仍能让代码易于理解呢?
一个主要的方式就是让代码自我文档化。当代码自我文档化的时候,就不需要注释去它的作用或者目的,并且也能使代码变得非常容易维护。

阅读全文

为什么Disruptor会那么快?

Disruptor是一个高性能的线程间消息传递的框架。

LMAX 目标是成为当世最快的商务平台。 为了实现这个目标,LMAX需要做一些特殊的工作在Java平台上取得低延迟和高吞吐率的目标。 性能测试表明使用队列(queue)传递数据会带来延迟, 所以LAMX对这一块做了非常好的优化。

Disruptor就是他们的研究成果。 研究发现CPU级别的cache miss和 需要内核仲裁的锁非常的耗费性能, 所以他们创建了一个Disruptor, 这是一个锁无关的实现。

它不是一个为特别任务实现的方案,不仅仅应用于金融领域。Disruptor可以用来解决并发编程中的一个普遍的问题: 消息队列的处理(producer和consumer)。

它使用了一个和传统不一样方式来实现。 所以你可能不能用文本替换的方式使用ring buffer替换你代码中的Queue等。官方网站上提供了一些例子, 本文的参考文档上也列出了一些。 官方的技术白皮书介绍了一些你想知道的细节。 官方文档还提供了非常多的性能测试的代码,也是学习disruptor好材料。

Disruptor究竟有多块, 看官方的和ArrayBlockingQueue测试结果:

注意y轴的刻度是指数级别的, 如果按照均匀递增的刻度,一张图无法显示。
这张图可以这样解读。 x轴越靠近零的比例越多, 性能越好。
Disrutor延迟时间大部分小于1ns, 而ArrayBlockingQueue平均32ns左右了。

阅读全文

lock-free 编程介绍

这篇文章收集整理了lock free的编程概念。
如果在一个共享的数据结构上的操作都不需要互斥,那么它是无锁的。如果一个进程在操作中间被中断,其它进程不受影响。

lock free(翻译成 无锁或者锁无关)的优势

  • 通过减少阻塞和等待,来改进并发性和可扩展性。
  • 消除条件竞争(race condition)、死锁、可组合性不足带来的潜在问题。
  • 避免优先级反转

但是无锁编程不是万能药,因为无锁算法实现起来更复杂,它也有潜在问题,比如竞争(contention),这会极大地影响性能。从这一点出发,Herb引出了他的第一条强烈建议:

  • 在使用无锁技术前,你必须先测试你的程序,确定它有性能或可扩展性问题。
  • 实现无锁算法后,再次测试你的程序,确定结果得到了有效的改进。

阅读全文

跟着实例学习ZooKeeper的用法: 文章汇总


跟着实例学习ZooKeeper的用法提供了全面的例子, 演示了Curator在项目中的应用,全面的介绍了ZooKeeper的Recipe的实现, 以及CuratorFramework的基本用法。
都是独立的, 你可以挑选感兴趣的章节阅读,方便在需要的时候查找。
欢迎在评论中提供意见和建议以及内容的错误,我会及时的更新。
以下是各章节的汇总。

所有的代码都可以在github下载。

leader选举

Leader latch

Leader Election

分布式锁

可重入锁Shared Reentrant Lock

不可重入锁Shared Lock

可重入读写锁Shared Reentrant Read Write Lock

信号量Shared Semaphore

多锁对象 Multi Shared Lock

Barriers

栅栏Barrier

双栅栏Double Barrier

计数器Counters

Shared Counter

Distributed Atomic Long

缓存Caches

Path Cache

Node Cache

Tree Cache

临时节点

队列Queues

Distributed Queue

Distributed Id Queue

Distributed Priority Queue

Distributed Delay Queue

Simple Distributed Queue

Curator框架应用

框架介绍

操作方法

事务

Curator扩展库

跟着实例学习ZooKeeper的用法: Curator扩展库

还记得Curator提供哪几个组件吗? 我们不妨回顾一下:

  • Recipes
  • Framework
  • Utilities
  • Client
  • Errors
  • Extensions

前面的例子其实前五个组件都涉及到了, 比如Utilities例子的TestServer, Client里的CuratorZookeeperClient, Errors里的ConnectionStateListener等。 还有最后一个组件我们还没有介绍,那就是Curator扩展组件。

Recipes组件包含了丰富的Curator应用的组件。 但是这些并不是ZooKeeper Recipe的全部。 大量的分布式应用已经抽象出了许许多多的的Recipe,其中有些还是可以通过Curator来实现。
如果不断都将这些Recipe都增加到Recipes中, Recipes会变得越来越大。 为了避免这种状况, Curator把一些其它的Recipe放在单独的包中, 命名方式就是curator-x-,比如curator-x-discovery, curator-x-rpc。
本文就是介绍curator-x-discovery。

阅读全文

跟着实例学习ZooKeeper的用法: 队列

Curator也提供ZK Recipe的分布式队列实现。 利用ZK的 PERSISTENTSEQUENTIAL节点, 可以保证放入到队列中的项目是按照顺序排队的。 如果单一的消费者从队列中取数据, 那么它是先入先出的,这也是队列的特点。 如果你严格要求顺序,你就的使用单一的消费者,可以使用leader选举只让leader作为唯一的消费者。

但是, 根据Netflix的Curator作者所说, ZooKeeper真心不适合做Queue,或者说ZK没有实现一个好的Queue,详细内容可以看 Tech Note 4, 原因有五:

  1. ZK有1MB 的传输限制。 实践中ZNode必须相对较小,而队列包含成千上万的消息,非常的大。
  2. 如果有很多节点,ZK启动时相当的慢。 而使用queue会导致好多ZNode. 你需要显著增大 initLimit 和 syncLimit.
  3. ZNode很大的时候很难清理。Netflix不得不创建了一个专门的程序做这事。
  4. 当很大量的包含成千上万的子节点的ZNode时, ZK的性能变得不好
  5. ZK的数据库完全放在内存中。 大量的Queue意味着会占用很多的内存空间。

尽管如此, Curator还是创建了各种Queue的实现。 如果Queue的数据量不太多,数据量不太大的情况下,酌情考虑,还是可以使用的。

阅读全文