热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java高并发系统设计之缓存篇

java基础栏目今天介绍java高并发系统设计的缓存篇。

java基础栏目今天介绍java高并发系统设计的缓存篇。

Write Through

的策略是这样的:先查询要写入的数据在缓存中是否已经存在,如果已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,如果缓存中数据不存在,我们把这种情况叫做“Write Miss(写失效)”。一般来说,我们可以选择两种“Write Miss”方式:一个是“Write Allocate(按写分配)”,做法是写入缓存相应位置,再由缓存组件同步更新到数据库中;另一个是“No-write allocate(不按写分配)”,做法是不写入缓存中,而是直接更新到数据库中。 我们看到 Write Through 策略中写数据库是同步的,这对于性能来说会有比较大的影响,因为相比于写缓存,同步写数据库的延迟就要高很多了。通过Write Back策略异步的更新数据库。

Read Through

策略就简单一些,它的步骤是这样的:先查询缓存中数据是否存在,如果存在则直接返回,如果不存在,则由缓存组件负责从数据库中同步加载数据。

3、Write Back

这个策略的核心思想是在写入数据时只写入缓存,并且把缓存块儿标记为“脏”的。而脏块儿只有被再次使用时才会将其中的数据写入到后端存储中。 在“Write Miss”的情况下,我们采用的是“Write Allocate”的方式,也就是在写入后端存储的同时要写入缓存,这样我们在之后的写请求中都只需要更新缓存即可,而无需更新后端存储了。注意与上面的write through策略作区分。

write back策略多用于向磁盘中写数据。例如:操作系统层面的 Page Cache、日志的异步刷盘、消息队列中消息的异步写入磁盘等。因为这个策略在性能上的优势毋庸置疑,它避免了直接写磁盘造成的随机写问题,毕竟写内存和写磁盘的随机 I/O 的延迟相差了几个数量级呢。

四、缓存高可用

缓存的命中率是缓存需要监控的数据指标,缓存的高可用可以一定程度上减少缓存穿透的概率,提升系统的稳定性。缓存的高可用方案主要包括客户端方案、中间代理层方案和服务端方案三大类:

1、客户端方案

在客户端方案中,你需要关注缓存的写和读两个方面: 写入数据时,需要把被写入缓存的数据分散到多个节点中,即进行数据分片; 读数据时,可以利用多组的缓存来做容错,提升缓存系统的可用性。关于读数据,这里可以使用主从和多副本两种策略,两种策略是为了解决不同的问题而提出的。 具体的实现细节包括:数据分片、主从、多副本

数据分片

一致性Hash算法。在这个算法中,我们将整个 Hash 值空间组织成一个虚拟的圆环,然后将缓存节点的 IP 地址或者主机名做 Hash 取值后,放置在这个圆环上。当我们需要确定某一个 Key 需要存取到哪个节点上的时候,先对这个 Key 做同样的 Hash 取值,确定在环上的位置,然后按照顺时针方向在环上“行走”,遇到的第一个缓存节点就是要访问的节点。

这时如果在 Node 1 和 Node 2 之间增加一个 Node 5,你可以看到原本命中 Node 2 的 Key 3 现在命中到 Node 5,而其它的 Key 都没有变化;同样的道理,如果我们把 Node 3 从集群中移除,那么只会影响到 Key 5 。所以你看,在增加和删除节点时,只有少量的 Key 会“漂移”到其它节点上,而大部分的 Key 命中的节点还是会保持不变,从而可以保证命中率不会大幅下降。 【提示】一致性hash出现的缓存雪崩现象使用虚拟节点解决。一致性hash分片与hash分片的区别在于,缓存命中率的问题,hash分片在存在机器加入或是减少的情况时候,会导致缓存失效,缓存命中率下降。

主从

Redis 本身支持主从的部署方式,但是 Memcached 并不支持,Memcached 的主从机制是如何在客户端实现的。为每一组 Master 配置一组 Slave,更新数据时主从同步更新。读取时,优先从 Slave 中读数据,如果读取不到数据就穿透到 Master 读取,并且将数据回种到 Slave 中以保持 Slave 数据的热度。主从机制最大的优点就是当某一个 Slave 宕机时,还会有 Master 作为兜底,不会有大量请求穿透到数据库的情况发生,提升了缓存系统的高可用性。

多副本

主从方式已经能够解决大部分场景的问题,但是对于极端流量的场景下,一组 Slave 通常来说并不能完全承担所有流量,Slave 网卡带宽可能成为瓶颈。为了解决这个问题,我们考虑在 Master/Slave 之前增加一层副本层,整体架构是这样的:

