day14项目优化总结第八章_第1页
day14项目优化总结第八章_第2页
day14项目优化总结第八章_第3页
day14项目优化总结第八章_第4页
day14项目优化总结第八章_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章目优化1id2、根据文件id查询信息这些接口在用户未认证状态下也可以,如果接口的性能不高,当高并发到来很可id接口地址 在发布前也是需要经历压力测试的,因为压力测试可以功能测试所发现不了的问比如:一个站,上线要求该可以支持1万用户同时,此时就需要模拟1万并发请求去的关键业务流程,比如:测试点播学习流程,测试系统是否可以抗住1万并发请求。全、IO异常等问题。1Second2second品信息查询,一秒可以请求该接口查询商品信息的次数就是QPS。拿查询接口举例,一次查询请求内部不会再去请求其它接口,此时QPS=TPS如果一次查询请求内容需要调用另一个接口查询数据,此时QPS=2*TPS小,吞吐量越来越大,以及QPS值也是越大越好,错误率要保持在一个很小的范围。1、CPU234、磁盘磁盘IO的性能指标是IOPSInput/OutputPerSecond)即每秒的输入输出量(或读写次如果过大说明IO操作密集,IOApacheJMeterApacheJava开发的压力测试工具,用于对软件做压力测Jmeter,解压,进入 修改perties,设置中文和字jsyntaxtextarea.font.family=Hack双击运行 下的jmeter.bat文件样本数:20010020000次测试180测试300内容管理日志级别改为info级别redisid查询课程信息,这里不存在复杂的SQL,也不存在数据库连接不释在nacos配置redis- host:port:6379password:redisdatabase:0max-active:max-idle:min-idle:timeout:在content-api微服务加载redis--data-id:redis-${files.active}.yaml refresh:在content-service @description@param@return@author@date2022/10/22publicCoursePublishgetCoursePublishCache(LongpublicCoursePublishgetCoursePublishCache(LongObjectjsonObj=redisTem te.opsForValue().get("course:"+StringjsonString=jsonObj.toString();CoursePublishcoursePublish=JSON.parseObject(jsonString,return}elseCoursePublishcoursePublish=getCoursePublish(courseId); te.opsForValue().set("course:"+}return}}}修改controller publicCoursePreviewDtogetCoursePublish(@PathVariable("courseId")LongcourseId)CoursePublishcoursePublish CoursePublishcoursePublish=returnnew}CourseBaseInfoDtocourseBase=newCourseBaseInfoDto();BeanUtils.copyProperties(coursePublish,courseBase); nDto>teach ns= n(),Teach CoursePreviewDtocoursePreviewInfo=newreturn}吞吐量达到2700左右,增加了近一倍。从数据库查询比如去请求/content/course/whole/181181号课程,该课程并不在课程发布表大量并发去一个数据库不存在的数据,由于缓存中没有该数据导致大量并发查询数据库,这个现象要缓存。缓存可以造成数据库瞬间压力过大,连接数等资源用完,最终数据库连接不如何解决缓存比如:课程Id2、使用过滤什么是过滤器,以下摘自百科种思路.但是随着集中元素增加,我们需要空间越越OnOon(表,ashtbe的数据结构。它可以通过一个shBtaay)1中有没有它了。就是过器的基本思。比如:将商品id写入过滤器,如果分3次hash此时在过滤器有3个点,当从过滤器查询该商品id,通过hash找到了该商品id在过滤器中的点,此时返回1,如果找不到一定会返回0。所以,为了避免缓存我们需要缓存预热将要查询的课程或商品信息的id提前存入过滤器,添加数据时将信息的id也存入过滤器,当去查询一个数据时先在过工具包Guava实现。redissonpublicCoursePublishgetCoursePublishCache(LongcourseId)ObjectjsonObj=redisTem te.opsForValue().get("course:"+StringjsonString=jsonObj.toString();returnCoursePublishcoursePublish=JSON.parseObject(jsonString,return}elseCoursePublishcoursePublish= te.opsForValue().set("course:"+courseId,JSON.toJSONString(coursePublish),30,TimeUnit.SECONDS);return}}缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽造成缓存雪崩问题的原因是是大量key拥有了相同的过期时间,比如对课程信息设置10分钟,在大量请求同时查询大量的课程信息时,此时就会有大量的}2、对同一类型信息的key通常对一类信息的key设置的过期时间是相同的,这里可以在原有固定时间的基础上 te.opsForValue().set("course:"+courseId,JSON.toJSONString(coursePublish),300+newRandom().nextInt(100),3热机制通常有专门的程序去将数据库的数据同步到缓存。缓存击穿是指大量并发同一个热点数据,当热点数据失效后同时去请求数据库,}可以由程序提前将热点数据加入缓存,缓存过期时间不过期,由程序做好缓下边使用synchronizedpublicCoursePublishgetCoursePublishCache(LongcourseId){StringjsonString= te.opsForValue().get("course:"+courseId);returnnull;CoursePublishcoursePublish=JSON.parseObject(jsonString,CoursePublish.class);returncoursePublish;CoursePublishcoursePublish= te.opsForValue().set("course:"+courseId,JSON.toJSONString(coursePublish),300,TimeUnit.SECONDS);return}}}1300对上边的代码进行优化,对查询缓存的代码不用synchronized加锁控制,只对查询数publicCoursePublishgetCoursePublishCache(LongObjectjsonObj te.opsForValue().get("course:"+courseId);StringjsonString=jsonObj.toString();CoursePublishcoursePublish=JSON.parseObject(jsonString,CoursePublish.class);returncoursePublish;ObjectjsonObj= te.opsForValue().get("course:"+courseId);StringjsonString=jsonObj.toString();CoursePublishcoursePublish=JSON.parseObject(jsonString,return}//CoursePublishcoursePublish= te.opsForValue().set("course:"+courseId,JSON.toJSONString(coursePublish),300,TimeUnit.SECONDS);return}}}}1)缓存去一个数据库不存在的数据无法将数据进行缓存,导致查询数据库,当并发较大就会对数据库造成压力。缓存可以造成数据库瞬间压力过大,连接数等资源用完,最终数据库连接不可用。缓存一个null值。使用过滤器。缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资造成缓存雪崩问题的原因是是大量key拥有了相同的过期时间。对同一类型信息的key设置不同的过期时间,比如:使用固定数+随机数作为过期时3)大量并发同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据设置key永不过期无中生有是,过滤null。缓存击穿keykey过期后key只会查询一次下边进试:虚拟机都去抢占同一个锁,锁是一个单独的程序提供加锁、服务,谁抢到锁谁去2、基于redis拿SETNX举例说明,SETNX命令的工作过程是去set一个不存在的key,多个线程去设置同一个key只会有一个线程设置成功,设置成功的的线程拿到锁。3、使用zookeeperzookeeper是一个分布式协调服务,主要解决分布式程序之间的同步的问题。zookeeper的结构类似的文件 ,多线程向zookeeper创建一个子 RedisNX SETresource-nameanystringNXEXmax-lock-timeNXkey这里启动三个ssh客户端,连接redis:dockerexecitredisredis-先认证auth表示设置lock001锁,value00130ininSETlock001001NXEX命令发送成功,观察三个ssh客户端发现只有一个设置成功,其它两个设置失败,设置成功的请求表示抢到了lock001锁。如何在代码中使用Setnx使用spring-boot-starter-data-redis提供的api即可实现setnx。 }}}这里考虑一个问题,当setnx一个key/value1后,这个key(就是锁)需要设置过如果不设置过期时间当获取到了锁却没有执行finally这个锁将会一直存在,其它线程所以执行setnx时要指定过期时间,即使用如下SETresource-nameanystringNXEXmax-lock-var3TimeUnitvar5)因为锁设置了过期时间,key等操作还没有执行完时key到期了,此时其它线程就抢到锁了,最终重复查询数据库可以将key的到期时间设置的长一些,足以执行完成查询数据库并设置缓存等相关操如果是采用手动删除锁可能和key到期自动删除有所,造成删除了别人的锁比如:当查询数据库等业务还没有执行完时key过期了,此时其它线程占用了锁,当获取分布式锁setlock01NX释放锁}}}} 在调用setnx命令设置key/value时,每个线程设置不一样的value值,这样当线程去删除锁时可以先根据key查询出来判断是不是自己当时设置的vlaue这整个操作是原子的,实现方法就是去执行上边的luaLua是一个小巧的语言,redis在2.6版本就支持通过执行Lua保证多个命令以上就是使用RedisNx方式实现分布式锁,为了避免删除别的线程设置的锁需要使用redis去执行Lua的方式去实现,这样就具有原子性,但是过期时间的值设置不存什么是再查阅文档 点击查我们选用Java的实现方 Redisson底层采用的是Netty框架。支持Redis2.8以上版本,支持Java1.6+以上版本。Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-MemoryGrid务。其中包括(BitSet,Set,Multimap,SortedSet,Map,List,Queue,BlockingQueue,Deque,BlockingDeque,Semaphore,Lock,AtomicLong,CountDownLatch,Publish/Subscribe,Bloomfilter,Remoteservice,SpringcacheExecutorserviceLiveObjectserviceSchedulerservice)。使用Redisson可以非常方便将Java本地内存中的常用数据结构的对象搬到分布式缓存redis中。也可以将常用的并发编程工具如:AtomicLong、CountDownLatch、Semaphore等支使用RScheduledExecutorService实现分布式调度服务。支持数据分片,将数据分片到不同的redis实例中。支持分布式锁,基于Java的Lock下边使用Redisson将Queue队列的数据存入Redis添加redisson 拷贝singleServerConfig.yaml到config工程下在redis配置文件中添加:config:classpath:singleServerConfig.yaml#config:classpath:clusterServersConfig.yamlredis集群配置Redisson相比setnx线程去获取锁,获取成功:执行lua,保存数据到redis数据库线程去获取锁,获取失败一直通过whilelua,保存数据到设置默认30秒时,这样的目的主要是防止死锁的发生第二种情况:线程A业务还没有执行完,时间就过了,线程A就会启动一个watchdog线程,不断的延长锁key的生存时间lua-保证原子性操主要是如果你的业务逻辑复杂的话,通过封装在lua中发送给redis,而且redis是单线程的,这样就保证这段复杂业务逻辑执行的原子性具体使用RLock操作分布锁,RLock继承JDK的Lock接口,所以他有Lock接口的所有特性,比如lock、unlock、trylock等特性,同时它还有很多新特性:强制锁释放,publicinterfaceRRLock30void@paramleaseTime@param voidlock(longleaseTime,TimeUnittrue,如果获取失败(即锁已被其他线程获取false.booleantryLock(longtimeTimeUnitunit)tryLock()false。如果如果一开始拿到锁true。@paramtime@paramunitbooleantryLock(longtime,TimeUnitunit)throws*@paramwaitTime@paramleaseTime@param waitTime大于booleantryLock(longwaitTime,longleaseTime,TimeUnitunit

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论