Guava

谈谈高并发系统的限流

本秂侑毒 提交于 2020-09-27 04:40:26
开涛大神在博客中说过: 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流 。本文结合作者的一些经验介绍限流的相关概念、算法和常规的实现方式。 缓存 缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪。使用缓存不单单能够提升系统访问速度、提高并发访问量,也是保护数据库、保护系统的有效方式。大型网站一般主要是“读”,缓存的使用很容易被想到。在大型“写”系统中,缓存也常常扮演者非常重要的角色。比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及HBase写数据的机制等等也都是通过缓存提升系统的吞吐量或者实现系统的保护措施。甚至消息中间件,你也可以认为是一种分布式的数据缓存。 降级 服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。 限流 限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行

带你100% 地了解 Redis 6.0 的客户端缓存

牧云@^-^@ 提交于 2020-09-24 08:34:40
点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 近日 Redis 6.0.0 GA 版本发布,这是 Redis 历史上最大的一次版本更新,包括了客户端缓存 (Client side caching)、ACL、Threaded I/O 和 Redis Cluster Proxy 等诸多更新。 我们今天就依次聊一下客户端缓存的必要性、具体使用、原理分析和实现。 为什么需要客户端缓存? 我们都知道,使用 Redis 进行数据的缓存的主要目的是减少对 MySQL 等数据库的访问,提供更快的访问速度,毕竟 《Redis in Action》中提到的, Redis 的性能大致是普通关系型数据库的 10 ~ 100 倍。 所以,如下图所示,Redis 用来存储热点数据,Redis 未命中,再去访问数据库,这样可以应付大多数情况下的性能要求。 但是,Redis 也有其性能上限,并且访问 Redis 必然有一定的网络 I/O 以及序列化反序列化损耗。所以,往往会引入进程缓存,将最热的数据存储在本地,进一步加快访问速度。 如上图所示 (示意图,细节不必过度在意,下同) ,Guava Cache 等进程缓存作为一级缓存,Redis 作为二级缓存: 先去 Guava Cache 中查询数据,如果命中则直接返回。 Guava Cache 中未命中,则再去 Redis 中查询,如果命中则返回数据

使用谷歌 Guava 实现 Java 一致性哈希 (用于根据哈希Hash值平均分配的场景)

心不动则不痛 提交于 2020-08-19 22:30:30
1. pom.xml 文件引入依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>29.0-jre</version> </dependency> 2. java 代码 HashFunction hashFunction = Hashing.sha512(); int buckets = 2; // 要平均分为几份 int hashCode = Hashing.consistentHash(hashFunction.hashString("XXXXXXXXXXXXXX", Charsets.UTF_8), buckets); // 然后就可以对 buckets 取余, 平均分配 if (hashCode % buckets == 0) { // XXXXXXX } else { // XXXXXXX } Guava 的一致性 Hash 算法, 只能保证大概的平均, 不能保证绝对的平均. 来源: oschina 链接: https://my.oschina.net/zdtdtel/blog/4369080

RateLimiter具体实现

佐手、 提交于 2020-08-19 17:24:43
由 Guava 提供的单机版本基于令牌桶算法 的限流工具。 通过限制后面请求的等待时间,来支持一定程度的突发请求(预消费) 两种模式: SmoothBursty (稳定模式): 平滑突发限流 。 SmoothWarmingUp (渐进模式): 平滑预热限流。 关键在于其分发令牌的速率会随库存令牌数而改变。 等存储令牌数从 maxPermits 降低到 thresholdPermits 时,发放令牌的时间也由 coldInterval 降低到了正常的 stableInterval 。也就是说消耗令牌越快时,生成令牌也越快。 表现形式如下图所示: 特点: 本次请求 当库存令牌不足以满足本次需求时, ( 差额令牌的创建时间 + 可获取令牌时间 ) - 当前时间 = 请求阻塞时间,但下一次请求才是真正按这个时间来阻塞等待! 构造函数里有一个参数 RateLimiter & SleepingStopwatch , 最终执行java.util.concurrent. TimeUnit . sleep 方法控制请求阻塞指定市场。 在核心 方法中使用 synchronized 加锁来控制并发。 成员变量 storedPermits : 当前存储令牌数 maxPermits : 最大存储令牌数 stableIntervalMicros :生成单个令牌需要时间。 eg. 比如说是每秒5个

hive-3.1.2 整合进 hadoop-3.3.0 + hbase-2.2.4

心不动则不痛 提交于 2020-08-19 17:22:30
一、下载匹配hadoop-3.x.y 版本的hive 3.1.2 下载地址 : http://mirror.bit.edu.cn/apache/hive/ 二、上传至安装目录 /home/apache-hive-3.1.2-bin.tar.gz 解压:tar -zxvf apache-hive-3.1.2-bin.tar.gz 后重命名目录:/home/hive-3.1.2 三、编辑 /etc/profile 文件 ...... if [ -n "${BASH_VERSION-}" ] ; then if [ -f /etc/bashrc ] ; then # Bash login shells run only /etc/profile # Bash non-login shells run only /etc/bashrc # Check for double sourcing is done in /etc/bashrc. . /etc/bashrc fi fi export JAVA_HOME =/usr/java/jdk1.8.0_131 export JRE_HOME = ${JAVA_HOME}/jre export HADOOP_HOME =/home/hadoop-3.3.0 export HIVE_HOME=/home/hive-3.1.2 export

