当前位置:首页 » 硬盘大全 » 分布式缓存集群性能搜索
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

分布式缓存集群性能搜索

发布时间: 2023-03-26 01:19:08

‘壹’ EhCache 分布式缓存/缓存集群

一 缓存系统简介 EhCache 是一个纯 Java 的进程内缓存框架 具有快速 精干等特点 是 Hibernate 中默认的 CacheProvider EhCache 应用架构图 下图是 EhCache 在应用程序中的位置

EhCache 的主要特性有 快速 精干 简单 多种缓存策略 缓存数据有两级 内存和磁盘 因此无需担心容量问题 缓存数据会在虚拟机重启的过程中写入磁盘 可以通过 RMI 可插入 API 等方式进行分布式缓存 具有缓存和缓存管理器的侦听接口 支持多缓存管理器实例 以及一个实例的多个缓存区域 提供 Hibernate 的缓存实现 由于 EhCache 是进程中的缓存系统 一旦将应用部署在集群环境中 每一个节点维护各自的缓存数据 当某个节点对缓存数据进行更新 这些更新的数据无法在其它节点 *** 享 这不仅会降低节点运行的效率 而且会导致数据不同步的情况发生 例如某个网站采用 A B 两个节点作为集群部署 当 A 节点的缓存更新后 而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候 一会是更新后的数据 一会是尚未更新的数据 尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上 但对于一些交互性比较强或者是非 Web 方式的系统来说 Session Sticky 显然不太适合 所以就需要用到 EhCache 的集群解决方案 从 版本开始 Ehcache可以使用分布式的缓存了 EhCache 从 版本开始 支持五种集群方案 分别是 ? Terracotta ? RMI ? JMS ? JGroups ? EhCache Server 其中的三种最为常用集群方式 分别是 RMI JGroups 以及 EhCache Server 本文主要介绍RMI的方式 分布式这个特性是以plugin的方式实现的 Ehcache自带了一些默认的分布式缓存插件实现 这些插件可以满足大部分应用的需要 如果需要使用其他的插件那就需要自己开发了 开发者可以通过查看distribution包里的源代码及JavaDoc来实现它 尽管不是必须的 在使用分布式缓存时理解一些ehcahce的设计思想也是有帮助的 这可以参看分布式缓存设计的页面 以下的部分将展示如何让分布式插件同ehcache一起工作 下面列出的是一些分布式缓存中比较重要的方面 ? 你如何知道集群环境中的其他缓存? ? 分布式传送的消息是什么形式? ? 什么情况需要进行复制?增加(Puts) 更新(Updates)或是失效(Expiries)? ? 采用什么方式进行复制?同步还是异步方式? 为了安装分布式缓存 你需要配置一个PeerProvider 一个CacheManagerPeerListener 它们对于一个CacheManager来说是全局的 每个进行分布式操作的cache都要添加一个cacheEventListener来传送消息

二 集群缓存概念及其配置 正确的元素类型 只有可序列化的元素可以进行复制 一些操作 比如移除 只需要元素的键值而不用整个元素 在这样的操作中即使元素不是可序列化的但键值是可序列化的也可以被复制 成员发现(Peer Discovery) Ehcache进行集群的时候有一个cache组的概念 每个cache都是其他cache的一个peer 没有主cache的存在 刚才我们问了一个问题 你如何知道集群环境中的其他缓存?这个问题可以命名为成员发现(Peer Discovery) Ehcache提供了两种机制用来进行成员发现 就像一辆汽车 手动档和自动档 要使用一个内置的成员发现机制要在ehcache的配置文件中指定元素的class属性为 net sf ehcache distribution 自动的成员发现 自动的发现方式用TCP广播机制来确定和维持一个广播组 它只需要一个简单的配置可以自动的在组中添加和移除成员 在集群中也不需要什么优化服务器的知识 这是默认推荐的 成员每秒向群组发送一个 心跳 如果一个成员 秒种都没有发出信号它将被群组移除 如果一个新的成员发送了一个 心跳 它将被添加进群组 任何一个用这个配置安装了复制功能的cache都将被其他的成员发现并标识为可用状态 要设置自动的成员发现 需要指定ehcache配置文件中元素的properties属性 就像下面这样 peerDiscovery=automatic multicastGroupAddress=multicast address | multicast host name multicastGroupPort=port timeToLive= (timeToLive属性详见常见问题部分的描述) 示例 假设你在集群中有两台服务器 你希望同步sampleCache 和sampleCache 每台独立的服务器都要有这样的配置 配置server 和server <class= net sf ehcache distribution properties= peerDiscovery=automatic multicastGroupAddress= />multicastGroupPort= timeToLive= 手动进行成员发现 进行手动成员配置要知道每个监听器的IP地址和端口 成员不能在运行时动态地添加和移除 在技术上很难使用广播的情况下就可以手动成员发现 例如在集群的服务器之间有一个不能传送广播报文的路由器 你也可以用手动成员发现进行单向的数据复制 只让server 知道server 而server 不知道server 配置手动成员发现 需要指定ehcache配置文件中的properties属性 像下面这样 peerDiscovery=manual rmiUrls=//server:port/cacheName //server:port/cacheName … rmiUrls配置的是服务器cache peers的列表 注意不要重复配置 示例 假设你在集群中有两台服务器 你要同步sampleCache 和sampleCache 下面是每个服务器需要的配置 配置server <class= net sf ehcache distribution properties= peerDiscovery=manual />rmiUrls=//server : /sampleCache |//server : /sampleCache 配置server <class= net sf ehcache distribution properties= peerDiscovery=manual />rmiUrls=//server : /sampleCache |//server : /sampleCache 配置CacheManagerPeerListener 每个CacheManagerPeerListener监听从成员们发向当前CacheManager的消息 配置CacheManagerPeerListener需要指定一个 它以插件的机制实现 用来创建CacheManagerPeerListener 的属性有 class – 一个完整的工厂类名 properties – 只对这个工厂有意义的属性 使用逗号分隔 Ehcache有一个内置的基于RMI的分布系统 它的监听器是RMICacheManagerPeerListener 这个监听器可以用 RMI来配置 <class= net sf ehcache distribution RMI properties= hostName=localhost port= />socketTimeoutMillis= 有效的属性是 hostname (可选) – 运行监听器的服务器名称 标明了做为集群群组的成员的地址 同时也是你想要控制的从集群中接收消息的接口