布隆过滤器优点:

(1)性能高。无论是写入操作还是读取操作,时间复杂度都是 O(1) 是常量值

(2)节省空间。比如,20 亿的数组需要 2000000000/8/1024/1024 = 238M 的空间,而如果使用数组来存储,假设每个用户 ID 占用 4 个字节的空间,那么存储 20 亿用户需要 2000000000 * 4 / 1024 / 1024 = 7600M 的空间,是布隆过滤器的 32 倍。

布隆过滤器缺点:

(1)它在判断元素是否在集合中时是有一定错误几率的,比如它会把不是集合中的元素判断为处在集合中。

原因:Hash算法本身的缺陷。

解决方案:使用多个 Hash 算法为元素计算出多个 Hash 值,只有所有 Hash 值对应的数组中的值都为 1 时,才会认为这个元素在集合中。

(2)不支持删除元素。布隆过滤器不支持删除元素的缺陷也和 Hash 碰撞有关。举一个例子,假如两个元素 A 和 B 都是集合中的元素,它们有相同的 Hash 值,它们就会映射到数组的同一个位置。这时我们删除了 A,数组中对应位置的值也从 1 变成 0,那么在判断 B 的时候发现值是 0,也会判断 B 是不在集合中的元素,就会得到错误的结论。

解决方案:我会让数组中不再只有 0 和 1 两个值,而是存储一个计数。比如如果 A 和 B 同时命中了一个数组的索引,那么这个位置的值就是 2,如果 A 被删除了就把这个值从 2 改为 1。这个方案中的数组不再存储 bit 位,而是存储数值,也就会增加空间的消耗。

4、狗桩效应

比方说当有一个极热点的缓存项,它一旦失效会有大量请求穿透到数据库,这会对数据库造成瞬时极大的压力,我们把这个场景叫做“dog-pile effect”(狗桩效应)。解决狗桩效应的思路是尽量地减少缓存穿透后的并发,方案也比较简单:

(1)在代码中控制在某一个热点缓存项失效之后启动一个后台线程,穿透到数据库,将数据加载到缓存中,在缓存未加载之前,所有访问这个缓存的请求都不再穿透而直接返回。

(2)通过在 Memcached 或者 Redis 中设置分布式锁,只有获取到锁的请求才能够穿透到数据库

六、CDN

1、静态资源加速的原因

在我们的系统中存在着大量的静态资源请求:对于移动 APP 来说,这些静态资源主要是图片、视频和流媒体信息;对于 Web 网站来说,则包括了 Javascript 文件、CSS 文件、静态 HTML 文件等等。它们的读请求量极大并且对访问速度的要求很高还占据了很高的带宽,这时会出现访问速度慢带宽被占满影响动态请求的问题,那么你就需要考虑如何针对这些静态资源进行读加速了。

2、CDN

静态资源访问的关键点是就近访问,即北京用户访问北京的数据,杭州用户访问杭州的数据,这样才可以达到性能的最优。我们考虑在业务服务器的上层增加一层特殊的缓存,用来承担绝大部分对于静态资源的访问,这一层特殊缓存的节点需要遍布在全国各地,这样可以让用户选择最近的节点访问。缓存的命中率也需要一定的保证,尽量减少访问资源存储源站的请求数量(回源请求)。这一层缓存就是CDN。

CDN(Content Delivery Network/Content Distribution Network,内容分发网络)。简单来说,CDN 就是将静态的资源分发到位于多个地理位置机房中的服务器上,因此它能很好地解决数据就近访问的问题,也就加快了静态资源的访问速度。

3、搭建CDN系统

搭建一个 CDN 系统需要考虑哪两点:

(1)如何将用户的请求映射到 CDN 节点上

你可能会觉得这很简单啊,只需要告诉用户 CDN 节点的 IP 地址,然后请求这个 IP 地址上面部署的 CDN 服务就可以了啊。但是,并不是这样,需要把ip替换为相应的域名。那么如何做到这一点呢?这就需要依靠 DNS 来帮我们解决域名映射的问题了。DNS(Domain Name System,域名系统)实际上就是一个存储域名和 IP 地址对应关系的分布式数据库。而域名解析的结果一般有两种,一种叫做“A 记录”,返回的是域名对应的 IP 地址;另一种是“CNAME 记录”,返回的是另一个域名,也就是说当前域名的解析要跳转到另一个域名的解析上。

