Java web应用性能分析之【高并发之缓存-多级缓存】

news2024/11/17 7:39:53

     

          说到缓存,作为java开发第一时间想到的是不是上图所示的Redis,又或者是Guava Cache、Caffeine、EhCache这些;Redis作为分布式缓存、其他的可以作为本地缓存。但是作为一名资深开发人员,着眼的层面应该再提升一个级别,从结构层面去考虑缓存,其实缓存指的是“多级缓存”。我们所说的Java Web应用,在当前技术栈下指的是基于springcloud的微服务应用,如下图微服务请求响应示意图所示,从客户端到服务端每个环节都有缓存。随着互联网业务的增长,微服务架构为了应对三高(高可用、高性能、高并发)中的高性能、高并发,需要引入“缓存”来应对高并发问题,从而达到高性能的目的。因此,在微服务架构中、要聊缓存、需要了解一下软件架构“三高”中的高并发。

微服务请求响应示意图

软件架构“三高”特性

  • 高并发(High Concurrency):高并发指的是系统能够同时处理大量的用户请求或操作。在高并发环境下,系统需要有效地管理资源,如线程和数据库连接,以便同时服务于大量用户或执行大量任务,而不会降低性能或导致服务中断。
  • 高可用(High Availability):高可用性指的是系统能够持续不断地为用户提供服务,即使面临部分故障或维护操作。这通常通过冗余设计(如多服务器、负载均衡、故障转移等)实现,确保系统的关键部分在任何时候都有一个备份可以接管工作。
  • 高性能(High Performance):高性能涉及到系统响应用户请求的速度和处理数据的能力。这不仅包括快速响应用户的交互请求,还包括在后端处理大量数据时的效率。提升性能通常涉及到优化代码、使用高效的算法、以及合理地利用硬件资源。

        这三个特性相互依赖,是打造健壮系统的基础。例如,提高系统的并发能力可能需要牺牲一部分性能;同样地,为了保证高可用性,可能需要投入更多的硬件资源和复杂的系统设计,这也可能影响性能。因此,在设计和优化系统时,需要在这三个方面之间找到一个平衡点。

高性能

        什么是高性能呢?高性能是指程序处理速度非常快,所占内存少,cpu占用率低。高性能的指标经常和高并发的指标紧密相关,想要提高性能,那么就要提高系统发并发能力,两者互相捆绑在一起。应用性能优化的时候,对于计算密集型和IO密集型还是有很大差别,需要分开来考虑。还有可以增加服务器的数量,内存,IO等参数提升系统的并发能力和性能,但不要浪费资源,要考虑硬件的使用率最高才能发挥到极致。

怎么样提高性能呢?

        避免因为IO阻塞让CPU闲置,导致CPU的浪费避免多线程间增加锁来保证同步,导致并行系统串行化免创建、销毁、维护太多进程、线程,导致操作系统浪费资源在调度上。

高可用

        高可用通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。高可用注意如果使用单机,一旦挂机将导致服务不可用,可以使用集群来代替单机,一台服务器挂了,还有其他后备服务器能够顶上。或者使用分布式部署项。比如现在redis的高可用的集群方案有: Redis单副本,Redis多副本(主从),Redis Sentinel(哨兵),Redis Cluster,Redis自研。

高并发的场景

        高并发系统是指在同一时间内有大量用户同时访问和操作的应用软件系统。例如:互联网(热门门户网站、微博、社交媒体、电商)、金融、游戏等领域。由于用户量大、访问频繁,高并发系统需要具备高性能、高可用性、高扩展性等特点,以满足用户的需求。

       例如,在电商平台上有大量用户同时浏览、搜索商品,提交订单等操作;社交媒体平台上有大量用户同时发布、点赞、评论等操作。这些场景需要系统能够同时处理大量请求,并保证系统的性能、可用性和用户体验。

高并发带来的问题

1. 请求延迟(系统性能的下降和延迟增加)

        在高并发系统中,请求延迟是一个常见的问题。由于大量的用户同时发起请求,系统需要处理大量的请求,导致请求的响应时间变长,甚至出现请求超时的情况。这种情况不仅影响用户体验,还可能对业务造成影响。