在CacheManager初始化的时候会检查hostname是否可用 如果hostName不可用 CacheManager将拒绝启动并抛出一个连接被拒绝的异常 如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到 警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置 port – 监听器监听的端口 socketTimeoutMillis (可选) – Socket超时的时间 默认是 ms 当你socket同步缓存请求地址比较远 不是本地局域网 你可能需要把这个时间配置大些 不然很可能延时导致同步缓存失败 配置CacheReplicators 每个要进行同步的cache都需要设置一个用来向CacheManagerr的成员复制消息的缓存事件监听器 这个工作要通过为每个cache的配置增加一个cacheEventListenerFactory元素来完成 <! Sample cache named sampleCache ><cache name= sampleCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false ><cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true /></cache>class – 使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的(指定为true时)还是同步的(指定为false时) 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制(指定为true时为复制) 默认是true 你可以使用ehcache的默认行为从而减少配置的工作量 默认的行为是以异步的方式复制每件事 你可以像下面的例子一样减少RMICacheReplicatorFactory的属性配置 <! Sample cache named sampleCache All missing RMICacheReplicatorFactory properties default to true ><cache name= sampleCache maxElementsInMemory= eternal= true overflowToDisk= false memoryStoreEvictionPolicy= LFU ><cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory /></cache> 常见的问题 Windows上的Tomcat 有一个Tomcat或者是JDK的bug 在tomcat启动时如果tomcat的安装路径中有空格的话 在启动时RMI监听器会失败 参见 bin/wa?A =ind &L=rmi users&P= 和 doc/faq howto bugs/l 由于在Windows上安装Tomcat默认是装在 Program Files 文件夹里的 所以这个问题经常发生 广播阻断 自动的peer discovery与广播息息相关 广播可能被路由阻拦 像Xen和VMWare这种虚拟化的技术也可以阻拦广播 如果这些都打开了 你可能还在要将你的网卡的相关配置打开 一个简单的办法可以告诉广播是否有效 那就是使用ehcache remote debugger来看 心跳 是否可用 广播传播的不够远或是传得太远 你可以通过设置badly misnamed time to live来控制广播传播的距离 用广播IP协议时 timeToLive的值指的是数据包可以传递的域或是范围 约定如下 是限制在同一个服务器 是限制在同一个子网 是限制在同一个网站 是限制在同一个region 是限制在同一个大洲 是不限制 译者按 上面这些资料翻译的不够准确 请读者自行寻找原文理解吧 在Java实现中默认值是 也就是在同一个子网中传播 改变timeToLive属性可以限制或是扩展传播的范围

三 RMI方式缓存集群/配置分布式缓存 RMI 是 Java 的一种远程方法调用技术 是一种点对点的基于 Java 对象的通讯方式 EhCache 从 版本开始就支持 RMI 方式的缓存集群 在集群环境中 EhCache 所有缓存对象的键和值都必须是可序列化的 也就是必须实现 java io Serializable 接口 这点在其它集群方式下也是需要遵守的 下图是 RMI 集群模式的结构图

采用 RMI 集群模式时 集群中的每个节点都是对等关系 并不存在主节点或者从节点的概念 因此节点间必须有一个机制能够互相认识对方 必须知道其它节点的信息 包括主机地址 端口号等 EhCache 提供两种节点的发现方式 手工配置和自动发现 手工配置方式要求在每个节点中配置其它所有节点的连接信息 一旦集群中的节点发生变化时 需要对缓存进行重新配置 由于 RMI 是 Java 中内置支持的技术 因此使用 RMI 集群模式时 无需引入其它的 Jar 包 EhCache 本身就带有支持 RMI 集群的功能 使用 RMI 集群模式需要在 ehcache xml 配置文件中定义 节点 分布式同步缓存要让这边的cache知道对方的cache 叫做Peer Discovery(成员发现) EHCache实现成员发现的方式有两种 手动查找 A 在ehcache xml中配置PeerDiscovery成员发现对象 Server 配置 配置本地hostName port是 分别监听 : 的mobileCache和 : 的mobileCache 注意这里的mobileCache是缓存的名称 分别对应着server server 的cache的配置 <?xml version= encoding= gbk ?><ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd > <diskStore path= java io tmpdir /> <! 集群多台服务器中的缓存 这里是要同步一些服务器的缓存 server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache 注意 每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置 > <! server 的配置 > < class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache /></ehcache>以上注意元素出现的位置在diskStore下