举个例子:比如你的公司的一级域名叫做 example.com,那么你可以把你的图片服务的域名定义为“img.example.com”,然后将这个域名的解析结果的 CNAME 配置到 CDN 提供的域名上,比如 uclound 可能会提供一个域名是“80f21f91.cdn.ucloud.com.cn”这个域名。这样你的电商系统使用的图片地址可以是“img.example.com/1.jpg”。

用户在请求这个地址时,DNS 服务器会将域名解析到 80f21f91.cdn.ucloud.com.cn 域名上,然后再将这个域名解析为 CDN 的节点 IP,这样就可以得到 CDN 上面的资源数据了。

域名层级解析优化

因为域名解析过程是分级的,每一级有专门的域名服务器承担解析的职责,所以域名的解析过程有可能需要跨越公网做多次 DNS 查询,在性能上是比较差的。一个解决的思路是:在 APP 启动时对需要解析的域名做预先解析,然后把解析的结果缓存到本地的一个 LRU 缓存里面。这样当我们要使用这个域名的时候,只需要从缓存中直接拿到所需要的 IP 地址就好了,如果缓存中不存在才会走整个 DNS 查询的过程。同时为了避免 DNS 解析结果的变更造成缓存内数据失效,我们可以启动一个定时器定期地更新缓存中的数据。

(2)如何根据用户的地理位置信息选择到比较近的节点。

GSLB(Global Server Load Balance,全局负载均衡)的含义是对于部署在不同地域的服务器之间做负载均衡,下面可能管理了很多的本地负载均衡组件。它有两方面的作用:一方面,它是一种负载均衡服务器,负载均衡,顾名思义嘛,指的是让流量平均分配使得下面管理的服务器的负载更平均;另一方面,它还需要保证流量流经的服务器与流量源头在地缘上是比较接近的。

GSLB 可以通过多种策略来保证返回的 CDN 节点和用户尽量保证在同一地缘区域,比如说可以将用户的 IP 地址按照地理位置划分为若干个区域,然后将 CDN 节点对应到一个区域上,根据用户所在区域来返回合适的节点;也可以通过发送数据包测量 RTT 的方式来决定返回哪一个节点。

总结:DNS 技术是 CDN 实现中使用的核心技术,可以将用户的请求映射到 CDN 节点上;DNS 解析结果需要做本地缓存,降低 DNS 解析过程的响应时间;GSLB 可以给用户返回一个离着他更近的节点,加快静态资源的访问速度。

拓展

(1)百度域名的解析过程

一开始,域名解析请求先会检查本机的 hosts 文件,查看是否有 www.baidu.com 对应的 IP;如果没有的话,就请求 Local DNS 是否有域名解析结果的缓存,如果有就返回标识是从非权威 DNS 返回的结果;如果没有就开始 DNS 的迭代查询。先请求根 DNS,根 DNS 返回顶级 DNS(.com)的地址;再请求.com 顶级 DNS 得到 baidu.com 的域名服务器地址;再从 baidu.com 的域名服务器中查询到 www.baidu.com 对应的 IP 地址,返回这个 IP 地址的同时标记这个结果是来自于权威 DNS 的结果,同时写入 Local DNS 的解析结果缓存,这样下一次的解析同一个域名就不需要做 DNS 的迭代查询了。

(2)CDN延时

一般我们会通过 CDN 厂商的接口将静态的资源写入到某一个 CDN 节点上,再由 CDN 内部的同步机制将资源分散同步到每个 CDN 节点,即使 CDN 内部网络经过了优化,这个同步的过程是有延时的,一旦我们无法从选定的 CDN 节点上获取到数据,我们就不得不从源站获取数据,而用户网络到源站的网络可能会跨越多个主干网,这样不仅性能上有损耗也会消耗源站的带宽,带来更高的研发成本。所以我们在使用 CDN 的时候需要关注 CDN 的命中率和源站的带宽情况。

相关学习推荐:java基础

以上就是java高并发系统设计之缓存篇的详细内容,更多请关注其它相关文章!


推荐阅读
  • 本文介绍了Paxos的世界中关于复制日志与状态机的概念和重要性。通过存储日志来实现数据的持久化,并通过日志流来记录数据的变化,而不是直接持久化数据本身。这样做的好处是简化了持久化存储的操作,并且方便多机之间的数据同步。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 解决github访问慢的问题的方法集锦
    本文总结了国内用户在访问github网站时可能遇到的加载慢的问题,并提供了解决方法,其中包括修改hosts文件来加速访问。 ... [详细]
author-avatar
阿川那小子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有