使用ZooKeeper实现Redis订阅消息的排他式处理
来源:互联网 发布:小学生机器人编程 编辑:程序博客网 时间:2024/06/03 22:59
前面咱们讨论过Redis Sentinel环境下Key过期事件消息订阅的问题,在演示程序中,由KeyExpiresMessageListener监听Redis发布出来的Key过期消息。
在生产环境下,这样的处理机制通常需要由一组独立部署的KeyExpiresMessageListener来构成高可用,但是当订阅消息发布出来时,所有的KeyExpiresMessageListener都能接收到,这样就会造成业务逻辑的重复处理,甚至可能导致系统逻辑错误,这就需要对各KeyExpiresMessageListener的工作进行全局的排他式控制,利用ZooKeeper我们可以很好地解决这个问题。
ZooKeeper是近几年广为应用的分布式协调框架,它使用类似Paxos协议的ZAB协议(ZooKeeper Atomic Broadcast)完成分布式系统一致性保障。分布式应用程序可以基于ZooKeeper实现数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁、分布式队列等功能。
ZooKeeper提供以下分布式一致性特性:
- 顺序一致性
- 原子性
- 单一视图
- 可靠性
- 实时性
这样,ZooKeeper集群就准备好了。
如前文所述,ZooKeeper可以提供的功能之一是分布式锁。分布式锁是控制分布式系统之间同步访问共享资源的一种方式,当不同系统或者同一个系统之内的不同节点访问同一个或一组资源的时候,需要通过互斥手段来防止相互之间的干扰,以保证一致性。
分布式锁的其中一种是排他锁或独占锁,当事务A对资源R加上了排它锁,那么在加锁期间,一致性系统将只允许事务A对资源R进行读取和更新操作,其他事务都不能对资源R进行任何类型的操作,直到事务A释放了资源R。我们的应用实践正是基于这种原理。
在ZooKeeper中,可以用一个数据节点来表示一个锁,比如:/a/lock,这是一个临时节点。ZooKeeper定义了三个大类的四种节点,以满足不同的需要:- 持久节点(PERSISTENT)
- 持久顺序节点(PERSISTENT_SEQUENTIAL)
- 临时节点(EPHEMERAL)
- 临时顺序节点(EPHEMERAL_SEQUENTIAL)
也就是会被添加顺序数字后缀的临时节点。
会使临时节点被清除的会话时效,包括两种形式:
- ZooKeeper系统重启
- 客户端主动关闭会话
此外,客户端也可以主动删除临时节点来清除它。
我们利用临时节点来实现一个各应用节点处理接收到的订阅消息的排它锁,机制是:当所有应用节点上的KeyExpiresMessageListener同时收到Key过期消息的时候,这些应用节点会随即尝试在ZooKeeper中创建一个锁节点,基于ZooKeeper良好的一致性保证,确保只有一个应用节点会创建锁节点成功,那么,后续的事务处理就只由这个幸运的应用节点来继续完成。
假设我们的业务是,接收Redis中订单数据Key过期的消息,并根据过期数据Key名字中包含的订单号来进行后续处理,订单数据Key形如EK_UPBO_15001。下面我们来看一下用于测试的程序。
首先是之前见过的AppConfig.java,定义了用来接收订阅消息的各种Bean:日志输出显示,程序已经连接上ZooKeeper。
现在在Redis里设置一个过期时间为5秒的Key:可以看到,本次竞争,Main2成功创建了排他锁,胜出:)
再观察一下ZooKeeper中的排他锁节点路径的情况:可以看到,由于我们在程序里设置了5秒的模拟业务处理耗时,所以临时节点/sasp/order/UPBO/15001也只短短存在了5秒钟就被删除掉了。
ZooKeeper是一个非常有用的框架,是Hadoop、HBase、Storm、Solr、Dubbo等众多大型分布式系统的核心组件,用于进行分布式协调。除此之外,ZooKeeper还有很多用途,本文只是抛砖引玉,更多的有趣实践请朋友们自己去探索吧!- 使用ZooKeeper实现Redis订阅消息的排他式处理
- 使用Spring-Redis实现消息的发布/订阅
- 12.springboot使用redis的订阅功能实现消息队列
- 使用redis实现消息发布订阅
- linux下使用hiredis异步API实现sub/pub消息订阅和发布的功能 标签: hiredishiredis异步APIhiredis事件处理redis消息订阅发布redis c接口 2016-
- Redis消息的发布/订阅
- Java实现Redis的消息订阅和发布
- Java实现Redis的消息订阅和发布
- Java实现Redis的消息订阅和发布
- Java实现redis的消息订阅和发布
- Java实现Redis的消息订阅和发布
- python 实现简单的redis 消息订阅推送
- Java实现Redis的消息订阅和发布
- 使用redis的setnx制作排他锁
- Spring Boot使用Redis进行消息的发布订阅
- 使用jedis操作redis之消息的发布和订阅
- 【Redis】jedis客户端实现redis消息的发布订阅(实时消息中间件)
- java使用redis发布和订阅消息
- android开发中bitmap图片占用内存计算方法
- 《C++ 笔记》 Part1 文件打开时的CString 转换为 char*
- codeforces 337A
- 关于大型网站技术演进的思考(八)--存储的瓶颈终篇(8)
- 自学ios之路(3)
- 使用ZooKeeper实现Redis订阅消息的排他式处理
- MFC CListCtrl不响应LVN_GETDISPINFO消息
- php curl
- 笔记 - Java 反射
- python类中的__call__、__init__、__getattr__、__setattr__、__setattr__详解
- 读《从〈机器猫〉看阶级斗争残酷的本质》
- 关于大型网站技术演进的思考(七)--存储的瓶颈(7)
- Android App整体架构设计的思考
- hdu2079 选课时间(题目已修改,注意读题)(多重背包)