同样在你的另外 台服务器上增加配置 Server 配置本地host port为 分别同步 : 的mobileCache和 : 的mobileCache <! server 的配置 >< class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache />Server 配置本地host port为 分别同步 : 的mobileCache缓存和 : 的mobileCache缓存 <! server 的配置 >< class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache />这样就在三台不同的服务器上配置了手动查找cache的PeerProvider成员发现的配置了 值得注意的是你在配置rmiUrls的时候要特别注意url不能重复出现 并且端口 地址都是对的 如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到 警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置 B 下面配置缓存和缓存同步监听 需要在每台服务器中的ehcache xml文件中增加cache配置和cacheEventListenerFactory cacheLoaderFactory的配置 <defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /><! 配置自定义缓存 maxElementsInMemory:缓存中允许创建的最大对象数 eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期 timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁 如果该值是 就意味着元素可以停顿无穷长的时间 timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁 这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间 overflowToDisk:内存不足时 是否启用磁盘缓存 memoryStoreEvictionPolicy:缓存满了之后的淘汰算法 每一个小时更新一次缓存( 小时过期) ><cache name= mobileCache maxElementsInMemory= eternal= false overflowToDisk= true timeToIdleSeconds= timeToLiveSeconds= memoryStoreEvictionPolicy= LFU > <! RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true = > <! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire > <cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true /> replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true <! 用于在初始化缓存 以及自动设置 > <bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory /></cache> C 这样就完成了 台服务器的配置 下面给出server 的完整的ehcache xml的配置 <?xml version= encoding= gbk ?><ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd > <diskStore path= java io tmpdir /> <!

集群多台服务器中的缓存 这里是要同步一些服务器的缓存 server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache 注意每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置 > <! server 的配置 > < class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache /> <defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /> <! 配置自定义缓存 maxElementsInMemory:缓存中允许创建的最大对象数 eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期 timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁 如果该值是 就意味着元素可以停顿无穷长的时间 timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁 这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间 overflowToDisk:内存不足时 是否启用磁盘缓存 memoryStoreEvictionPolicy:缓存满了之后的淘汰算法 每一个小时更新一次缓存( 小时过期) > <cache name= mobileCache maxElementsInMemory= eternal= false overflowToDisk= true timeToIdleSeconds= timeToLiveSeconds= memoryStoreEvictionPolicy= LFU > <! RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true = > <! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire > <cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true /> replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true <! 用于在初始化缓存 以及自动设置 > <bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory /> </cache></ehcache> 自动发现 自动发现配置和手动查找的方式有一点不同 其他的地方都基本是一样的 同样在ehcache xml中增加配置 配置如下 <! 搜索某个网段上的缓存timeToLive 是限制在同一个服务器 是限制在同一个子网 是限制在同一个网站 是限制在同一个region 是限制在同一个大洲 是不限制 >< class= net sf ehcache distribution properties= peerDiscovery=automatic multicastGroupAddress= multicastGroupPort= timeToLive= /> lishixin/Article/program/Java/hx/201311/25706

‘贰’ 什么为分布式缓存

分布式缓存主要用于在高并发环境下,减轻数据库的压力,提高系统的响应速度和并发吞吐。当大量的读、写请求涌向数据库时,磁盘的处理速度与内存显然不在一个量级,因此,在数据库之前加一层缓存,能够显着提高系统的响应速度,并降低数据库的压力。作为传统的大竖关系型数据库,Mysql提供完整的ACID操作,支持丰富的数据类型、强大的关联查询、where语句等,能够非常客易地建立查询索引,执行复杂的内连接、外连接、求和、排序、分组等操作,并且支持存储过程、函数等功能,产品成熟度高,功能强大。但是,对于需要应对高并发访问并且存储海量数据的场景来说,出于对性能的考虑,不得不放弃很多传统关系型数据库原本强大的功能,牺牲了系统的易用性,并且使得系统的设计和管理变得更为复杂。这也使得在过去几年中,流行着另一种新的存储解决方案——NoSQL,它与传统的关系型数据库最大的差别在于,它不使用SQL作为查询语言来查找数据,而采用key-value形式进行查找,提供了滚仿闹更高的查询效率及吞吐,并且能够更加方便地进行扩展,存储海量数据,在数千个节点上进行分区,自动进行数据的复制和备份。在分布式系统中,消息作为应用间通信的一种方式,得到了十分广泛的应用。消息可以被保存在队列中,直到被接收者取出,由于消息发送者不需要同步等待消息接收者的响应,消息的异步接收降低了系统集成的耦合度,提升了分布式系统协作大罩的效率,使得系统能够更快地响应用户,提供更高的吞吐。
当系统处于峰值压力时,分布式消息队列还能够作为缓冲,削峰填谷,缓解集群的压力,避免整个系统被压垮。垂直化的搜索引擎在分布式系统中是一个非常重要的角色,它既能够满足用户对于全文检索、模糊匹配的需求,解决数据库like查询效率低下的问题,又能够解决分布式环境下,由于采用分库分表,或者使用NoSQL数据库,导致无法进行多表关联或者进行复杂查询的问题。

‘叁’ 分布式存储最佳缓存比

作者:深入细节的 SmartX 一线技术团队

近日,VMware 发布了 vSAN 8,对存储架构进行了重大更新。其中最主要的变化,即引入了新的 Express Storage Architecture(ESA)架构:用“存储池”替代了原存储架构(OSA)中的“磁盘组”,并不再需要专用 SSD 承担缓存加速功能,一定程度上避免了 8.0 之前版本中的专用缓存盘利用率低、易发生缓存击穿等问题。
而值得一提的是,在 vSAN 大版本更新之前,SmartX 即通过统一缓存空间和智能冷热数据管理优化了分布式存储缓存机制,有效规避了上述问题。本文将通过重点解读 vSAN(以 vSAN 7 为例)和 SmartX 分布式块存储组件 ZBS* 缓存机制的原理,并测试对比两种缓存机制下虚拟机性能表现,让读者更好地了解两种技术实现机制的区别对业务可能带来的实际影响。