2. 资源竞争(资源竞争和资源耗尽、系统性能的下降和延迟增加)

        由于多个线程或进程同时访问共享资源,高并发系统容易出现资源竞争的问题。当多个请求同时访问同一份资源时,系统需要对其进行加锁或同步处理,以避免数据不一致和冲突。如果资源竞争过于激烈,会导致系统性能下降,甚至出现死锁和崩溃的情况。

3. 数据库瓶颈(资源竞争和资源耗尽、系统性能的下降和延迟增加)

        许多高并发系统都会使用数据库来存储和处理数据。在大量用户同时访问和操作时,数据库容易成为系统的瓶颈。数据库的读写性能、连接数和数据量等都可能成为制约系统性能的因素。如果数据库无法承受高并发请求,会导致查询速度变慢、数据丢失等问题。

4. 系统宕机(系统稳定性和可用性的挑战)

        在高并发场景下,如果系统的容量和性能没有得到充分的规划和设计,一旦遭遇流量高峰,系统容易宕机。此外,系统的硬件故障、网络故障以及软件缺陷等也可能导致系统宕机。系统宕机不仅影响用户体验,还可能对业务造成重大损失。

高并发的特点

  • 大量请求:高并发场景下,系统需要同时处理大量的请求,这些请求可能来自于不同的用户或客户端。
  • 同时访问:这些请求几乎同时到达系统,需要在短时间内进行处理和响应。
  • 资源竞争:由于大量请求同时到达,系统的资源(如CPU、内存、网络带宽等)可能会面临竞争和争夺。
  • 响应时间要求高:高并发场景通常对系统的响应速度有较高的要求,用户期望能够快速获取响应结果

高并发的指标

        高并发是现在互联网分布式框架设计必须要考虑的因素之一,它是可以保证系统能被同时并行处理很多请求,对于高并发来说,它的指标有:

  • 响应时间:系统对进来的请求反应的时间,比如你打开一个页面需要1秒,那么这1秒就是响应时间。
  • 吞吐量:吞吐量是指每秒能处理多少请求数量,好比你吃饭,每秒能吃下多少颗米饭。秒查询率:秒查询率是指每秒响应请求数,和吞吐量差不多。
  • 并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。


高并发应对策略:缓存、限流、降级

  •  缓存:缓解系统负载压力,提高系统响应速度。Java web应用性能分析之【高并发之缓存-多级缓存】-CSDN博客
  • 限流:控制并发访问量,保护系统免受过载影响。Java web应用性能分析之【高并发之限流】-CSDN博客
  • 降级:保证核心功能的稳定性,舍弃非关键业务或简化处理。Java web应用性能分析之【高并发之降级】-CSDN博客

缓存定义

        缓存是一种临时存储数据的技术,意味着在数据被使用之前将其复制到一个更快的存储介质中。在计算机领域,缓存一般用于提高系统的响应速度和性能。

        缓存是一种提高系统性能的技术,但需要适时清理以避免问题。删除缓存可以释放存储空间并保持系统的稳定性,但也可能带来一些不便。因此,在删除缓存之前,我们需要慎重考虑,并了解系统的特殊需求。

        1.磁盘缓存:存储在硬盘等永久性存储介质上,用于加速数据的读取和访问。

        2.CPU缓存:位于处理器内部的高速存储器,用于暂时存储频繁访问的数据或指令,提高计算机的性能。

        3.应用缓存:存储在内存中的应用程序数据或资源,用于提高应用程序的响应速度和用户体验。在这里,下面讲的“微服务架构下的缓存”即是应用缓存。

