1.分布式配置
要点:配置信息保存在
db
与zk
中(保险起见,数据安全性更高),弄一个后台管理界面,对配置修改后,先保存到db
,然后同步写入zk
的节点中。应用启动时,先连到zk
上读取节点中的配置,同时监听节点的数据变化,当配置变化时,得到实时通知。
2.消除单点故障(Single Point of Failure,SPOF)
└── ./OrderNoService
├── A0000001
10.0.0.1:8001
└── A0000002
10.0.0.2:8001
复制代码
多个服务实例,启动时在
zk
上临时顺序节点,服务的调用方约定取最小节点为Master
,当master
挂掉后,节点自动删除,调用方得到事件通知,取新的最小节点来调用(
相当于slave
提升为master)
3.分布式服务注册与订阅
在分布式环境中,为了保证高可用性,通常同一个应用或同一个服务的提供方都会部署多份,达到对等服务。而消费者就须要在这些对等的服务器中选择一个来执行相关的业务逻辑,比较典型的服务注册与订阅,代表:dubbo。
4、分布式锁
Order
└── 3456890
├── 000001
├── 000002
└── 000003
复制代码
原理:以多个程序运行实例同时在处理订单
3456890
为例,每个程序运行实例处理前,创建一个临时顺序节点,然后检查自己创建的节点是否为最小,如果不是,表明没抢到锁,如果是,表示抢到了锁,抢到锁的程序处理完以后,删除该节点表示释放锁。同时,其它处于等候状态的程序,为了实时得到锁的释放通知,均监听父节点Order/3456890
的子节点变化,发现子节点变化时,重复刚才的检测过程,直到自己创建的节点变成最小为止。 与redis SETNX
之类的分布式锁相比,zk
的分布式锁,还能实现解决Top N
之类的有限资源竞争问题(类似并发中的信号量)。比如:一堆程序要打印,但是只有2台打印机(或者打印队列的长度只有2,最多同时只能允许2个程序提交打印任务), 类似刚才的思路 ,可以检测最小的前2个节点,只有创建最小前2个节点的程序,才认为是拿到了信号,允许提交打印任务。
5、分布式队列
Queue
└── Queue1
├── 000001
├── 000002
└── 000003
复制代码
如上图,创建
Queue/Queue1
做为一个队列(或Topic
),然后每创建一个顺序节点,视为一条消息(节点存储的数据即为消息内容),生产者每次创建一个新节点,做为消息发送,消费者监听Queue1
的子节点变化(或定时轮询),每次取最小节点当做消费消息,处理完后,删除该节点。相当于实现了一个FIFO
(先进先出)的队列。 注:zk
框架强制的是CP
(一致性),而非专为高并发、高性能场景设计的,如果在高并发,qps
很高的情况下,分布式队列需酌情考虑。
6、生成分布式唯一id
Order
└── OrderId
├── 000001
├── 000002
└── 000003
复制代码
思路:每次要生成一个新
Id
时,创建一个持久顺序节点,创建操作返回的节点序号,即为新Id
,然后把比自己节点小的删除即可。
7.命名服务
在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通常可以是集群中的机器,提供的服务地址,进程对象等等——这些我们都可以统称他们为名字(Name)。其中较为常见的就是一些分布式服务框架中的服务地址列表。通过调用ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。