* ZBS 内置于 SmartX 超融合软件 SMTX OS,可与 SmartX 原生虚拟化 ELF 搭配提供服务。

本文重点
vSAN 7 采用划分读写缓存空间的机制,将缓存磁盘按照容量占比划分为写缓冲区(30%)和读缓存区(70%)。这种方式可能出现缓存利用率低、在访问数据量过大时导致缓存击穿,进而引起性能下降等问题。
ZBS 采用统一缓存空间的机制,并通过 2 级 LRU 算法对冷热数据进行管理,在充分利用缓存容量的同时避免了因访问量激增导致虚拟机性能下降的情况。
本文基于相同的硬件配置和 I/O 读写场景,分别测试 VMware 超融合(vSphere 虚拟化 + vSAN 分布式存储)写入 300 GB 数据、SMTX OS(ELF + ZBS)写入 500 GB 数据时虚拟机的性能表现。结果显示,vSAN 7 难以充分利用缓存介质,发生缓存击穿,导致存储性能下降;而 SMTX OS 即便在写入更多数据的情况下也未发生缓存击穿,虚拟机性能保持稳定。
场景问题
混闪配置是超融合或分布式存储现阶段的主流落地模式。混闪配置是指机器中的磁盘使用 SSD + HDD 混合组成,其中 SSD 磁盘作为数据缓存层,而 HDD 磁盘作为数据容量层。以该模式构建的分布式存储池通过软件算法进行冷热数据自动判断,在提供高性能的同时,还可获得较大的存储容量,进而提升资源利用率,获得相对全闪存储更高的性价比。

在将 SSD 磁盘用作数据缓存层时,部分超融合产品会将缓存容量(Cache)划分为读和写各自独立的两部分。例如,vSAN 7 及更早版本会将每个磁盘组(Disk Group)中的缓存磁盘,按照容量占比划分为写缓冲区(30%)和读缓存区(70%),当读取数据未命中缓存或者写缓存已满,将会直接从容量层进行读写。

‘肆’ 分布式文件存储系统通过什么方式提高可用性和安全性

分布式存储的六大优点


1. 高性能

一个具有高性能的分布式存户通常能够高效地管理读缓存和写缓存,并且支持自动的分级存储。分布式存储通过将热点区域内数据映射到高速存储中,来提高系统响应速度;一旦这些区域不再是热点,那么存储系统会将它们移出高速存储。而写缓存技术则可使配合高速存储来明显改变整体存储的性能,按照一定的策略,先将数据写入高速存储,再在适当的时间进行同步落盘。

2. 支持分级存储

由于通过网络进行松耦合链接,分布式存储允许高速存储和低速存储分开部署,或者任意比例混布。在不可预测的业务环境或者敏捷应用情况下,分层存储的优势可以发挥到最佳。解决了目前缓存分层存储最大的问题是当性能池读不命中后,从冷池提取数据的粒度太大,导致延迟高,从而给造成整体的性能的抖动的问题。

3. 多副本的一致性

与传统的存储架构使用RAID模式来保证数据的可靠性不同,分布式存储采用了多副本备份机制。在存储数据之前,分布式存储对数据进行了分片,分片后的数据按照一定的规则保存在集群节点上。为了保证多个数据副本之间的一致性,分布式存储通常采用的是一个副本写入,多个副本读取的强一致性技术,使用镜像、条带、分布式校验等方式满足租户对于可靠性不同的需求。在读取数据失败的时候,系统可以通过从其他副本读取数据,重新写入该副本进行恢复,从而保证副本的总数固定;当数据长时间处于不一致状态时,系统会自动数据重建恢复,同时租户可设定数据恢复的带宽规则,最小化对业务的影响。

4. 容灾与备份

在分布式存储的容灾中,一个重要的手段就是多时间点快照技术,使得用户生产系统能够实现一定时间间隔下的各版本数据的保存。特别值得一提的是,多时间点快照技术支持同时提取多个时间点样本同时恢复,这对于很多逻辑错误的灾难定位十分有用,如果用户有多台服务器或虚拟机可以用作系统恢复,通过比照和分析,可以快速找到哪个时间点才是需要回复的时间点,降低了故障定位的难度,缩短了定位时间。这个功能还非常有利于进行故障重现,从而进行分析和研究,避免灾难在未来再次发生。多副本技术,数据条带化放置,多时间点快照和周期增量复制等技术为分布式存储的高可靠性提供了保障。

5. 弹性扩展

得益于合理的分布式架构,分布式存储可预估并且弹性扩展计算、存储容量和性能。分布式存储的水平扩展有以下几个特性:

1) 节点扩展后,旧数据会自动迁移到新节点,实现负载均衡,避免单点过热的情况出现;

2) 水平扩展只需要将新节点和原有集群连接到同一网络,整个过程不会对业务造成影响;

3) 当节点被添加到集群,集群系统的整体容量和性能也随之线性扩展,此后新节点的资源就会被管理平台接管,被用于分配或者回收。

6. 存储系统标准化

随着分布式存储的发展,存储行业的标准化进程也不断推进,分布式存储优先采用行业标准接口(SMI-S或OpenStack Cinder)进行存储接入。在平台层面,通过将异构存储资源进行抽象化,将传统的存储设备级的操作封装成面向存储资源的操作,从而简化异构存储基础架构的操作,以实现存储资源的集中管理,并能够自动执行创建、变更、回收等整个存储生命周期流程。基于异构存储整合的功能,用户可以实现跨不同品牌、介质地实现容灾,如用中低端阵列为高端阵列容灾,用不同磁盘阵列为闪存阵列容灾等等,从侧面降低了存储采购和管理成本。