微服务架构下的缓存

        如下图“微服务请求响应示意图”所示,从web请求响应这个链路来说,每个节点都有自己的缓存,所以将缓存又叫做“多级缓存”,这样更具体。从前到后的多级缓存包括:浏览器缓存----》CDN缓存---》Nginx缓存-----》分布缓存------》java进程内的缓存

        多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Tomcat压力,提升服务性能:

  • 浏览器访问静态资源时,优先读取浏览器本地缓存
  • 访问非静态资源(ajax查询数据)时,访问服务端
  • 请求到达Nginx后,优先读取Nginx本地缓存
  • 如果Nginx本地缓存未命中,则去直接查询Redis(不经过Tomcat)
  • 如果Redis查询未命中,则查询Tomcat
  • 请求进入Tomcat后,优先查询JVM进程缓存
  • 如果JVM进程缓存未命中,则查询数据库

各种介质数据访问延迟

操作类型

粗略时间

访问本地内存

100ns

SSD磁盘搜索

100,000ns

网络数据包在同一个数据中心来回一次的时间

500,000ns

非SSD磁盘搜索

10,000,000ns

按顺序从网络读取1MB数据

10,000,000ns

按顺序从非SSD磁盘读取1MB数据

30,000,000ns

跨大西洋网络数据包来回一次的时间

150,000,000ns

跨太平洋网络数据包来回一次的时间

300,000,000ns

每秒等于多少

1,000,000,000ns

  • 美国访问中国的数据中心网络延迟就有300ms
  • redis/memcached一次请求(1-2k)大概耗时0.5ms
  • 加索引的数据库的一次请求(1-2k)大概耗时50ms,是缓存的100倍
技术栈各个层次的缓存

缓存为什么显著提升性能
  • 缓存数据通常来自内存,比磁盘等其他介质有更快的访问速度
  • 缓存的数据通常是终态,不需要中间计算,节省了CPU资源消耗
  • 缓存降低了数据库、磁盘、网络的负载压力,使得这些IO设备能获得更好的响应特性,提升系统整体性能
缓存不适宜场景
  • 频繁修改的数据

此类型数据应用还来不及读取就失效了徒增系统负担,一般数据的读写比在2:1以上,缓存才有意义。

  • 没有热点的访问

缓存使用内存存储,内存资源有限且宝贵,如果数据没有二八定律即大部分访问集中在小部分数据上,则缓存效果不会明显

  • 数据不一致与脏读不允许

一般会对缓存数据设置过期时间,过期时间内可能会和数据库不一致,如果业务容忍则也可以使用,如果业务不能容忍,则需要数据在数据库变更时也要清除缓存。

客户端缓存--浏览器缓存

        浏览器缓存是指将网页中的资源(如HTML、CSS、JavaScript、图像等)存储在用户的浏览器内部,以便在后续请求同一资源时可以直接从本地缓存中获取,而无需再次从服务器下载。

适用场景

        浏览器缓存适用于那些静态内容变化较少的网页和静态资源,可以显著提升网站性能和用户体验,并减少服务器的负载。

常见用法

        使用浏览器缓存可以通过设置响应头中的Expires和Cache-Control字段来控制缓存的行为。

        1.使用Expires字段:Expires字段指定了缓存的过期时间,是一个具体的日期和时间。服务器可以在响应头中添加Expires字段,告诉浏览器在该时间之前可以直接从缓存中获取资源,而无需再向服务器发起请求。例如:Expires: Mon, 31 Dec 2022 23:59:59 GMT。

        2.使用Cache-Control字段:Cache-Control字段提供了更灵活的缓存控制选项。可以通过设置max-age指令来指定缓存的最大有效时间,单位是秒。例如:Cache-Control: max-age=3600 表示资源可以在1小时内直接从缓存中获取。还可以使用其他指令,如no-cache表示缓存但不使用缓存、no-store表示禁止缓存等。

注意事项

        浏览器缓存存储实时性不敏感的数据,如商品框架、商家评分、评价和广告词。它有过期时间,并通过响应头进行控制。实时性要求高的数据不适合使用浏览器缓存。

服务端缓存--CDN缓存

        CDN(Content Delivery Network)是建立在承载网之上的分布式网络,由分布在不同区域的边缘节点服务器组成。

        CDN缓存通常用于存放静态页面数据、活动页面、图片等数据。它有两种缓存机制:推送机制(将数据主动推送到CDN节点)和拉取机制(首次访问时从源服务器获取数据并存储在CDN节点)。

