1. Go 新手笔记

    Go 学习笔记

    2019/05/26 Go

  2. php 新手笔记

    php学习笔记

    2019/05/10 php

  3. Guava RateLimiter限流

    Guava RateLimiter限流 缓存,降级和限流是大型分布式系统中的三把利剑。目前限流主要有漏桶和令牌桶两种算法。 缓存:缓存的目的是减少外部调用,提高系统响速度。俗话说:”缓存是网站优化第一定律”。缓存又分为本机缓存和分布式缓存,本机缓存是针对当前JVM实例的缓存,可以直接使用JDK Collection框架里面的集合类或者诸如Google Guava Cache来做本地缓存;分布式缓存目前主要有Memcached,Redis等。 降级:所谓降级是指在系统调用高峰时,优先保证我们的核心服务,对于非核心服务可以选择将其关闭以保证核心服务的可用。例如在淘宝双11时,支付功能是核心,其他诸如用户中心等非核心功能可以选择降级,优先保证交易。 限流:任何系统的性能都有一个上限,当并发量超过这个上限之后,可1能会对系统造成毁灭性地打击。因此在任何时刻我们都必须保证系统的并发请求数量不能超过某个阈值,限流就是为了完成这一目的。

    2019/02/20 Java 算法

  4. 如何让两个线程交替打印数字

    如何让两个线程交替打印数字

    2019/01/27 Java 算法

  5. 基于Redis的分布式锁到底安全吗?

    [转载]基于Redis的分布式锁到底安全吗?

    2019/01/26 Redis

  6. Java中断机制

    Java中断机制

    2019/01/26 Java

  7. ExecutorService shutdown()和shutdownNow()方法区别

    ExecutorService shutdown()和shutdownNow()方法区别 ExecutorService是我们经常使用的线程池,当我们使用完线程池后,需要关闭线程池。ExecutorService的shutdown()和shutdownNow()方法都可以用来关闭线程池,那么他们有什么区别呢?

    2019/01/24 Java

  8. 优惠劵系统库存设计浅谈

    优惠劵系统库存设计浅谈

    2019/01/21 Java Redis

  9. Java中的伪共享

    Java中的伪共享(false sharing) 维基百科中对伪共享的定义如下: In computer science, false sharing is a performance-degrading usage pattern that can arise in systems with distributed, coherent caches at the size of the smallest resource block managed by the caching mechanism. When a system participant attempts to periodically access data that will never be altered by another party, but those data shares a cache block with data that are altered, the caching protocol may force the first participant to reload the whole unit despite a lack of logical necessity. The caching system is unaware of activity within this block and forces the first participant to bear the caching system overhead required by true shared access of a resource. 其大致意思是: CPU的缓存是以缓存行(cache line)为单位进行缓存的,当多个线程修改不同变量,而这些变量又处于同一个缓存行时就会影响彼此的性能。例如:线程1和线程2共享一个缓存行,线程1只读取缓存行中的变量1,线程2修改缓存行中的变量2,虽然线程1和线程2操作的是不同的变量,由于变量1和变量2同处于一个缓存行中,当变量2被修改后,缓存行失效,线程1要重新从主存中读取,因此导致缓存失效,从而产生性能问题。为了更深入一步理解伪共享,我们先看一下CPU缓存。

    2018/12/26 Java 高性能

  10. 浅谈Disruptor

    浅谈Disruptor Disruptor是一个低延迟(low-latency),高吞吐量(high-throughput)的事件发布订阅框架。通过Disruptor,可以在一个JVM中发布事件,和订阅事件。相对于Java中的阻塞队列(ArrayBlockingQueue,LinkedBlockingQueue),Disruptor的优点是性能更高。它采用了一种无锁的数据结构设计,利用环形数组(RingBuffer)来存放事件,通过对象复用减少垃圾回收进一步提高性能。 从”慢日志”说起 线上有一个接口最近频繁报警(tp99变高),通过监控报警系统定位到问题主要出现在日志打印环节。接口方法入参和出参都会打印”info”日志,我们采用的日志是logback。它默认的是同步打印日志,在日志报文过大时,磁盘IO耗时会变得更加明显。某个慢请求90%的处理时间都消耗在日志打印中。于是我们决定采用异步的方式打印日志。sl4j2日志框架支持异步的日志打印,改成异步日志打印之后接口性能报警消失。而sl4j2高性能的秘密就在于Disruptor。 Disruptor解决的问题 设想一下,在一个JVM中当我们有多个消息的生产者线程,一个消费者线程时,他们之间如何进行高并发、线程安全的协调?很简单,用一个阻塞队列。 当我们有多个消息的生产者线程,多个消费者线程,并且每一条消息需要被所有的消费者都消费一次(这就不是一般队列,只消费一次的语义了),该怎么做? 这时仍然需要一个队列。但是: 每个消费者需要自己维护一个指针,知道自己消费了队列中多少数据。这样同一条消息,可以被多个人独立消费。 队列需要一个全局指针,指向最后一条被所有生产者加入的消息。消费者在消费数据时,不能消费到这个全局指针之后的位置——因为这个全局指针,已经是代表队列中最后一条可以被消费的消息了。 需要协调所有消费者,在消费完所有队列中的消息后,阻塞等待。 如果消费者之间有依赖关系,即对同一条消息的消费顺序,在业务上有固定的要求,那么还需要处理谁先消费,谁后消费同一条消息的问题。 总而言之,如果有多个生产者,多个消费者,并且同一条消息要给到所有的消费者都去处理一下,需要做到以上4点。这是不容易的。 LMAX Disruptor,正是这种场景下,满足以上4点要求的单机跨线程消息传递、分发的开源、高性能实现。 关键概念 RingBuffer 应用需要传递的消息在Disruptor中称为Event(事件)。 RingBuffer是Event的数组,实现了阻塞队列的语义: 如果RingBuffer满了,则生产者会阻塞等待。 如果RingBuffer空了,则消费者会阻塞等待。 Sequence 在上文中,我提到“每个消费者需要自己维护一个指针”。这里的指针就是一个单调递增长整数(及其基于CAS的加法、获取操作),称为Sequence。 除了每个消费者需要维护一个指针外,RingBuffer自身也要维护一个全局指针(如上一节第2点所提到的),记录最后一条可以被消费的消息。

    2018/12/25 Java 高性能