‘伍’ 大型互联网架构概述,看完文章又涨知识了

1. 大型网站系统的特点

2. 大型网站架构演化历程

2.1. 初始阶段架构

问题:网站运营初期,访问用户少,一台服务器绰绰有余。

特征:应用程序、数据库、文件等所有的资源都在一台服务器上。

描述:通常服务器操作系统使用 linux,应用程序使用 PHP 开发,然后部署在 Apache 上,数据库使用 Mysql,通俗称为 LAMP。汇集各种免费开源软件以及一台廉价服务器就可以开始系统的发展之路了。

2.2. 应用服务和数据服务分离

问题:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足,一台服务器已不足以支撑。

特征:应用服务器、数据库服务器、文件服务器分别独立部署。

描述:三台服务器对性能要求各不相同:应用服务器要处理大量业务逻辑,因此需要更快更强大的 CPU;数据库服务器需要快速磁盘检索和数据缓存,因此需要更快的硬盘和更大的内存;文件服务器需要存储大量文件,因此需要更大容量的硬盘。

2.3. 使用缓存改善性能

问题:随着用户逐渐增多,数据库压力太大导致访问延迟。

特征:由于网站访问和财富分配一样遵循二八定律:80% 的业务访问集中在 20% 的数据上。将数据库中访问较集中的少部分数据缓存在内存中,可以减少数据库的访问次数,降低数据库的访问压力。

描述:缓存分为两种:应用服务器上的本地缓存和分布式缓存服务器上的远程缓存,本地缓存访问速度更快,但缓存数据量有限,同时存在与应用程序争用内存的情况。分布式缓存可以采用集群方式,理论上可以做到不受内存容量限制的缓存服务。

2.4. 使用应用服务器集群

问题:使用缓存后,数据库访问压力得到有效缓解。但是单一应用服务器能够处理的请求连接有限,在访问高峰期,成为瓶颈。

特征:多台服务器通过负载均衡同时向外部提供服务,解决单一服务器处理能力和存储空间不足的问题。

描述:使用集群是系统解决高并发、海量数据问题的常用手段。通过向集群中追加资源,提升系统的并发处理能力,使得服务器的负载压力不再成为整个系统的瓶颈。

2.5. 数据库读写分离

问题:网站使用缓存后,使绝大部分数据读操作访问都可以不通过数据库就能完成,但是仍有一部分读操作和全部的写操作需要访问数据库,在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈。

特征:目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到一台服务器上。网站利用数据库的主从热备功能,实现数据库读写分离,从而改善数据库负载压力。

描述:应用服务器在写操作的时候,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库。这样当应用服务器在读操作的时候,访问从数据库获得数据。为了便于应用程序访问读写分离后的数据库,通常在应用服务器端使用专门的数据访问模块,使数据库读写分离的对应用透明。

2.6. 反向代理和 CDN 加速

问题:中国网络环境复杂,不同地区的用户访问网站时,速度差别也极大。

特征:采用 CDN 和反向代理加快系统的静态资源访问速度。

描述:CDN 和反向代理的基本原理都是缓存,区别在于 CDN 部署在网络提供商的机房,使用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据;而反向代理则部署在网站的中心机房,当用户请求到达中心机房后,首先访问的服务器时反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。

2.7. 分布式文件系统和分布式数据库

问题:随着大型网站业务持续增长,数据库经过读写分离,从一台服务器拆分为两台服务器,依然不能满足需求。

特征:数据库采用分布式数据库,文件系统采用分布式文件系统。

描述:分布式数据库是数据库拆分的最后方法,只有在单表数据规模非常庞大的时候才使用。不到不得已时,更常用的数据库拆分手段是业务分库,将不同的业务数据库部署在不同的物理服务器上。

2.8. 使用 NoSQL 和搜索引擎

问题:随着网站业务越来越复杂,对数据存储和检索的需求也越来越复杂。

特征:系统引入 NoSQL 数据库及搜索引擎。

描述:NoSQL 数据库及搜索引擎对可伸缩的分布式特性具有更好的支持。应用服务器通过统一数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。

2.9. 业务拆分

问题:大型网站的业务场景日益复杂,分为多个产品线。

特征:采用分而治之的手段将整个网站业务分成不同的产品线。系统上按照业务进行拆分改造,应用服务器按照业务区分进行分别部署。

描述:应用之间可以通过超链接建立关系,也可以通过消息队列进行数据分发,当然更多的还是通过访问同一个数据存储系统来构成一个关联的完整系统。

纵向拆分:将一个大应用拆分为多个小应用,如果新业务较为独立,那么就直接将其设计部署为一个独立的 Web 应用系统。纵向拆分相对较为简单,通过梳理业务,将较少相关的业务剥离即可。

横向拆分:将复用的业务拆分出来,独立部署为分布式服务,新增业务只需要调用这些分布式服务横向拆分需要识别可复用的业务,设计服务接口,规范服务依赖关系。

2.10. 分布式服务

问题:随着业务越拆越小,存储系统越来越庞大,应用系统整体复杂程度呈指数级上升,部署维护越来越困难。由于所有应用要和所有数据库系统连接,最终导致数据库连接资源不足,拒绝服务。

特征:公共业务提取出来,独立部署。由这些可复用的业务连接数据库,通过分布式服务提供共用业务服务。

3. 大型网站架构模式

3.1. 分层

大型网站架构中常采用分层结构,将软件系统分为应用层、服务层、数据层:

分层架构的约束:禁止跨层次的调用(应用层直接调用数据层)及逆向调用(数据层调用服务层,或者服务层调用应用层)。

分层结构内部还可以继续分层,如应用可以再细分为视图层和业务逻辑层;服务层也可以细分为数据接口层和逻辑处理层。

3.2. 分割

将不同的功能和服务分割开来,包装成高内聚低耦合的模块单元。这有助于软件的开发和维护,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。

3.3. 分布式

大于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即将不同模块部署在不同的服务器上,通过远程调用协同工作。

分布式意味可以用更多的机器工作,那么 CPU、内存、存储资源也就更丰富,能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。

分布式也引入了一些问题:

常用的分布式方案:

3.4. 集群

集群即多台服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务。

集群需要具备伸缩性和故障转移机制:伸缩性是指可以根据用户访问量向集群添加或减少机器;故障转移是指,当某台机器出现故障时,负载均衡设备或失效转移机制将请求转发到集群中的其他机器上,从而不影响用户使用。

3.5. 缓存

缓存就是将数据存放在距离最近的位置以加快处理速度。缓存是改善软件性能的第一手段。

网站应用中,缓存除了可以加快数据访问速度以外,还可以减轻后端应用和数据存储的负载压力。

常见缓存手段:

使用缓存有两个前提:

3.6. 异步

软件发展的一个重要目标和驱动力是降低软件耦合性。事物之间直接关系越少,彼此影响就越小,也就更容易独立发展。

大型网站架构中,系统解耦的手段除了分层、分割、分布式等,还有一个重要手段——异步。

业务间的消息传递不是同步调用,而是将一个业务操作拆分成多阶段,每个阶段间通过共享数据的方式异步执行进行协作。

异步架构是典型的生产者消费模式,二者不存在直接调用。异步消息队列还有如下特性:

3.7. 冗余

大型网站,出现服务器宕机是必然事件。要保证部分服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份。这样当某台服务器宕机是,可以将其上的服务和数据访问转移到其他机器上。

访问和负载很小的服务也必须部署 至少两台服务器构成一个集群,目的就是通过冗余实现服务高可用。数据除了定期备份,存档保存,实现 冷备份 外;为了保证在线业务高可用,还需要对数据库进行主从分离,实时同步实现 热备份。

为了抵御地震、海啸等不可抗因素导致的网站完全瘫痪,某些大型网站会对整个数据中心进行备份,全球范围内部署 灾备数据中心。网站程序和数据实时同步到多个灾备数据中心。

3.8. 自动化

大型网站架构的自动化架构设计主要集中在发布运维方面:

3.9. 安全

4. 大型网站核心架构要素

架构 的一种通俗说法是:最高层次的规划,难以改变的决定。

4.1. 性能

性能问题无处不在,所以网站性能优化手段也十分繁多:

4.2. 可用性

可用性指部分服务器出现故障时,还能否对用户提供服务

4.3. 伸缩性

衡量伸缩的标准就是是否可以用多台服务器构建集群,是否容易向集群中增删服务器节点。增删服务器节点后是否可以提供和之前无差别的服务。集群中可容纳的总服务器数是否有限制。

4.4. 扩展性

衡量扩展性的标准就是增加新的业务产品时,是否可以实现对现有产品透明无影响,不需要任何改动或很少改动,既有功能就可以上线新产品。主要手段有:事件驱动架构和分布式服务。

4.5. 安全性

安全性保护网站不受恶意攻击,保护网站重要数据不被窃取。

欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

‘陆’ JAVA几种缓存技术介绍说明

1、TreeCache / JBossCache

JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间 的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。

2、WhirlyCache

Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。

3、SwarmCache

SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。

4、JCache

JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。

5、ShiftOne

ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。

‘柒’ 什么是分布式缓存

分布式缓存能够处理大量的动态数据,因此比较适合应用在Web 2.0时代中的社交网站等需要由用户生成内容的场景。从本地缓存扩展到分布式缓存后,关注重点从CPU、内存、缓存之间的数据传输速度差异也扩展到了业务系统、数据库、分布式缓存之间的数据传输速度差异。

常用的分布式缓存包括Redis和Memcached。

Memcached

Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。Memcached通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。

特点:哈希方式存储;全内存操作;简单文本协议进行数据通信;只操作字符型数据;集群由应用进行控制,采用一致性哈希算法。

限制性:数据保存在内存当中的,一旦机器重启,数据会全部丢失;只能操作字符型数据,数据类型贫乏;以root权限运行,而且Memcached本身没有任何权限管理和认证功能,安全性不足;能存储的数据长度有限,最大键长250个字符,储存数据不能超过1M。

Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

特点:

Redis支持的数据类型包括:字符串、string、hash、set、sortedset、list;Redis实现持久化的方式:定期将内存快照写入磁盘;写日志;Redis支持主从同步。

限制性:单核运行,在存储大数据的时候性能会有降低;不是全内存操作;主从复制是全量复制,对实际的系统运营造成了一定负担。

‘捌’ 分布式搜索引擎elasticsearch的架构原理

分布式搜索引擎:把大量的索引数据拆散成多块,每台机器放一部分,然 后利用多台机器对分散之后的数据进行搜索,所有操作全部是分布在多台机器上进行,形成了 完整的分布式的架构。

近实时,有两层意思:

集群包含多个节点,每个节点属于哪个集群都是通数旦桥过一个配置来决定的,
Node 是集群中的一个节点,节点也有一个名称,默认是随机分配的。默认节点会去加入一个名 称为 elasticsearch 的集群。如果直接启动一堆节点,那么它们会自动组成一个elasticsearch 集群,当然一个节点也可以组成 elasticsearch 集群。