缓存相关常见问题_CDN(CDN)-阿里云帮助中心

服务端缓存--Nginx缓存

第一步:客户端第一次向Nginx请求数据A;

第二步:当Nginx发现缓存中没有数据A时,会向服务端请求数据A;

第三步:服务端接收到Nginx发来的请求,则返回数据A到Nginx,并且缓存在Nginx;

第四步:Nginx返回数据A给客户端应用;此时状态码是200

第五步:客户端第二次向Nginx请求数据A;

第六步:当Nginx发现缓存中存在数据A时,则不会请求服务端;

第七步:Nginx把缓存中的数据A返回给客户端应用。此时状态码是304

Nginx-cache配置

Nginx通过proxy_cache来实现缓存。Buffer(缓冲)主要用于传输效率不同步或者优先级不相同的设备之间传输数据,通过对一方数据进行临时存放,在统一发送的方式传递给另一方,以降低进程间的等待时间;Cache(缓存)主要用于将硬盘上已有的数据在内存中建立缓存数据,提高数据的访问效率。

而proxy_cache只有在Proxy Buffer机制开启的情况下Proxy Cache的配置才会发挥作用

相关配置

  • proxy_zone:zone | off 默认是off,即关闭proxy_cache功能,zone为用于存放缓存的内存区域名称,可以在http/server、location块内使用

  • proxy_cache_path: path [levels=levels] keys_zone-name:size [inactive=time] [max_size=size] 只能在http块内使用
    • path设置缓存数据存放的路径

    • levels设置目录层级,如levels=1:2,表示有两个子目录

    • keys_zone 设置内存zone的名称和大小,如keys_zone=my:10m

    • inactive设置缓存多长时间失效,当磁盘上的缓存数据在该时间段内没有被访问过,就会失效,数据将被删除,默认10s

    • max_size 设置硬盘中最多缓存多少数据,数据超出,则删除最少访问的数据

  • proxy_cache_methods GET HEAD POST 设置缓存哪些方法

  • proxy_cache_min_uses 1 设置缓存的最小使用次数

  • proxy_cache_valid code time 对不同的状态码缓存不同的时间

  • proxy_cache_key line 设置缓存的key值

http {
    proxy_cache_path    /var/www/cache #缓存地址
                        levels=1:2 #目录分级
                        keys_zone=test_cache:10m #开启的keys空间名字:空间大小(1m可以存放8000个key)
                        max_size=10g #目录最大大小(超过时,不常用的将被删除)
                        inactive=60m #60分钟内没有被访问的缓存将清理
                        use_temp_path=off; #是否开启存放临时文件目录,关闭默认存储在缓存地址
                                         
    server {
    		# 使用缓存
        location / {
            proxy_cache test_cache;    #开启缓存对应的名称,在keys_zone命名好
            proxy_cache_valid 200 304 12h;    #状态码为200 304的缓存12小时
            proxy_cache_valid any 10m;    #其他状态缓存10分钟
            proxy_cache_key $host$uri$is_args$args;    #设置key值
            add_header Nginx-Cache "$upstream_cache_status";
        }
        #不使用缓存
        if ($request_uri ~ ^/(login|register) ) {    #当请求地址有login或register时
        	set $nocache = 1;    #设置一个自定义变量为true
    		}
    		location / {
        	proxy_no_cache $nocache $arg_nocache $arg_comment;
        	proxy_no_cache $http_pragma $http_authoriztion;
    		}
    }
}

expires配置
location ~ .*.(jpg|jpeg|gif|png)$ {
	# 设置图片缓存过期时间
	expires 1d;
} 

# 匹配静态目录
location ~^ /(|css|js) / {
	expires 2h;
}
    location ~ .*\.(?:htm|html)$    #不缓存html
    {
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }
 }

