[京东技术]本文转载自kaitao.toutiao.im, 转载务必声明。
简介
最近遇到很多人来咨询我关于浏览器缓存的一些问题,而这些问题都是类似的,因此总结本文来解答以后遇到类似问题的朋友。
因本文主要以浏览器缓存场景介绍,所以非浏览器场景下的一些用法本文不会介绍,而且本文以chrome为测试浏览器。
浏览器缓存是指当我们使用浏览器访问一些网站页面或者http服务时,根据服务端返回的缓存设置响应头将响应内容缓存到浏览器,下次可以直接使用缓存内容或者仅需要去服务端验证内容是否过期即可。这样的好处可以减少浏览器和服务端之间来回传输的数据量,节省带宽提升性能。
首先看个例子;当我们第一次访问http://item.jd.com/1856588.html时将得到如下响应头:
然后接着按F5刷新页面,将得到如下响应头
第二次返回的相应状态码为304,表示服务端文档没有修过过,浏览器缓存的内容还是最新的。
接下来我们看下如何在Java应用层控制浏览器缓存。
示例
Last-Modified
如下是我们的spring mvc缓存测试代码:
@RequestMapping("/cache")
public ResponseEntity<String> cache(
HttpServletRequest request,
//为了方便测试,此处传入文档最后修改时间
@RequestParam("millis") long lastModifiedMillis,
//浏览器验证文档内容是否修改时传入的Last-Modified
@RequestHeader (value = "If-Modified-Since", required = false) Date ifModifiedSince) {
//当前系统时间
long now = System.currentTimeMillis();
//文档可以在浏览器端/proxy上缓存多久
long maxAge = 20;
//判断内容是否修改了,此处使用等值判断
if(ifModifiedSince != null && ifModifiedSince.getTime() == lastModifiedMillis) {
return new ResponseEntity<String>(HttpStatus.NOT_MODIFIED);
}
DateFormat gmtDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
String body = "<a href=''>点击访问当前链接</a>";
MultiValueMap<String, String> headers = new HttpHeaders();
//文档修改时间
headers.add("Last-Modified", gmtDateFormat.format(new Date(lastModifiedMillis)));
//当前系统时间
headers.add("Date", gmtDateFormat.format(new Date(now)));
//过期时间 http 1.0支持
headers.add("Expires", gmtDateFormat.format(new Date(now + maxAge)));
//文档生存时间 http 1.1支持
headers.add("Cache-Control", "max-age=" + maxAge);
return new ResponseEntity<String>(body, headers, HttpStatus.OK);
}
为了方便测试,测试时将文档的修改时间通过millis参数传入,实际应用时可以使用如商品的最后修改时间等替代。
首次访问
首次访问http://localhost:9080/cache?millis=1471349916709,将得到如下响应头:
响应状态码200表示请求内容成功,另外有如下几个缓存控制参数:
Last-Modified:表示文档的最后修改时间,当去服务器验证时会拿这个时间去;
Expires:http/1.0规范定义,表示文档在浏览器中的过期时间,当缓存的内容超过这个时间则需要重新去服务器获取最新的内容;
Cache-Control:http/1.1规范定义,表示浏览器缓存控制,max-age=20表示文档可以在浏览器中缓存20秒。
根据规范定义Cache-Control优先级高于Expires;实际使用时可以两个都用,或仅使用Cache-Control就可以了(比如京东的活动页sale.jd.com)。一般情况下Expires=当前系统时间(Date) + 缓存时间(Cache-Control: max-age)。大家可以在如上测试代码进行两者单独测试,缓存都是可行的。
F5刷新
接着按F5刷新当前页面,将看到浏览器发送如下请求头:
此处发送时有一个If-Modified-Since请求头,其值是上次请求响应中的Last-Modified,即浏览器会拿这个时间去服务端验证内容是否发生了变更。接着收到如下响应信息:
响应状态码为304,表示服务端告诉浏览器说“浏览器你缓存的内容没有变化,直接使用缓存内容展示吧”。
注:在测试时要过一段时间更改下参数millis来表示内容修改了,要不然会一直看到304响应。
Ctrl+F5强制刷新
如果你想强制从服务端获取最新的内容,可以按Ctrl+F5:
浏览器在请求时不会带上If-Modified-Since,并带上Cache-Control:no-cache和Pragma:no-cache,这是为了告诉服务端说我请给我一份最新的内容。
from cache
当我们按F5刷新、Ctrl+F5强制刷新、地址栏输入地址刷新时都会去服务端验证内容是否发生了变更。那什么情况才不去服务端验证呢?即有些朋友还会发现有一些“from cache”的情况,这是什么情况下发生的呢?
从A页面跳转到A页面或者从A页面跳转到B页面时:
大家可以通过如上方式模拟,即从A页面跳转到A页面也是情况1。此时如果内容还在缓存时间之内,直接从浏览器获取的内容,而不去服务端验证。
访问页面http://item.jd.com/11056556.html,然后点击面包屑中的HTTP权威指南时会跳转到当前页面,此时看到如下结果,页面及页面异步加载的一些js、css、图片都from cache了。
还有如通过浏览器历史记录进行前进后退时也会走from cache。本文是基于chrome 52.0.2743.116 m版本测试,不同浏览器行为可能存在差异。
Age
一般用于代理层(如CDN),大家在访问京东一些页面时会发现有一个Age响应头,然后强制刷新(Ctrl+F5)后会发现其不断的变化;其表示此内容在代理层从缓存到现在经过了多长时间了,即在代理层缓存了多长时间了。
Vary
一般用于代理层(如CDN),用于代理层和浏览器协商什么情况下使用哪个版本的缓存内容(比如压缩版和非压缩版),即什么情况下后续请求才能使用代理层缓存的该版本内容,比如如下响应是告知浏览器Content-Encoding:gzip,即缓存代理层缓存了gzip版本的内容;那么后续的请求在请求时Accept-Encoding头部中包含gzip时才能使用改代理层缓存。
Via
一般用于代理层(如CDN),表示访问到最终内容经过了哪些代理层,用的什么协议,代理层是否缓存命中等等;通过它可以进行一些故障诊断。
ETag
@RequestMapping("/cache/etag")
public ResponseEntity<String> cache(
HttpServletRequest request,
HttpServletResponse response,
//浏览器验证文档内容的实体 If-None-Match
@RequestHeader (value = "If-None-Match", required = false) String ifNoneMatch) {
//当前系统时间
long now = System.currentTimeMillis();
//文档可以在浏览器端/proxy上缓存多久
long maxAge = 10;
String body = "<a href=''>点击访问当前链接</a>";
//弱实体
String etag = "W/\"" + md5(body) + "\"";
if(StringUtils.equals(ifNoneMatch, etag)) {
return new ResponseEntity<String>(HttpStatus.NOT_MODIFIED);
}
DateFormat gmtDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
MultiValueMap<String, String> headers = new HttpHeaders();
//ETag http 1.1支持
headers.add("ETag", etag);
//当前系统时间
headers.add("Date", gmtDateFormat.format(new Date(now)));
//文档生存时间 http 1.1支持
headers.add("Cache-Control", "max-age=" + maxAge);
return new ResponseEntity<String>(body, headers, HttpStatus.OK);
}
其中ETag用于发送到服务端进行内容变更验证的,而Catch-Control是用于控制缓存时间的(浏览器、代理层等)。此处我们使用了弱实体W\”343sda”,弱实体(”343sda”)只要内容语义没变即可,比如内容的gzip版和非gzip版可以使用弱实体验证;而强实体指字节必须完全一致(gzip和非gzip情况是不一样的),因此建议首先选择使用弱实体。nginx在生成etag时使用的算法是Last-Modified + Content-Length计算的:
ngx_sprintf(etag->value.data,"\"%xT-%xO\"",
r->headers_out.last_modified_time,
r->headers_out.content_length_n)
到此简单的基于文档修改时间和过期时间的缓存控制就介绍完了,在内容型响应我们大多数根据内容的修改时间来进行缓存控制,ETag根据实际需求而定(比如)。另外还可以使用html Meta标签控制浏览器缓存,但是对代理层缓存无效,因此不建议使用。
总结
1、服务端响应的Last-Modified会在下次请求时以If-Modified-Since请求头带到服务端进行文档是否修改的验证,如果没有修改则返回304,浏览器可以直接使用缓存内容;
2、Cache-Control:max-age和Expires用于决定浏览器端内容缓存多久,即多久过期,过期后则删除缓存重新从服务端获取最新的;另外可以用于from cache场景;
3、http/1.1规范定义的Cache-Control优先级高于http/1.0规范定义的Expires;
4、一般情况下Expires=当前系统时间 + 缓存时间(Cache-Control:max-age);
5、http/1.1规范定义了ETag来通过文档摘要的方式控制。
Last-Modified与ETag同时使用时,浏览器在验证时会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,如果同时使用If-Modified-Since和If-None-Match则服务端必须两个都验证通过后才能返回304;且nginx就是这样做的。因此实际使用时应该根据实际情况选择。还有If-Match和If-Unmodified-Since本文就不介绍了。
接下来我们看下如何使用nginx进行缓存控制。
nginx缓存设置
nginx提供了expires、etag、if-modified-since指令来进行浏览器缓存控制。
expires
假设我们使用nginx作为静态资源服务器,此时可以使用expires进行缓存控制。
location /img {
alias /export/img/;
expires 1d;
}
当我们访问静态资源时,如http://192.168.61.129/img/1.jpg,将得到类似如下的响应头:
对于静态资源会自动添加ETag,可以通过添加“etag off”指令禁止生成ETag。如果是静态文件Last-Modified是文件的最后修改时间;Expires是根据当前服务端系统时间算出来的。如上nginx配置的计算逻辑(实际计算逻辑比这个多,具体参考官方文档):
if (expires == NGX_HTTP_EXPIRES_ACCESS ||r->headers_out.last_modified_time == -1) {
max_age = expires_time;
expires_time += now;
}
if-modified-since
此指令用于表示nginx如何拿服务端的Last-Modified和浏览器端的If-Modified-Since时间进行比较,默认“if_modified_since exact”表示精确匹配,也可以使用“if_modified_sincebefore”表示只要文件的上次修改时间早于或等于浏览器短的If-Modified-Since时间,就返回304。
nginx proxy expires
使用nginx作为反向代理时,请求会先进入nginx,然后nginx将请求转发给后端应用。如下图所示:
首先配置upstream:
upstream backend_tomcat {
server 192.168.61.1:9080 max_fails=10 fail_timeout=10s weight=5;
}
接着配置location:
location = /cache {
proxy_pass http://backend_tomcat/cache$is_args$args;
}
接下来我们可以通过如http://192.168.61.129/cache?millis=1471349916709访问nginx,nginx会将请求转发给后端java应用。也就是说nginx只是做了相关的转发(负载均衡),并没有对请求和响应做什么处理。
假设对后端返回的过期时间需要调整,可以添加expires指令到location:
location = /cache {
proxy_pass http://backend_tomcat/cache$is_args$args;
expires 5s;
}
然后再请求相关的URL,将得到如下响应:
过期时间相关的响应头被expires指令更改了,但是Last-Modified是没有变的。
即使我们更改了缓存过期头,但nginx本身没有对这些内容做缓存,每次请求还是要到后端验证的,假设在过期时间内,这些验证在nginx这一层验证就可以了,不需要到后端验证,这样可以减少后端的很大压力。即整体流程是:
1、浏览器发起请求,首先到nginx,nginx根据url在nginx本地查找是否有文档缓存;
2、nginx没有找到本地缓存,则去后端获取最新的文档,并放入到nginx本地缓存中;返回200状态码和最新的文档给浏览器;
3、nginx找到本地缓存了,首先验证文档是否过期(Cache-Control:max-age=5),如果过期则去后端获取最新的文档,并放入nginx本地缓存中,返回200状态码和最新的文档给浏览器;如果文档没有过期,如果If-Modified-Since与缓存文档的Last-Modified匹配,则返回300状态码给浏览器,否则返回200状态码和最新的文档给浏览器。
即内容不需要动态(计算、渲染等)速度更快,内容越接近于用户速度越快。像apache traffic server、squid、varnish、nginx等技术都可以来进行内容缓存。还有CDN就是用来加速用户访问的:
即用户首先访问到全国各地的CDN节点(使用如ATS、Squid实现),如果CDN没命中,会回源到中央nginx集群,该集群如果没有命中缓存(该集群的缓存不是必须的,要根据实际命中情况等决定),最后回源到后端应用集群。
像我们商品详情页的一些服务就大量使用了nginx缓存减少回源到后端的请求量,从而提升访问速度。可以参考《构建需求响应式亿级商品详情页》、《京东商品详情页服务闭环实践》和《应用多级缓存模式支撑海量读服务》。
nginx代理层缓存
http模块配置:
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_cache_path /export/cache/proxy_cachelevels=1:2 keys_zone=cache:512m inactive=5m max_size=8g use_temp_path=off;
#proxy timeout
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
其中红色部分是proxy_cache_path指令相关配置:
levels=1:2 :表示创建两级目录结构,比如/export/cache/proxy_cache/7/3c/,将所有文件放在一级目录结构中如果文件量很大会导致访问文件慢;
keys_zone=cache:512m :设置存储所有缓存key和相关信息的共享内存区,1M大约能存储8000个key;
inactive=5m :inactive指定被缓存的内容多久不被访问将从缓存中移除,以保证内容的新鲜;默认10分钟;
max_size=8g :最大缓存阀值,“cachemanager”进程会监控最大缓存大小,当缓存达到该阀值,该进程将从缓存中移除最近最少使用的内容;
use_temp_path:如果为on,则内容首先被写入临时文件(proxy_temp_path ),然后重命名到proxy_cache_path指定的目录;如果设置为off,则内容直接被写入到proxy_cache_path指定的目录,如果需要cache建议off,该特性是1.7.10提供的。
location配置
location = /cache {
proxy_cache cache;
proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid 200 5s;
proxy_pass http://backend_tomcat/cache$is_args$args;
add_header cache-status $upstream_cache_status;
}
缓存相关配置:
proxy_cache :指定使用哪个共享内存区域存储缓存键和相关信息;
proxy_cache_key :设置缓存使用的key,默认为访问的完整URL,根据实际情况设置缓存key;
proxy_cache_valid :为不同的响应状态码设置缓存时间;如果是proxy_cache_valid 5s 则200、301、302响应将被缓存;
proxy_cache_valid
proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下):
1、以秒为单位的“X-Accel-Expires”响应头来设置响应缓存时间;
2、如果没有“X-Accel-Expires”,可以根据“Cache-Control”、“Expires”来设置响应缓存时间;
3、否则使用proxy_cache_valid设置的缓存时间;
如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。
add_headercache-status $upstream_cache_status在响应头中添加缓存命中的状态:
HIT:缓存命中了,直接返回缓存中内容,不回源到后端;
MISS:缓存没有命中,回源到后端获取最新的内容;
EXPIRED:缓存命中但过期了,回源到后端获取最新的内容;
UPDATING:缓存已过期但正在被别的nginx进程更新;配置了proxy_cache_use_staleupdating指令时会存在该状态;
STALE:缓存已过期,但因后端服务出现了问题(比如后端服务挂了)返回过期的响应;配置了如proxy_cache_use_stale error timeout指令后会存在该状态;
REVALIDATED:启用proxy_cache_revalidate指令后,当缓存内容过期时nginx通过一次If-Modified-Since的请求头去验证缓存内容是否过期,此时会返回该状态;
BYPASS:proxy_cache_bypass指令有效时强制回源到后端获取内容,即使已经缓存了;
proxy_cache_min_uses
用于控制请求多少次后响应才被缓存;默认“proxy_cache_min_uses 1;”,如果缓存热点比较集中、存储有限,可以考虑修改该参数以减少缓存数量和写磁盘次数;
proxy_no_cache
用于控制什么情况下响应将不被缓存;比如配置“proxy_no_cache $args_nocache”,如果带的参数值至少有一个不为空或者0,则响应将不被缓存;
proxy_cache_bypass
类似于proxy_no_cache,但是其控制什么情况不从缓存中获取内容,而是直接到后端获取内容;如果命中则$upstream_cache_status为BYPASS;
proxy_cache_use_stale
当对缓存内容的过期时间不敏感,或者后端服务出问题时即使缓存的内容不新鲜也总比返回错误给用户强(类似于托底),此时可以配置该参数,如“proxy_cache_use_stale error timeout http_500 http_502 http_503http_504”:即如果超时、后端连接出错、500、502、503等错误时即使缓存内容已过期也先返回给用户,此时$upstream_cache_status为STALE;还有一个updating表示缓存已过期但正在被别的nginx进程更新将先返回过期的内容,此时 $upstream_cache_status为UPDATING;
proxy_cache_revalidate
当缓存过期后,如果开启了proxy_cache_revalidate,则会发出一次If-Modified-Since和If-None-Match条件请求,如果后端返回304则会得到两个好处:节省带宽和减少写磁盘的次数;此时$upstream_cache_status为REVALIDATED;
proxy_cache_lock
当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off)则只有一个请求被发送至后端;其他请求将等待该内容返回;当第一个请求返回时,其他请求将从缓存中获取内容返回;当第一个请求超过了proxy_cache_lock_timeout超时时间(默认5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的);启用proxy_cache_lock可以应对Dog-pile effect(当某个缓存失效时,同时又大量相同的请求没命中缓存,而同时请求到后端,从而导致后端压力太大,此时限制一个请求去拿即可)。
proxy_cache_lock_age是1.7.8新添加的,如果在proxy_cache_lock_age指定的时间内(默认5s),最后一个发送到后端进行新缓存构建的请求还没有完成,则下一个请求将被发送到后端来构建缓存(因为1.7.8版本之后,proxy_cache_lock_timeout超时之后返回的内容是不缓存的,需要下一次请求来构建响应缓存)。
清理缓存
有时候缓存的内容是错误的,需要手工清理,nginx plus版本提供了purger的功能,但是对于非plus版本的nginx可以考虑使用ngx_cache_purge(https://github.com/FRiCKLE/ngx_cache_purge)模块进行清理缓存,如:
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge cache$1$is_args$args;
}
注意该方法应该只允许内网可以访问,如有必要可以考虑需要密码才能访问。
到此代理层缓存就介绍完了,通过代理层缓存可以解决很多问题,可以参考《京东商品详情页服务闭环实践》和《京东商品详情页服务闭环实践》。
一些经验
1、只缓存200状态码的响应,像302等要根据实际场景决定(比如当系统出错时自动302到错误页面,此时缓存302就不对了);
2、有些页面不需要强一致,可以进行几秒的缓存(比如商品详情页展示的库存,可以缓存几秒钟,短时间的不一致对于用户来说是没有影响的);
3、js/css/image等一些内容缓存时间可以设置的很久(比如1个月甚至1年),通过在页面修改版本来控制过期,不建议随机数方式;
4、假设商品详情页异步加载的一些数据使用的是Last-Modified进行的过期控制,而服务端做了逻辑修改但内容是没有修改的,即内容的最后修改时间没变,如果想过期这些异步加载的数据,可以考虑在商品详情页添加异步加载数据的版本号,通过添加版本号来加载最新的数据,或者将Last-Modified时间加1来解决;而这种情况比较适合使用ETag;
5、商品详情页异步加载的一些数据,可以考虑更长时间的缓存(比如1个月而不是几分钟),可以通过MQ将修改时间推送商品详情页,从而实现按需过期数据;
6、服务端考虑使用内存缓存(tmpfs)、SSD缓存;考虑服务端负载均衡算法,如一致性哈希提升缓存命中率;
7、缓存KEY要合理设计(比如去掉参数/排序参数保证代理层缓存命中),要有清理缓存的工具,出问题时能快速清理掉问题KEY;
8、AB测试/个性化需求时应禁用掉浏览器缓存,但考虑服务端缓存;
9、为了便于查找问题,一般会在响应头中添加源服务器信息,如访问京东商品详情页会看到ser响应头,此头存储了源服务器IP,以便出现问题时知道哪台服务器有问题。
相关阅读
参考
https://www.w3.org/Protocols/HTTP/1.0/spec.html
https://www.w3.org/Protocols/rfc2616/rfc2616.html
http://nginx.org/en/docs/http/ngx_http_headers_module.html#expires
http://nginx.org/en/docs/http/ngx_http_core_module.html#if_modified_since
http://nginx.org/en/docs/http/ngx_http_core_module.html#etag
相关推荐
**基于AJAX的高并发数据传输与缓存技术研究** 在现代Web开发中,AJAX(Asynchronous JavaScript and XML)已经成为提升用户体验的关键技术。通过在后台与服务器进行异步数据交换,AJAX允许网页实现部分刷新,无需...
在构建Java高并发秒杀系统时,我们通常会利用一系列技术和设计原则来确保系统的稳定性和高效性。这个系统采用的技术栈包括SpringMVC、Maven、MySQL以及Spring和MyBatis,这些都是Java开发中的核心组件。 **...
总结,这个项目展示了如何运用SSM框架和前端技术构建一个高并发的秒杀系统,涉及了从后端架构设计、数据库交互、高并发处理策略到前端用户体验等多个层面的技术要点。通过学习和实践,开发者可以提升在大型项目中的...
【基于Node.js的高并发电商购物系统设计与实现】 在当今互联网时代,电子商务网站面临着日益增长的并发访问压力,特别是由于直播营销和各种电商节日活动的兴起,这使得企业对高性能、高并发的系统需求更加迫切。...
【标题】:基于SpringBoot的高并发限时抢购秒杀系统设计与实现 【描述】:这个项目是一个使用SpringBoot框架构建的高并发限时抢购(秒杀)系统,它涵盖了从后端服务到数据库的设计与实现。系统的核心目标是处理大量...
面对高并发场景下的挑战,静态化架构设计成为了提高性能的有效手段之一。尽管系统已经经过了多次升级,包括架构优化、模块优化、代码优化和增加缓存等措施,但在极端情况下,这些措施仍难以满足进一步提升性能的需求...
《亿级流量网站架构核心技术——跟开涛学搭建高可用高并发系统》是一本深入探讨如何构建能够处理大规模用户访问的互联网系统的技术书籍。在现代互联网行业中,面对日益增长的用户需求和流量压力,设计出高可用、高...
在IT行业中,高并发解决方案是针对大量用户同时访问或操作同一系统、应用或服务时,保证系统稳定、高效运行的技术策略。高并发场景通常出现在互联网服务、电子商务、社交媒体、在线游戏以及大数据处理等领域。以下是...
### 大型网站系统构架-高并发高负载 随着互联网技术的发展,越来越多的企业和组织开始构建自己的在线平台,特别是大型网站,如门户站点等。这些网站通常面临着大量的用户访问和高并发请求的压力。为了应对这些问题...
1.1 高并发原则 3 1.1.1 无状态 3 1.1.2 拆分 3 1.1.3 服务化 4 1.1.4 消息队列 4 1.1.5 数据异构 6 1.1.6 缓存银弹 7 1.1.7 并发化 9 1.2 高可用原则 10 1.2.1 降级 10 1.2.2 限流 11 1.2.3 切流量 12 1.2.4 可回滚...
在互联网快速发展的今天,Web系统常常需要处理大量的并发访问请求。高并发Web系统的涉及与优化,是确保系统稳定性...随着Web技术的不断进步,高并发系统的优化方法也将继续演进和丰富,以适应不断增长的网络应用需求。
**面试篇**包含了高并发场景下的优化策略和常见问题,比如优化加锁方式可能导致的死锁,缓存穿透、击穿和雪崩的现象及其解决方案,以及Java中synchronized和Lock的区别和使用场景。 **系统架构篇**涉及高并发下的...
综上所述,"ssm高并发之秒杀系统"项目涵盖了从架构设计到具体实现的多个层面,涉及了Java Web开发中的核心技术和高并发场景下的优化策略,是学习和实践高并发系统设计的一个良好案例。通过深入理解和实践这个项目,...
在高并发架构中,合理利用缓存技术能够显著提升系统性能。 redis作为一个开源的内存数据结构存储系统,也常被用于高并发场景。它支持数据的持久化,可以存储临时的数据以及作为消息队列使用,对于降低数据库的读写...
对于高并发系统,我们需要关注以下几个关键指标: 1. **QPS(Queries Per Second)**:每秒钟的查询次数。这是衡量系统处理能力的重要指标之一。 2. **响应时间**:从客户端发起请求到接收到响应的时间长度。理想...
在IT领域,构建高并发高性能服务器是至关重要的技术挑战,特别是在大数据时代,处理大量用户请求、实时数据交换以及保持高效的服务响应成为系统设计的核心。本资料包提供的"高并发高性能服务器"源码提供了深入理解这...
"牛客网Linux高并发服务器开发"这个压缩包文件,显然聚焦于利用Linux进行高性能服务器的设计与实现,这涉及到多个核心知识点。下面将详细阐述这些关键概念。 1. **嵌入式Linux开发**: 嵌入式Linux是Linux操作系统...
Redis是一个内存数据存储系统,常用于缓存、计数器和消息队列等场景,尤其适合高并发环境,因为它提供了低延迟的数据操作。 描述中提到,“php程序设计,web系统源码,源码,数据库MySQL”表明这是一个基于PHP的Web...
在Go语言的支持下,Go-pike具有高性能和低延迟的特点,能够处理高并发的网络请求,从而提升整体的Web服务响应速度。此外,Go语言的跨平台性也使得Go-pike能够在各种操作系统上无缝运行。 在使用Go-pike时,开发者...