文档是 es 中最小的数据单元,一个 document 可以是1条客户数据、1条商品分类数据、1条 订单数据,通常用json 数据结构来表示。每个 index 下的 type,都可以存储多条 document。
1个 document 里面有多个 field,每个 field 就是1个数据字段。

es 集群多个节点,会自动选举1个节点为 master 节点,这个 master 节点其实就是干一些管理 的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 master 节点宕机了,那么会重新选举1个节点为 master 节点。 如果是非 master节点宕薯猛机了,那么会由 master 节点,让那个宕机节点上的 primary shard 的身 份转移到其他机器上的 replica shard。接着你要是修复了那个宕机机器,重启了之后,master 节点会控制将缺失的 replica shard 分配过去,同步后续修改的数据之类的,让集群恢复正常。 说得更简单1点,就是说如果某个非 master 节点宕机了,那么此节点上的 primary shard 不就 没了。那好迟租,master 会让 primary shard 对应的 replica shard(在其他机器上)切换为 primary shard。如果宕机的机器修复了,修复后的节点也不再是 primary shard,而是 replica shard。

索引可以拆分成多个 shard ,每个 shard 存储部分数据。拆分多个 shard是有好处的,一是支持横向扩展,比如你数据量是 3T,3 个 shard,每个 shard 就 1T 的数据, 若现在数据量增加到 4T,怎么扩展,很简单,重新建1个有 4 个 shard 的索引,将数据导进 去;二是提高性能,数据分布在多个 shard,即多台服务器上,所有的操作,都会在多台机器 上并行分布式执行,提高了吞吐量和性能。 接着就是这个 shard 的数据实际是有多个备份,就是说每个 shard 都有1个 primary shard ,负责写入数据,但是还有多个 replica shard 。 primary shard 写入数据之后, 会将数据同步到其他几个 replica shard上去。
通过这个 replica 的方案,每个 shard 的数据都有多个备份,如果某个机器宕机了,没关系啊, 还有别的数据副本在别的机器上,这样子就高可用了。

总结:分布式就是两点,1.通过shard切片实现横向扩展;2.通过replica副本机制,实现高可用

基本概念

写数据过程:客户端通过hash选择一个node发送请求,这个node被称做coordinating node(协调节点),协调节点对docmount进行路由,将请求转发给到对应的primary shard,primary shard 处理请求,将数据同步到所有的replica shard,此时协调节点,发现primary shard 和所有的replica shard都处理完之后,就反馈给客户端。

客户端发送get请求到任意一个node节点,然后这个节点就称为协调节点,协调节点对document进行路由,将请求转发到对应的node,此时会使用随机轮询算法,在primary shard 和replica shard中随机选择一个,让读取请求负载均衡,接收请求的node返回document给协调节点,协调节点,返回document给到客户端

es最强大的是做全文检索,就是比如你有三条数据
1.java真好玩儿啊
2.java好难学啊
3.j2ee特别牛

你根据java关键词来搜索,将包含java的document给搜索出来。

更新/删除数据过程,首先还是write、merge操作,然后flush过程中:
1、write过程和上面的一致;
2、refresh过程有点区别

所谓的倒排索引,就是把你的数据内容先分词,每句话分成一个一个的关键词,然后记录好每一个关键词对应出现在了哪些 id 标识的数据。
然后你可以从其他地根据这个 id 找到对应的数据就可以了,这个就是倒排索引的数据格式 以及搜索的方式,这种利倒排索引查找数据的式,也被称之为全文检索。

Inverted Index就是我们常见的倒排索引, 主要包括两部分:
一个有序的数据字典 Dictionary(包括单词 Term 和它出现的频率)。
与单词 Term 对应的 Postings(即存在这个单词的文件)
当我们搜索的时候,首先将搜索的内容分解,然后在字典里找到对应 Term,从而查找到与搜索相关的文件内容。

本质上,Stored Fields 是一个简单的键值对 key-value。默认情况下,Stored Fields是为false的,ElasticSearch 会存储整个文件的 JSON source。

哪些情形下需要显式的指定store属性呢?大多数情况并不是必须的。从_source中获取值是快速而且高效的。如果你的文档长度很长,存储 _source或者从_source中获取field的代价很大,你可以显式的将某些field的store属性设置为yes。缺点如上边所说:假设你存 储了10个field,而如果想获取这10个field的值,则需要多次的io,如果从Stored Field 中获取则只需要一次,而且_source是被压缩过 的。

这个时候你可以指定一些字段store为true,这意味着这个field的数据将会被单独存储(实际上是存两份,source和 Stored Field都存了一份)。这时候,如果你要求返回field1(store:yes),es会分辨出field1已经被存储了,因此不会从_source中加载,而是从field1的存储块中加载。

Doc_values 本质上是一个序列化的 列式存储,这个结构非常适用于聚合(aggregations)、排序(Sorting)、脚本(scripts access to field)等操作。而且,这种存储方式也非常便于压缩,特别是数字类型。这样可以减少磁盘空间并且提高访问速度,ElasticSearch 可以将索引下某一个 Document Value 全部读取到内存中进行操作.

Doc_values是存在磁盘的

在es中text类型字段默认只会建立倒排索引,其它几种类型在建立倒排索引的时候还会建立正排索引,当然es是支持自定义的。在这里这个正排索引其实就是Doc Value。

即上文所描述的动态索引

往 es 写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 filesystem cache 中去。