响应会返回给浏览器Expires属性,展示的是过期时间,之后再次请求该资源时,如果没有超过响应返回的Expires时,则不需要向服务器访问,直接从缓存中获取

静态资源缓存
# 缓存zone levels表示缓存层级以及目录位数 keys_zone表示缓存内存大小 inactive有效期 max_size所占用的最大磁盘大小
proxy_cache_path /data/nginx/cache_ad levels=1:2 keys_zone=cache_cache_ad:100m inactive=7d max_size=200m;

server {
 location / {
   # 缓存zone
   proxy_cache cache_ad;
   # 缓存key  进行md5
   proxy_cache_key $host$uri$is_args$args;
   # 什么情况下进行缓存存储
   proxy_cache_valid 200 304 12h;
 }
}
检查是否使用Nginx缓存

        如果需要知道Nginx是否使用了缓存,你可以在响应头中加入$upstream_cache_status变量以进行检测。

add_header X-Cache-Status $upstream_cache_status;这是在Nginx添加缓存命中状态的add_header指令。

        此示例X-Cache-Status在响应客户端时添加HTTP标头。以下是$upstream_cache_status可能的值。

  • MISS在缓存中找不到响应,因此从原始服务器获取响应。然后缓存响应。HIT响应直接来自有效的缓存。
  • BYPASS响应是从原始服务器获取的,而不是从缓存中提供的,因为请求与proxy_cache_bypass指令匹配。
  • EXPIRED缓存中的记录已过期。响应包含来自原始服务器的新内容。
  • STALE内容过时,因为源服务器未正确响应但proxy_cache_use_stale已配置。
  • UPDATING缓存内容已过时,因为当前正在更新以响应先前的请求,并且proxy_cache_use_stale updating已配置。
  • REVALIDATED-proxy_cache_revalidate指令已启用,Nginx验证当前缓存的内容是否仍然有效通过If-Modified-SinceIf-None-Match
服务端缓存--分布式缓存

        分布式寻址算法是分布式对象缓存的关键,即缓存键如何分布到不同服务器,集群增加节点时如何处理

均匀hash算法
  • 针对一个key,计算hashcode,然后在对节点数量取模,完成寻址。
  • 当新增节点或某个节点故障时,会有大量key的缓存失效,给数据库带来压力。
一致性hash算法
  • 解决分布式缓存集群扩容时数据访问不一致问题的算法,防止缓存雪崩。
  • 实现步骤
    • 构建一个一致性hash环(0-(232-1),也是hashcode的范围即4个字节的范围)
    • 首先根据node的hashcode把node加入到环上
    • 再根据key的hashcode把key加入到环上
    • 最后沿着环按顺时针找到最近的node完成寻址
  • 当新增节点或某个节点故障时,仅有少量的key的缓存失效,把压力降到最低。
  • 但此算法的缺点就是node的hashcode可能分布不均匀导致负载不均衡,需要基于虚拟节点的一致性hash
基于虚拟节点的一致性hash算法
  • 把node拆分成M个虚拟节点(nodeN_0......nodeN_M)
  • 然后把虚拟节点按hashcode放入hash环,解决均衡问题
  • 虚拟节点越多,对增减节点时缓存失效的概率越低,同时算法的效率也会降低,综合起来M应该在150-200
Redis VS Memcached
  • Redis支持复杂的数据结构,Memcached只支持字符串
  • Redis支持多路复用、异步IO保证高性能
  • Redis支持主从复制保证高可用
  • Redis原生支持集群模式
Redis集群
  • 集群预分好16384个slot,根据CRC16(key) mod 16384的值决定key放入哪个slot,结果是均匀的
  • Redis-cluster把所有物理节点映射到[0-16383]slot上,并负责维护slot与服务器的映射关系
  • slot使得增/删节点变得非常简单,可以像磁盘分区一样自由分配slot,在配置文件里可显示指定也可默认
  • 管理员可以根据机器的配置和负载情况进行slot的动态调整,基本上解决了最开始的负载均衡问题
  • 当新增节点时,各节点会分一些slot到新节点。当删除节点时,该节点上的slot也会分给其他节点
  • 所有的Redis节点彼此互联,客户端连接集群上任何一个可用节点即可