精美图文讲解Java AQS 共享式获取同步状态以及Semaphore的应用

巧了我就是萌 提交于 2020-08-19 04:13:48
| 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough 现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star🌟 看到本期内容这么少,是不是心动了呢? 前言 上一篇万字长文 Java AQS队列同步器以及ReentrantLock的应用 为我们读 JUC 源码以及其设计思想做了足够多的铺垫,接下来的内容我将重点说明差异化,如果有些童鞋不是能很好的理解文中的一些内容,强烈建议回看上一篇文章,搞懂基础内容,接下来的阅读真会轻松加愉快 AQS 中我们介绍了独占式获取同步状态的多种情形: 独占式获取锁 可响应中断的独占式获取锁 有超时限制的独占式获取锁 AQS 提供的模版方法里面还差共享式获取同步状态没有介绍,所以我们今天来揭开这个看似神秘的面纱 AQS 中的共享式获取同步状态 独占式是你中没我,我中没你的的一种互斥形式,共享式显然就不是这样了,所以他们的唯一区别就是: 同一时刻能否有多个线程同时获取到同步状态 简单来说,就是这样滴: 我们知道同步状态 state 是维护在 AQS 中的,抛开可重入锁的概念,我在上篇文章中也提到了

hive-3.1.2 整合进 hadoop-3.3.0 + hbase-2.2.4

前提是你 提交于 2020-08-17 16:11:15
一、下载匹配hadoop-3.x.y 版本的hive 3.1.2 下载地址 : http://mirror.bit.edu.cn/apache/hive/ 二、上传至安装目录 /home/apache-hive-3.1.2-bin.tar.gz 解压:tar -zxvf apache-hive-3.1.2-bin.tar.gz 后重命名目录:/home/hive-3.1.2 三、编辑 /etc/profile 文件 ...... if [ -n "${BASH_VERSION-}" ] ; then if [ -f /etc/bashrc ] ; then # Bash login shells run only /etc/profile # Bash non-login shells run only /etc/bashrc # Check for double sourcing is done in /etc/bashrc. . /etc/bashrc fi fi export JAVA_HOME =/usr/java/jdk1.8.0_131 export JRE_HOME = ${JAVA_HOME}/jre export HADOOP_HOME =/home/hadoop-3.3.0 export HIVE_HOME=/home/hive-3.1.2 export

常用限流算法与Guava RateLimiter源码解析

假如想象 提交于 2020-08-17 07:53:12
在分布式系统中,应对高并发访问时,缓存、限流、降级是保护系统正常运行的常用方法。当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用。同时有一些业务场景,比如短信验证码,或者其它第三方API调用,也需要提供必要的访问限制支持。还有一些资源消耗过大的请求,比如数据导出等(参考 记一次线上Java服务CPU 100%处理过程 ),也有限制访问频率的需求。 常见的限流算法有令牌桶算法,漏桶算法,与计数器算法。本文主要对三个算法的基本原理及Google Guava包中令牌桶算法的实现RateLimiter进行介绍,下一篇文章介绍最近写的一个以RateLimiter为参考的分布式限流实现及计数器限流实现。 令牌桶算法 令牌桶算法的原理就是以一个恒定的速度往桶里放入令牌,每一个请求的处理都需要从桶里先获取一个令牌,当桶里没有令牌时,则请求不会被处理,要么排队等待,要么降级处理,要么直接拒绝服务。当桶里令牌满时,新添加的令牌会被丢弃或拒绝。 令牌桶算法的处理示意图如下(图片来自网络) 令牌桶算法主要是可以控制请求的平均处理速率,它允许预消费,即可以提前消费令牌,以应对突发请求,但是后面的请求需要为预消费买单(等待更长的时间),以满足请求处理的平均速率是一定的。 漏桶算法 漏桶算法的原理是水(请求)先进入漏桶中,漏桶以一定的速度出水(处理请求)

Redis缓存的使用与设计

别来无恙 提交于 2020-08-14 18:57:13
1. 缓存的收益与成本 1. 收益: 加速读写 读缓存中的数据要比读数据存储位置的速度要快。(例如:寄存器-内存,内存-磁盘) 降低后端负载 如果不加缓存的话,并发的压力会直接加到后端数据库上,并发较大的时候,数据库可能会hold不住,而这里可以通过增加一层缓存,通过直接访问缓存不仅访问速度更快,而且减少了io次数,减少了数据库的压力。 2. 成本: 数据不一致: 缓存层是数据层的时间窗口不一致,和更新策略有关。 代码维护成本: 多了一层缓存逻辑 运维成本: 例如Redis Cluster… 2. 缓存更新策略 1. LRU/LFU/FIFO(一致性差,维护成本低) 2. 超时剔除: 例如expire(一致性差,维护成本低) 对于一些可以容忍数据不一致性的情况,可以使用这种策略。 3. 主动更新:开发控制生命周期(一致性较强,维护成本较高) 可以利用发布-订阅这种思想,在缓存来监听数据是否发生变化,若发生变化则失效. (例如volatile关键字的实现,缓存一致性协议中的嗅探机制,就是使用的这一策略, 也可利用消息队列来维护最终一致性) 低一致性: 最大内存和淘汰策略 高一致性:超时剔除和主动更新结合,最大内存和淘汰策略兜底(防OOM)。 3. 缓存的粒度控制 缓存的粒度,以缓存mysql中的数据为例,例如查询用户信息操作频繁,那么应该缓存用户信息的所有属性(select *)