组件杂想

99 阅读4分钟

订阅发布模式应用

1. spring application publish event ContextRefreshedEvent , CustomEvent , ContextReadyEvent
2. redis 中的 订阅 channel ,当channel有变化时通知 channel的订阅者.
3. zookeeper中的watcher机制监听 某个节点的 创建 ,修改, 删除事件 , 客户端有个event listener线程不断轮询有没有服务端推送过来事件,如果收到事件就回调事件对应的回调方法

Redisson

Redisson提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期,也就是说,如果一个拿到锁的线程一直没有完成逻辑,那么看门狗会帮助线程不断的延长锁超时时间,锁不会因为超时而被释放。

默认情况下,看门狗的续期时间是30s,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson 还提供了可以指定leaseTime参数的加锁方法来指定加锁的时间。超过这个时间后锁便自动解开了,不会延长锁的有效期。

watch dog 在当前节点存活时每10s给分布式锁的key续期 30s;

watch dog 机制启动,且代码中没有释放锁操作时,watch dog 会不断的给锁续期;

从可2得出,如果程序释放锁操作时因为异常没有被执行,那么锁无法被释放,所以释放锁操作一定要放到 finally {} 中

如果释放锁操作本身异常了,watch dog 还会不停的续期吗?

不会,因为无论释放锁操作是否成功,EXPIRATION_RENEWAL_MAP中的目标 ExpirationEntry 对象已经被移除了,watch dog 通过判断后就不会继续给锁续期了。

Rabbitmq 消费不均衡

prefetch Count

什么是prefetch Count,先举个栗子:

假定 RabbitMQ 队列有 N 个消费队列,RabbitMQ 队列中的消息将以轮询的方式发送给消费者。

消息的数量是 M,那么每个消费者得到的数据就是 M%N。如果某一台的机器中的消费者,因为自身的原因,或者消息本身处理所需要的时间很久,消费的很慢,但是其他消费者分配的消息很快就消费完了,然后处于闲置状态,这就造成资源的浪费,消息队列的吞吐量也降低了。

这时候prefetch Count就登场了,通过引入prefetch Count来避免消费能力有限的消息队列分配过多的消息,而消息处理能力较好的消费者没有消息处理的情况。

RabbitM 会保存一个消费者的列表,每发送一条消息都会为对应的消费者计数,如果达到了所设定的上限,那么 RabbitMQ 就不会向这个消费者再发送任何消息。直到消费者确认了某条消息之后 RabbitMQ 将相应的计数减1,之后消费者可以继续接收消息,直到再次到达计数上限。这种机制可以类比于 TCP/IP 中的"滑动窗口"。

所以消息不会被处理速度很慢的消费者过多霸占,能够很好的分配到其它处理速度较好的消费者中。通俗的说就是消费者最多从 RabbitMQ 中获取的未消费消息的数量。

prefetch Count数量设置为多少合适呢?大概就是30吧

RocketMq


对延时消息机制的思考

优点:

设计简单,把所有相同延迟时间的消息都先放到一个队列中,做定时扫描,可以保证消息消费的有序性;

延时队列中的消息时按消息到期时间进行递增排序,也就是说队列中消息越靠前的到期时间越早;

缺点:

 
延时消息机制所有的定时任务都在一个定时器中,定时器采用的java.util.Timer,而Timer是单线程运行的;如果延迟消息的数量很大大的话,可能单线程处理不过来,也就会造成消息到期后没有及时发送出去的现象,甚至会造成消息拥堵;

可能的改进点:

-   为每个延迟队列上分别采用一个Timer;
-   或者说仅使用Timer开始定时任务做扫描,而消息处理的核心逻辑使用线程池处理,进而提高消息处理的效率;


timer 设计 


基于大顶堆 小顶堆 堆排序实现任务队列 , 任务执行时间没到时 需要sleep() 或者 wait( 剩余时间)