服务端缓存--java进程内的缓存(本地缓存)

        在Java中,本地缓存通常是指在应用程序中缓存数据的一种方式,以便更快地访问经常需要的数据。这种缓存通常是在应用程序的生命周期内有效的。

        在JAVA里一般我们有几种类型的应用缓存可以选择,比如JAVA本身提供的缓存(HashMap,ConcurrentHashMap)、还有第三方提供的应用缓存Ecache、 Guava 、caffeine。因为JAVA提供的缓存只提供了简单的缓存增加删除机制,基本上没有任何扩展的功能,所以就衍生了一批第三方的应用缓存,第三方应用缓存提供了丰富的扩展功能,比如说我们上面的缓存自动失效机制、缓存事件订阅机制,这些扩展机制能给开发人员管理缓存提供很大的便捷性。 

        本地缓存对比

框架命中率速度回收算法使用难度集群适用场景内存线程安全
Guava cache第三LRU、LFU、FIFO不支持读多写少,允许少量缓存偏移jvm堆内存
Caffeine第一W-TinyLFU不支持读多写少,允许少量缓存偏移,能用 Caffeine 就别用 Guava cachejvm堆内存
Ehcache第二LRU、LFU、FIFO支持分布式系统中对数据一致性要求高jvm堆内存+直接内存+磁盘
HashMap
ConcurrentHashMap

引入缓存带来的问题

  • 缓存预热

        缓存中存放的是热点数据,热点数据通过LRU算法筛选出来的,整个过程时间比较长,过程内性能一般,需要在缓存系统启动时就把热点数据加载好就是缓存预热warm up,

  • 缓存穿透

        如果不恰当的业务或恶意请求持续高并发的请求某个不存在的缓存,如果缓存没有相应的对策,那所有的查询请求都落到数据库上,带来很大的压力,甚至崩溃。一个简单的对策是将不存在的数据也缓存起来值为null,并设置较短的过期时间

  • 缓存雪崩

        当缓存服务器崩溃时,请求压力全部打倒数据库,导致数据库也宕机,进而整个服务失效。发生这种问题时甚至不能简单的重启缓存服务器和数据库服务器来恢复。

  • 缓存一致性:数据库和分布式缓存不一致

  分两种情况,读数据和写数据(更新)

    1. 读数据:读数据时候先读取缓存,如果缓存没有(miss hit)就读取数据库,然后在从数据库中取出数据并添加到缓存中,最后在返回数据给客户端。

        

    2. 更新数据:  先更新数据库数据在删除缓存(也有人认为先删除缓存在更新数据库)。

      

  • 缓存一致性:数据库和多级缓存不一致      

但事无完美,当引入多级缓存后,我们又会遇到缓存数据一致性的挑战,以下图为例:

图片

缓存一致性问题

我们都知道作为数据库写操作,是不通过缓存的。假设商品服务实例 1 将 1 号商品价格调整为 80 元,这会衍生一个新问题:如何主动向应用程序推送数据变更的消息来保证它们也能同步更新缓存呢?

相信此时你已经有了答案。没错,我们需要在当前架构中引入 MQ 消息队列,利用 RocketMQ 的主动推送功能来向其他服务实例以及 Redis 缓存服务发起变更通知。

图片

通过 RocketMQ 解决保证消息一致性

如上图所示,在商品服务实例 1 对商品调价后,主动向 RocketMQ Broker 发送变更消息,Broker 将变更信息推送至其他实例与 Redis 集群,这些服务实例在收到变更消息后,在缓存中先删除过期缓存,再创建新的数据,以此保证各实例数据一致。