es 的搜索引擎严重依赖于底层的 filesystem cache ,你如果给 filesystem cache 更多的 内存,尽量让内存可以容纳所有的 idx segment file 索引数据文件,那么你搜索的时候就 基本都是走内存的,性能会非常高。 性能差距究竟可以有多大?我们之前很多的测试和压测,如果走磁盘一般肯定上秒,搜索性能 绝对是秒级别的,1秒、5秒、10秒。但如果是走 filesystem cache ,是走纯内存的,那么一 般来说性能比走磁盘要高一个数量级,基本上就是毫秒级的,从几毫秒到几百毫秒不等。

那如何才能节约filesystem cache这部分的空间呢?
当写数据到ES时就要考虑到最小化数据,当一行数据有30几个字段,并不需要把所有的数据都写入到ES,只需要把关键的需要检索的几列写入。这样能够缓存的数据就会越多。 所以需要控制每台机器写入的数据最好小于等于或者略大于filesystem cache空间最好。 如果要搜索海量数据,可以考虑用ES+Hbase架构。用Hbase存储海量数据,然后ES搜索出doc id后,再去Hbase中根据doc id查询指定的行数据。

当每台机器写入的数据大于cache os太多时,导致太多的数据无法放入缓存,那么就可以把一部分热点数据刷入缓存中。

对于那些你觉得比较热的、经常会有人访问的数据,最好做个专门的缓存预热系统,就是 对热数据每隔一段时间,就提前访问一下,让数据进入 filesystem cache 里去。这样下 次别人访问的时候,性能肯定会好很多。

把热数据和冷数据分开,写入不同的索引里,然后确保把热索引数据刷到cache里。

在ES里最好不要用复杂的关联表的操作。当需要这样的场景时,可以在创建索引的时候,就把数据关联好。比如在mysql中需要根据关联ID查询两张表的关联数据:select A.name ,B.age from A join B where A.id = B.id,在写入ES时直接去把相关联数据放到一个document就好。

es 的分页是较坑的,为啥呢?举个例子吧,假如你每页是 10 条数据,你现在要查询第 100 页,实际上是会把每个 shard 上存储的前 1000 条数据都查到1个协调节点上,如果你有个 5 个 shard,那么就有 5000 条数据,接着协调节点对这 5000 条数据进行一些合并、处理,再获取到 最终第 100 页的 10 条数据。
分布式的,你要查第 100 页的 10 条数据,不可能说从 5 个 shard,每个 shard 就查 2 条数据, 最后到协调节点合并成 10 条数据吧?你必须得从每个 shard 都查 1000 条数据过来,然后根据 你的需求进行排序、筛选等等操作,最后再次分页,拿到里面第 100 页的数据。你翻页的时 候,翻的越深,每个 shard 返回的数据就越多,而且协调节点处理的时间越长,非常坑爹。所 以用 es 做分页的时候,你会发现越翻到后面,就越是慢。

我们之前也是遇到过这个问题,用 es 作分页,前几页就几十毫秒,翻到 10 页或者几十页的时 候,基本上就要 5~10 秒才能查出来一页数据了。

解决方案吗?
1)不允许深度分页:跟产品经理说,你系统不允许翻那么深的页,默认翻的越深,性能就越差;
2)在APP或者公众号里,通过下拉来实现分页,即下拉时获取到最新页,可以通过scroll api来实现;
scroll 会1次性给你生成所有数据的1个快照,然后每次滑动向后翻页就是通过游标 scroll_id 移动获取下一页,性能会比上面说的那种分页性能要高很多很 多,基本上都是毫秒级的。 但是,唯1的缺点就是,这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场 景。也就是说,你不能先进到第 10 页,然后去第 120 页,然后再回到第 58 页,不能随意乱跳 页。所以现在很多APP产品,都是不允许你随意翻页的,也有一些网站,做的就是你只能往 下拉,一页一页的翻。
初始化时必须指定 scroll 参数,告诉 es 要保存此次搜索的上下文多长时间。你需要确保用户不会持续不断翻页翻几个小时,否则可能因为超时而失败。
除了用 scroll api ,也可以用 search_after 来做, search_after 的思想是使用前一页的结果来帮助检索下一页的数据,显然,这种方式也不允许你随意翻页,你只能一页一页往后 翻。初始化时,需要使用一个唯1值的字段作为 sort 字段。

‘玖’ 1.16.5服务器优化技术有哪些

服务器优化技术主要有分布式缓存、异步操作、使用集群以及代码。
网站性能优化第一定律:优先考虑使用缓存优化性能。
缓存原理
(1)什么是缓存?(将数据存储在相对较高访问速度的介质中,以供系统处理)
(2)缓存的优点:访问速度快,如果需要计算可以减少计算时间
(3)缓存的本质是一张以键值对存储的内存hash表
(4)主要用来存储:读写比例高,很少变化的数据
(5)网站的访问遵循28定律
合理使用缓存应该注意以下问题
(1)频繁更新的数据(数据还没有读就已经失效,一般要求读写比在2:1以上才有意义)
(2)没有热点数据(无疑浪费资源)
(3)数据不一致与脏读(缓存被加载的过程中可能会产生数据不一致,有效时间过程数据在内存中就会变成脏数据)
(4)缓存的可用性(如果太过依赖缓存,容易产生雪崩。使用缓存热备并不能提高缓存的可用性,使用集群可以提高可用性)
(5)缓存预热(LRU计算时间过长,有的数据需要提前加载)
(6)缓存穿透(解决部分数据无法命中,而加重数据库压力的问题,一般设置空值)分布式缓存架构
(1)JBoss Cache:数据相同
(2)Memcached:数据不同互不通信
(3)Memcached5大优点:协议简单、通用性强(支持各种语言)、Libevent网络通信、内存管理高效、互不通信。