看到这里你会发现,对于缓存来说,并没有终极的解决方案。虽然多级缓存设计带来了更好的应用性能,但也为了缓存一致性必须引入 MQ 增加了架构的复杂度。那到底多级缓存设计该如何取舍呢?在我看来,有三种情况特别适合引入多级缓存。

  • 第一种情况,缓存的数据是稳定的。例如邮政编码、地域区块、归档的历史数据这些信息适合通过多级缓存减小 Redis 与数据库的压力。

  • 第二种情况,瞬时可能会产生极高并发的场景。例如春运购票、双 11 零点秒杀、股市开盘交易等,瞬间的流量洪峰可能击穿 Redis 缓存,产生流量雪崩。这时利用预热的进程内缓存分摊流量,减少后端压力是非常有必要的。

  • 第三种情况,一定程度上允许数据不一致。例如某博客平台中你修改了自我介绍这样的非关键信息,此时在应用集群中其他节点缓存不一致也并不会带来严重影响,对于这种情况我们采用T+1的方式在日终处理时保证缓存最终一致就可以了。

以上是我总结的三种适合服务层做多级缓存的场景。当然如果你们的应用并发量不大,在未来的1~2 年内利用 Redis 分布式缓存集群完全可以胜任应用性能要求,那自然就没有必要设计多级缓存,我们要根据业务特点灵活调整架构。

  • 缓存不可用之旁路缓存

        缓存不可用时,不能阻塞正常业务请求。Redis 是一个独立的系统软件,和业务应用程序是两个软件,当我们部署了 Redis 实例后,它只会被动地等待客户端发送请求,然后再进行处理。所以,如果应用程序想要使用 Redis 缓存,我们就要在程序中增加相应的缓存操作代码。所以,我们也把 Redis 称为旁路缓存,也就是说,读取缓存、读取数据库和更新缓存的操作都需要在应用程序中来完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云上聚智——移动云云服务器进行后端的搭建及部署

什么是移动云 移动云是指将移动设备和云计算技术相结合,为移动应用提供强大的计算和存储能力的服务模式。传统的移动应用通常在本地设备上进行计算和存储,而移动云将这些任务转移到云端进行处理。通过移动云,移动设备可以利用云端的高性能计算…

Linux程序开发(三):MakeFile编程及Githup项目编码

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊! 喜欢我的博客的话,记得…

海外私人IP和原生IP有什么区别,谁更有优势?

一、什么是海外私人IP?什么是原生IP? 1、海外私人IP: 海外私人IP是由专门的服务提供商提供的IP地址,这些IP地址通常与特定地理位置或国家相关联。这些IP地址独享私人而不用与其他用户共享。海外私人IP访问特定国家或地区的网站&am…

新定义RD8T36P48使用USCI0的TWI功能点亮OLED

时间不多,因此先只给出工程,等有时间再添加详细说明 现象 这是从之前的一个51单片机的程序移植过来的,主要修改了IIC启动和停止,以及数据发送的代码,我现在还不是很满意的一点是发送过程中要等待上一个字节发送完才能…

如何通过OpenHarmony的音频模块实现录音变速功能?

简介 OpenAtom OpenHarmony(以下简称“OpenHarmony”)是由开放原子开源基金会孵化及运营的开源项目,是面向全场景、全连接、全智能时代的智能物联网操作系统。 多媒体子系统是OpenHarmony系统中的核心子系统,为系统提供了相机、…

hpc中查看显存占用,等效nvidia-smi

nvidia-smi在hpc中无法使用, 但是可以通过以下方法查看应用程序占用的显存 先执行程序,之后 bjobs输出 可以看到使用的是gpu01节点 之后 ssh gpu01

高刚性滚柱直线导轨有哪些优势?

滚柱导轨是机械传动系统中用于支持和引导滑块或导轨的装置,承载能力较高、刚性强及高精度等特点。特别适用于大负载和高刚性的工业设备,如机床、数控机床等设备,这些优势使其在工业生产和机械设备中得到了广泛的应用。 1、高精度:…

营收净利双降、股东减持,大降价也救不了良品铺子

号称“高端零食第一股”的良品铺子(603719.SH),正遭遇部分股东的“用脚投票”。 5月17日晚间,良品铺子连发两份减持公告,其控股股东宁波汉意创业投资合伙企业、持股5%以上股东达永有限公司,两者均计划减持。 其中,宁…

切换python和python3的版本

参考:http://t.csdnimg.cn/iUtSR 进入root sudo su 使用 sudo 权限运行 update-alternatives 命令,为 python 和 python3 设置默认版本。 sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 sudo update-alternatives…

【Oracle篇】rman工具实用指南:常用命令详解与实践(第二篇,总共八篇)

💫《博主介绍》:✨又是一天没白过,我是奈斯,DBA一名✨ 💫《擅长领域》:✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌️…

day 38 435.无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树

435.无重叠区间 思路 为了使区间尽可能的重叠所以排序来使区间尽量的重叠,使用左边界排序来统计重叠区间的个数与452. 用最少数量的箭引爆气球恰好相反。 代码 class Solution {public int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals,(a,…

Python-温故知新

1快速打开.ipynb文件 安装好anaconda后,在需要打开notebook的文件夹中, shift键右键——打开powershell窗口——输入jupyter notebook 即可在该文件夹中打开notebook的页面: 2 快速查看函数用法 光标放在函数上——shift键tab 3...

JavaWeb Sevelet学习 创建Sevelet程序

Servlet 是JavaWeb中的开发动态Web一门技术 是由Sun公司提供的一个接口,允许开发者编写运行在服务器(Tomcat)上的Java程序,这些程序可以 生成动态网页内容, 响应客户端的请求。简单来说,Servlet就是Java E…

C++入门 基于ros的话题通信

一、 开发环境 ubuntu20.04 ros版本noetic 参考视频 https://www.bilibili.com/video/BV1Ci4y1L7ZZ/?p52&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source4cd1b6f268e2a29a11bea5d2568836ee 二、 创建两个功能包 //创建工作空间 工作空…

Aiseesoft Video Converter Ultimate视频转换大师,免安装中文旗舰版 v10.8.32

软件介绍 视频转换大师是一款集转码、编辑以及压缩功能于一身的专业软件,支持处理超过1,000种视频和音频格式。该工具不仅提供基础的格式转换服务,还拓展至高级功能,包括视频效果调整、数据压缩以及ID3信息编辑等,同时&#xff0…

socket地址理解

socket介绍 套接字的基本概念 1. 套接字的定义: 套接字(socket)是计算机网络中用于通信的端点,它抽象了不同主机上应用进程之间双向通信的机制。 2. 套接字的作用: 套接字连接应用进程与网络协议栈,使…

加密与解密(第四版)】第二十五章笔记

第二十五章 数据取证技术 25.1 硬盘数据的获取和固定 取证专用的Linux可启动光盘 硬盘复制机 利用取证计算机复制硬盘 手机(JTAG) 电子数据的固定(HASH值) 25.2 硬盘的分区和数据恢复 25.3 内存分析 25.4 动态仿真技术 25.…

虚拟ECU:彻底改变汽车软件开发与测试

汽车开发领域有着垂直性较强的一系列需求,其中最为瞩目的需求之一就是对安全高效的软件测试方法的需求。传统的汽车开发偏向使用硬件原型与真实ECU进行软件测试,但由于硬件设备往往在开发周期的中后阶段才生产完成,给汽车开发带来了成本与时间…

做OZON怎么选择物流,OZON物流Xingyuan

随着跨境电商的蓬勃发展,OZON作为俄罗斯领先的电商平台,吸引了大量中国卖家入驻。然而,物流作为跨境电商的关键环节,其选择对于卖家来说至关重要。本文将围绕“做OZON怎么选择物流”这一问题,深度解析OZON物流Xingyuan…

二分查找

题目链接 题目: 分析: 如果按照从头到尾的顺序一次比较, 每次只能舍弃一个元素, 效率是非常低的, 而且没有用到题目的要求, 数组是有序的因为数组是有序的, 所以如果我们随便找到一个位置, 和目标元素进行比较, 如果大于目标元素, 说明该位置的右侧元素都比目标元素大, 都可…