G1原理—10.如何优化G1中的FGC
大纲
1.G1的FGC可以优化的点
2.一个bug导致的FGC(Kafka发送重试 + subList导致List越来越大)
3.为什么G1的FGC比ParNew + CMS要更严重
4.FGC的一些参数及优化思路
1.G1的FGC可以优化的点
(1)FGC的基本原理
(2)遇到FGC应该怎么处理
(3)应该如何操作来规避FGC
(4)应该如何操作来加快FGC的速度
(1)FGC的基本原理
一.FGC的并行处理
G1有两个得天独厚的优势:
优势一.Region是一个相对独立的内存区域
优势二.每个Region都有一个RSet
通过GC Roots + RSet,就能完整对某Region进行所有存活对象的标记。
二.FGC的并行处理流程
并行FGC开始前的前置工作:对象头、锁信息等信息的保存处理。在保存完一些对象头相关的信息之后,就要开始FGC了。
具体步骤和串行化的FGC是类似的。
步骤一:标记所有存活对象
步骤二:计算对象的新地址
步骤三:更新对象间的引用地址
步骤四:移动对象完成压缩
步骤五:对象移动后的后续处理
三.并行标记过程STW
FGC并行化后,其并行标记过程和串行化过程时差别不是很大,都是要标记出来所有的存活的对象。
需要注意的是:因为是并行化处理,所以多个线程在进行并行标记时,每个线程都会比起串行化处理时,多一个标记栈(任务栈)。也就是把起始对象GC Roots分成多份,每一个GC线程持有一部分。
FGC会对所有堆分区里的对象都进行标记,而且系统程序会STW。
四.FGC标记过程中的任务窃取
完成任务栈的对象标记的线程会从未完成的线程那里窃取一些任务。
(2)遇到FGC应该怎么处理
一.尽可能避免
FGC是需要极力避免的,JVM的优化手段多数都是尽可能减少FGC的出现。比如调整分代比例、Region大小、停顿时间、老年代预留空间比例等。所以,对于FGC的处理,最重要的手段就是避免它。
二.尝试优化FGC的速率
如果是正常的FGC,优化速率的方法就是,减少FGC需要处理的量。也就是FGC时,避免堆中存在大量需要复杂处理的对象。
(3)应该如何操作来规避FGC
基本的思路还是要避免达到产生FGC的条件。
一.产生FGC的条件主要是以下两种
条件一:MGC不及时,导致垃圾对象存活过多,造成空间不够
这其实也是并发标记的启动时机存在问题。如果并发标记启动的频率,远远落后于垃圾产生的速率。那么就会出现大量空间被垃圾对象占用,导致不必要的FGC。另外就是回收速度太低,导致停顿时间内回收垃圾太少,造成空间不够。
条件二:存活对象太多,各种GC都尝试过,无法腾出足够空间给新对象
执行了YGC + MGC后出现晋升失败,不得不进行FGC。
二.产生FGC的场景主要是以下两种
场景一:G1使用的算法,是标记复制算法(YGC和MGC) + 标记整理算法(FGC)。在进行垃圾回收时,新创建的对象及存活的对象,没有足够空间可使用。复制操作无法实现,因为每次GC的存活对象要复制到空闲Region中。
场景二:多次GC后仍然无法给新对象腾出足够的空间,导致FGC。此时所能做的就是尽可能合理优化参数,保证不触发这些场景。
(4)应该如何操作来加快FGC的速度
FGC的速度,在JVM层面其实已经做了很多优化,包括并行优化等。那么在此基础之上,我们还能通过什么策略来提升FGC的速度?比如要减少FGC处理的总量,靠减少堆内存来减少FGC要处理的总量吗?针对FGC的速度要做的优化,不能简单的从堆内存空间大小来考虑。
G1提供了一种思路,叫"弥留空间"。当G1发现经历多次GC后,就会允许一定比例的空间,作为把垃圾对象当成存活对象处理的空间。这些垃圾对象所在的一定范围的区域,可以成为弥留空间。虽然这个弥留空间是垃圾对象,但在GC处理时,是当作存活对象来处理。
FGC在处理这块弥留空间里的对象时,会把它们直接当作存活对象来处理,不需要做各种复杂的标记、判定引用、指针替换等各种操作,直接去复制。明知是死亡对象,但此时先不做全部空间的标记压缩整理,而只做部分的。所以弥留空间就能快速被跳过,减少处理空间,一定程度提高FGC的速率。弥留空间,就是为了提升FGC的效率而设计的。
2.一个bug导致的FGC(Kafka发送重试 + subList导致List越来越大)
(1)运营场景业务分析
(2)业务场景背景介绍
(3)问题现场及问题排查
(4)问题解决
(1)运营场景业务分析
一般在电商公司里会有一个运营平台,有些公司叫营销平台,这个平台的作用主要就是拉新、增涨营收。就是通过运营平台发起活动、或者投放广告,来实现用户增长。对于平台的存量用户,也会有优惠活动、节日福利活动等来留住用户。
各种各演的运营活动,都会通过运营平台去产生。然后专门有一个抽离的运营消息推送服务来推送运营活动消息给用户。由于这些消息的数量非常庞大,对于一家几十万上百万的用户,一天假如有3次运营活动,就要至少好几百万甚至上千万的的消息要推送。这么大量的消息,不会直接全量推送,而是生成推送消息,发送到MQ,然后通过一个消费者去消费这些消息,慢慢把千万级别的消息推送给用户。
(2)业务场景背景介绍
在这个场景中,一个很重要的要点就是:运营消息推送平台会生成消息推送到消息中间件Kafka中。这个消息生成、推送至MQ的速率,很大程度影响到整个推送流程的速度。
因此,对这个消息生成和推送的过程,就需做优化,当时优化的思路是:
一.分布式生成消息,即多台机器,把用户群体分成多个部分来生成消息
二.batch推送消息,减少与消息中间件的网络通信
三.运营消息推送平台,使用多线程并发推送batch消息
四.把一些大批量的查询借助一些其他的数据搜索引擎或缓存来提升效率
比如,借助JVM本地缓存,每台机器保存一些用户账号相关信息。比如,使用ES来存储用户信息,提升多条件下的搜索查询效率。比如,使用Redis Cluster缓存,避免使用数据库导致效率低。
这些基本的思路其实还是比较简单的,细节上的优化就是:batch的大小如何确定、多线程推送时线程池的线程数量要怎么设置等。
(3)问题现场及问题排查
一.引发OOM的原因是频繁FGC
然后在一次优化测试上线后,运行一段时间,没有什么大问题。在某天Kafka服务发生了一次抖动,持续时间大概5-6s的时间,然后发现这个运营平台直接崩溃了。
在优化前,这个运营平台的推送效率有待提升,但是系统还是很稳定的。出现这个问题后紧急查看了报错日志,发现是堆内存OOM导致进程崩溃。
于是下载GC日志,下载内存快照文件,查看dump快照文件,最后发现是batch推送时线程池中的线程持有了大量的大List对象。
本来是打算找OOM的原因,解决OOM问题的。但发现在OOM前出现了大量的FGC,而大量的FGC才最终导致系统崩溃。
那么结合dump快照里大量的List对象,很容易想到是大量的List导致频繁FGC。而大量的List都还存活,所以最终导致OOM。
二.频繁FGC的原因是List造成的对象过大
那么为什么会有这么多次FGC,为什么有这么多的List没被回收?通过代码排查,发现了一个很严重的代码bug,这个bug其实很好规避。
原来在代码中采取的策略是:每次会查询一组用户数据,这组用户数据会有2000个用户。然后将这组数据封装成消息体是按照一个List放200个用户去封装,也就是将200个用户封装成一个List消息体之后,才会发送到Kafka中。
注意:Kafka本身也有一个缓冲机制来实现batch发送。我们的代码将消息一条一条发送时,Kafka会在本地客户端暂存。存到一定大小时,才会按照一个批次推送到Kafka服务端。
这种策略正常来说是没问题的,因为200个用户封装后的大小也不大。但是写代码时,因为运营的一个需求,把其中一段代码修改了一下。运营要求在某个促销活动下,消息必须推送到用户侧,不能出现漏发错发多发。
原有的代码是:把拿到的2000一组的用户数据,拆分成10个batch,然后推送至Kafka。假如推送失败就不管了,因为漏发某个用户的消息也问题不大。
修改后的代码是:针对这种特殊活动,添加了一些逻辑,即等待Kafka返回推送结果。如果拿到推送结果则表明推送成功,则执行完毕。如果拿不到推送结果则表明推送失败,需要把失败的用户集,重新加入到一个集合中去重试推送。具体的伪代码如下:
//获取一组用户信息
ArrayList list = getUserList();
List subList;
List failList = new ArrayList();
int index = 0;
//拆分用户信息
while(true) {
if (index >= list.size()-1) {
break;
}
subList = list.subList(index, index + 200);
kafkaPushResult = sendToKafka();
//等待发送结果
if (kafkaPushResult == false) {
//发送失败,是第一次,就把发送失败的subList赋值给failList
if (index == 0) {
failList = subList;
}
//不是第一次,就把发送失败的全部加入到failList中,等待后续继续发送
failList.addAll(subList);
}
}
上述代码看起来是不是没什么问题?事实上,当这个kafkaPushResult失败没有触发时,确实不会出什么问题。但是一旦触发了失败,就会出现问题了。
原因在于对于List来说,subList不是新建了一个对象,而是把大的list的其中一段使用了两个指针去指向它,所以本质上subList还是大的list的一部分。
那么如果频繁触发发送失败,failList这么写就相当于是大的list的一部分。那么执行failList.addAll(subList)代码时,相当于是在把这部分失败的元素,加入到大的list里。
所以,list是会越来越大。如果一次推送几十万用户的消息,一个线程池里面设置30-60个线程。那么在Kafka抖动的几秒的这段时间,这些list会极速扩张好几千倍不止。也就是说,假设这5s内,一共能拿到10w的用户数据。那么在5s内就会膨胀到几千万甚至上亿的数据,紧接着,重试操作会针对这些数据重试,而这个大的list又暂时不释放。如果Kafka抖动时间短,经历几次FGC就完成重新推送,没什么问题了。如果Kafka经常抖动或抖动时间长,就会造成频繁的FGC,甚至OOM。
这个场景,由于FGC产生的原因比较直接。所以分析时很容易通过GC日志 + dump快照文件迅速定位了问题。但很多FGC场景,产生的原因各不相同,分析过程还是会非常复杂的。不过基本思路都是:系统日志 -> 监控数据 -> GC日志 -> dump文件 -> 代码反查 -> bug复现 -> 解决问题。
(4)问题解决
知道了问题原因,其实就很好解决了。根本原因还是因为在写代码时对api源码的实现不熟悉,同时也没有深入检查代码的习惯,导致在做一些业务处理时出现了意想不到的bug。
对于这个代码,其实只需要做一个改动就OK了。在外层初始化failList,并且在需要把subList数据作为数据源的操作时,使用addAll操作,把它加入到新的list中再进行操作即可。
failList = new ArrayList();
if (index == 0) {failList = subList;
}->
failList.addAll(subList)
在使用subList拆分list时,一定要熟悉一下这个subList的源码实现方式。往往JDK的一些优化手段,会给我们程序造成一些不必要的问题。
此外,如果出现了频繁FGC,很有可能是对象产生的速度和垃圾回收的速度匹配不上,回收的量不够就会有可能OOM了。
3.为什么G1的FGC比ParNew + CMS要更严重
(1)ParNew + CMS的FGC触发
(2)G1的FGC触发
(3)G1的FGC更加恐怖的原因总结
(1)ParNew + CMS的FGC触发
ParNew + CMS触发的FGC的规则其实还是比较简单的,总结来说,就是老年代不够用了。
当然老年代不够用的过程可能比较多:新生代晋升、大对象占用等。但使用ParNew + CMS时,新生代和老年代的比例往往都是比较均衡,有些系统新生代甚至远大于老年代。
那么在这种场景下,FGC相对来说回收的空间就不算太恐怖,毕竟回收的空间只有堆内存的1/2左右。比较耗时的地方就是:全量标记、对象复制、压缩整理的过程。因此FGC即使偶尔发生一次,比如一天一次或几小时一次,也能接受。
并且老年代对象的晋升,是有一系列的担保机制的,比如:老年代剩余内存大于新生代存活对象、老年代剩余内存大小大于历次新生代晋升到老年代的对象的平均大小等。
因此综合分析下来,ParNew + CMS触发FGC时,从空间上和处理算法(标记整理)上来说,偶尔一次还是能够接受的。
(2)G1的FGC触发
G1的FGC触发场景,基本上有两种:
一.新生代晋升失败导致的FGC
有可能是因为晋升预留空间不够导致的,比如预留的晋升空间比例参数G1ReservePercent调整为了5,而新生代区本次晋升对象比较多,此时就会发生晋升失败导致FGC。
这种情况触发的FGC稍微好一点,因为老年代的实际使用量是:老年代大小 * (1 - --XX:G1ReservePercent%)。并且因为是晋升导致的FGC,此时新生代是刚执行完新生代回收的。所以基本上这种情况下导致的FGC,只需回收相对比较小的区域即可。
即便如此,这种情况下的FGC效率依然很低,因为涉及到大量的标记、压缩、整理、引用处理等各种操作。
二.对象分配失败导致的FGC
对象分配失败导致的FGC,就比较恐怖了。因为在对象分配失败时,会经历如下整个过程:TLAB -> TLAB扩展 -> 堆内存分配 -> Region扩展 -> YGC -> MGC -> 堆扩展 -> 分配失败。
如果是这个过程造成分配失败,则意味着整个堆内存的使用率非常高。即使经过了YGC + MGC + 扩展操作,还是无法成功分配。
这时进入的FGC就可以理解为:几乎大部分的内存都被占用了,连一个对象都无法成功分配。此时的FGC需要处理的Region,几乎是整个堆内存里的所有Region。
并且结合FGC的整个处理过程:标记->对象头处理->对象移动->压缩->清理->Rset处理等一系列操作,此时的FGC就会非常耗时。
所以这个情况下触发的FGC会非常恐怖,当然如果没有乱调参数,正常情况也不会发生这么恐怖的FGC。
三.总结
如果YGC执行后晋升失败导致FGC,那么就是reserve空间不够导致的。也就是分配对象失败,执行YGC后,必然会发生晋升,此时有可能就会在晋升失败前触发FGC来清理了。所以基本上不会出现达到多次YGC + MGC之后,还无法分配成功的情况。
但要注意有可能会出现:QPS暴增,对象产生速度比较快,然后回收速度比较慢,虽然经历了多次YGC,但垃圾对象依然很多的情况。
(3)G1的FGC更加恐怖的原因总结
一.G1通常来说要管理更大的堆内存空间,因此需要处理更多的对象
二.G1触发FGC的条件比较苛刻,分配失败的FGC需处理整个堆内存
三.G1在执行FGC过程中,需要针对复杂的Rset引用关系做更多处理
4.FGC的一些参数及优化思路(都围绕回收速度跟不上垃圾产生速度展开)
(1)-XX:G1HeapRegionSize
(2)-XX:G1ReservePercent默认是10
(3)-XX:MaxGCPauseMillis停顿时间
(4)-XX:InitiatingHeapOccupancyPercent
(5)-XX:ConcGCThreads
(6)-XX:G1ConcMarkStepDurationMillis
(7)-XX:MarkSweepAlwaysCompactCount
(1)-XX:G1HeapRegionSize
这个参数用于控制Region大小,调整这个参数可以避免老年代中的大对象占用过多的内存。因为老年代大对象占用过多的内存,就会提高老年代的使用率。老年代的使用率高了,就必然会增加晋升失败的概率。所以增大Region大小,可以避免不算太大的对象进入老年代,从而降低晋升失败的概率。
调大RegionSize的另外一个优点是:在发生对象复制、晋升时,PLAB也会相对大一些,从而在复制、晋升时,速率也会提升。
(2)-XX:G1ReservePercent默认是10
这个参数代表老年代预留给新生代对象晋升的空间占用堆内存的比例,如果经常因为晋升失败导致FGC,说明这个值太小。此时可适当调高这个值,降低FGC频率。
(3)-XX:MaxGCPauseMillis停顿时间
这个参数设置是否合理,关系到了垃圾回收的效率。假如设置了20ms的停顿时间,则很有可能导致每次GC回收的垃圾非常少。假如系统并发非常高,产生垃圾的速度非常快,就有可能会不断进行YGC。但是每次YGC都只能回收掉很少一部分垃圾,最终造成FGC。
所以,一个合理的停顿时间设置,是非常有必要的。一般情况下,系统的停顿时间可以设置100-200ms之间,具体情况需要根据系统运行情况及JVM监控情况来调整。
(4)-XX:InitiatingHeapOccupancyPercent
意思是当堆内存的占用比例达45%时,就会触发并发标记(可能开启MGC)。假如因为垃圾回收的速率跟不上系统产生垃圾的速度而造成频繁的FGC,那么就可以适当调低这个参数,尽快开启MGC,通过提升MGC的频率来避免JVM内堆积过多的垃圾对象。
注意:这个参数调小造成的多次GC和停顿时间造成的多次GC不是一个概念。
停顿时间造成的GC:是因为每次停顿时间不够,只能回收很少的垃圾,导致垃圾堆积最终FGC。
调小InitiatingHeapOccupancyPercent这个参数:此时停顿时间固定,但是回收的频率提升上来了。这样在同样的程序运行时间里,能够回收更多的垃圾,可以避免FGC。
(5)-XX:ConcGCThreads
这个参数是指在标记过程中的并行标记(STW)线程数量。如果因为并发标记不够及时,并发标记时间过长,导致垃圾回收的速率跟不上,造成FGC。
略微提升这个值,可能能够提升标记速度,以达到避免FGC的效果。当然线程数量多少,要和服务器的配置相匹配,不能盲目调大这个值。
(6)-XX:G1ConcMarkStepDurationMillis
这个参数指的是并发标记(不会STW)执行的时间,默认是10ms。调小该参数可以提升并发标记的次数,让并发标记触发的更加频繁一点,从而让重新标记更短一点,以此来提升垃圾回收的速率,避免垃圾回收速度跟不上垃圾产生速度,最终造成FGC。
正常来说这个参数也是不需要调整的,只有发现系统经常因为垃圾处理不及时而频繁的触发FGC,才有可能需要调小这个参数。
(7)-XX:MarkSweepAlwaysCompactCount
这个参数表示,经过多次GC后:允许JVM内存中有一定比例的空间用来将垃圾对象当作存活对象来处理,可以称这块儿空间为弥留空间。
弥留空间主要的目的就是可以把垃圾对象当作存活对象来处理,相当于给了一块比较好处理的空间,能够减少FGC时的处理压力。可以说是间接"减少FGC需要处理的空间",这个空间不宜太大。如果太大就会造成一部分空间被占用,一般来说保持默认即可。
(8)总结
上面介绍的这些参数,多数都是以"避免"FGC的思路来展开优化。只有第七个参数是通过为FGC"减负"的思路来展开优化,而且避免FGC通常都是从提升垃圾回收的速率这个角度出发:让垃圾回收速率赶上垃圾对象产生的速率。
对于FGC来说,"减负"这个思路,在多数情况下是无法采取的。因为FGC的特性就决定了不太可能通过其本身的参数调整来提速,更多的优化思路和优化手段还是要从"避免"角度出发,避免大多数FGC才是优化的重点。
回收速度跟不上垃圾产生速度总结:
一.调大RegionSize,让PLAB增大,从而加快复制、晋升的速度
二.调大老年代预留给新生代晋升的占比,降低晋升失败的频率
三.调小触发MGC的老年代占比,加快MGC
四.增加并发标记的线程,加快GC
五.降低每次并发标记的执行时间,降低重新标记时间,加快GC
六.调大弥留空间占比,降低FGC的处理压力,提升FGC的处理速度
为什么G1的FGC比ParNew + CMS要更严重:
一.ParNew + CMS的FGC触发
就是老年代不够用了。
二.G1的FGC触发条件
条件一:新生代晋升失败导致的FGC。
条件二:对象分配失败导致的FGC。
三.G1的FGC更加恐怖的原因总结
原因一:G1通常来说要管理更大的堆内存空间,因此需要处理更多的对象。
原因二:G1触发FGC的条件比较苛刻,分配失败的FGC需处理整个堆内存。
原因三:G1在执行FGC过程中,需要针对复杂的Rset引用关系做更多处理。
相关文章:
G1原理—10.如何优化G1中的FGC
大纲 1.G1的FGC可以优化的点 2.一个bug导致的FGC(Kafka发送重试 subList导致List越来越大) 3.为什么G1的FGC比ParNew CMS要更严重 4.FGC的一些参数及优化思路 1.G1的FGC可以优化的点 (1)FGC的基本原理 (2)遇到FGC应该怎么处理 (3)应该如何操作来规避FGC (4)应该如何操…...
【专题一 递归】21. 合并两个有序链表
1.题目解析 2.讲解算法原理 解法:递归-> 重复的子问题 重复子问题 ->函数头的设计 合并两个有序链表--->Node dfs(l1,l2) 只关心某一个子问题在做什么事情 ->函数体的设计 比大小l1→next dfs( l1.next, l2)return l1 递归的出口 if(l1null)return l2…...
WebSocket——推送方案选型
一、前言:为何需要服务端主动推送? 在现代应用中,很多功能都依赖于“消息推送”。比如: 小红点提醒:我们经常在手机应用里看到的一个小红点提示,表示有新的消息或任务需要我们关注。新消息提醒࿱…...
Openresty 安装
1. 依赖包安装: # yum install readline-devel pcre-devel openssl-devel 2. 在系统中添加openresty的仓库: # sudo yum install yum-utils # sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo …...
回归预测 | MATLAB实TCN时间卷积神经网络多输入单输出回归预测
效果一览 基本介绍 回归预测 | MATLAB实TCN时间卷积神经网络多输入单输出回归预测 …………训练集误差指标………… 1.均方差(MSE):166116.6814 2.根均方差(RMSE):407.5741 3.平均绝对误差(MAE):302.5888 4.平均相对…...
TikTok专线服务器助力品牌营销新高度
在这个信息爆炸的时代,短视频平台如雨后春笋般涌现,TikTok便是其中的佼佼者。众多品牌纷纷涌入这个平台,试图借助其强大的用户基础和传播能力来提升知名度。而在这其中,IPIPGO直播专线的出现,为品牌在TikTok上的营销提…...
flutter VoidCallBack ValueChange<T> 的函数定义
在 Flutter 中,VoidCallback 和 ValueChanged<T> 是两种常用的回调函数类型,它们通常用于处理事件或传递数据。下面是它们的详细定义及使用方式。 1. VoidCallback 函数类型 VoidCallback 是一个没有参数也没有返回值的回调函数类型。它通常用于简单的事件处理,比如…...
pyspark连接clickhouse数据库的方式(其它数据库同样适用)
目录 一、背景简记二、pyspark连接clickhouse方式记录三、结语参考学习博文 一、背景简记 实际工作中,大部分所用的数据存储地址都是在数据库中,如我司现在常用的数据库是clickhouse,相关数据的统计分析都在此上操作。如果想用pyspark连接cl…...
当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (css 样式问题)
一、问题 遇到个样式问题,当父级元素设置了flex 布局 ,两个子元素都设置了flex :1, 但是当子元素放不下的时候会溢出父元素怎么解决 (拖拽浏览器 使页面变小) 二、解决方法 .father{min-height: 600px;width: 100%;display: flex…...
软件方法论--课程笔记(整理中)
C1:概览Introduction (1)软件的4个特性 一致性(Conformity):软件必须符合严格的规格和要求,包括与其他组件的接口和环境的连接,避免因为不一致导致无法复用或开发问题。 不可见性…...
从 0 开始实现一个 SpringBoot + Vue 项目
从 0 开始实现一个 SpringBoot Vue 项目 从 0 开始实现一个 SpringBoot Vue 项目 软件和工具创建 SpringBoot 后端项目创建 MySQL 数据库配置文件实现增删改查接口 Model 层mapper 层service 层controller 层测试 实现项目功能接口 代码测试 创建 Vue 前端 安装 Node.js配置…...
怎么修复损坏的U盘?而且不用格式化的方式!
当你插入U盘时,若电脑弹出“需要格式化才能使用”提示,且无法打开或读取其中的数据,说明U盘极有可能已经损坏。除此之外,若电脑在连接U盘后显示以下信息,也可能意味着U盘出现问题,需要修复损坏的U盘&#x…...
使用redis-cli命令实现redis crud操作
项目场景: 线上环境上redis中的key影响数据展示,需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤: 1、确定redis安装的服务器; 2、找到redis的安装目录下 ##找到redis安装目…...
Kibana 控制台中提供语义、向量和混合搜索
作者:来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗?那么,你不需要连接到某个第三方的大型语言模型(LLM)吗?不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…...
设计模式-结构型-装饰器模式
装饰器模式(Decorator Pattern)是结构型设计模式中的一种,它允许你通过将对象封装在一个新的对象中,来动态地添加新的功能,而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”,它是一种…...
CAP:Serverless + AI 让应用开发更简单
AI 已被广泛视为推动行业进步的关键力量,其在各行业的落地步伐加快。企业在构建 AI 应用开发过程中经常会面临 AI 技术门槛过高、试错周期过长、GPU 资源昂贵且弹性能力不足、缺乏配套工具、业务与模型的开发运维过于割裂、缺乏定制化能力等挑战,成为企业…...
Redis超详细入门教程(基础篇)
目录 一、什么是Redis 二、安装Redis 1、Windows系统安装 2、Linux系统安装 三、Redis通用命令 四、Redis基本命令 五、五种数据结构类型 5.1、String类型 5.2、List集合类型 5.3、Set集合类型 5.4、Hash集合类型 5.5、Zset有序集合类型 六、总结 一、什么是Redi…...
对话 TDengine 解决方案中心总经理陈肃:构建技术与市场的桥梁
TD 小T导读 他是大数据领域的杰出专家,拥有超过十项一作发明专利,是中国通信行业标准《大数据 消息中间件技术要求与测试方法》的重要编写者,并凭借数据中间件领域的突出成就荣获 2019 年“CJK OSS Award”。他是腾讯云 TVP 专家和 TGO 鲲鹏会…...
Formality:参考设计/实现设计以及顶层设计
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 Formality存在两个重要的概念:参考设计/实现设计和顶层设计,本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…...
通过内核模块按fd强制tcp的quickack方法
一、背景 tcp的quickack功能是为了让ack迅速回发,快速响应,减少网络通讯时延,属于一个优化项,但是tcp的quickack是有配额限制的,配置是16个quick,也就是短时间内quickack了16次以后,这个配额为…...
Wi-Fi 7、Wi-Fi 6 与 5G、4G 的全方位对比
随着无线通信技术的飞速发展,Wi-Fi 7、Wi-Fi 6,以及5G、4G 已经成为人们生活和工作中不可或缺的网络技术。无论是家庭网络、高速移动通信,还是工业物联网,这些技术都在发挥各自的作用。那么,它们之间有什么区别&#x…...
【例43.3】 转二进制
目录 描述 输入描述 输出描述 用例输入 1 用例输出 1 来源 类型 知识补充站 代码 C Python3 C 描述 请你把一个整数n转化为二进制并从低位到高位输出。 输入描述 一行,仅含一个正整数 n (1≤n≤109)。 输出描述 从低位到高位输出一个二进制数&a…...
qt vs ios开发应用环境搭建和上架商店的记录
qt 下载链接如下 https://download.qt.io/new_archive/qt/5.14/5.14.2/qt-opensource-mac-x64-5.14.2.dmg 安装选项全勾选就行,这里特别说明下qt5.14.2/qml qt5.14.2对qml支持还算成熟,但很多特性还得qt6才行,这里用qt5.14.2主要是考虑到服…...
安全测评主要标准
大家读完觉得有帮助记得关注和点赞!!! 安全测评的主要标准包括多个国际和国内的标准,这些标准为信息系统和产品的安全评估提供了基础和指导。 一、安全测评的主要标准 1.1、国际标准 可信计算机系统评估准则(TC…...
如何学习数学 | 数学家如何思考
学习数学的关键在哪里? 原创 遇见数学 不少人面对数学都会觉得高深莫测,甚至非常枯燥乏味。 只有当你真正走入它的世界,才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门,需要的不仅仅是背公式,或者做一…...
职场沟通与行为
职场沟通与行为 引言 在职场上,你是否曾遇到过困惑的沟通?是否对同事的行为有过疑虑?这不仅是个别现象,而是我们这个时代工作文化中的普遍问题。许多职场的摩擦,来自沟通不畅或是行为不当。那么,如何才能…...
IIO(Industrial I/O)驱动介绍
文章目录 IIO(Industrial I/O)驱动是Linux内核中用于工业I/O设备的子系统,主要用于处理传感器数据采集和转换。以下是其关键点: 功能 数据采集:从传感器读取数据。数据处理:对原始数据进行滤波、校准等操作…...
关于vite+vue3+ts项目中env.d.ts 文件详解
env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...
32单片机综合应用案例——物联网(IoT)环境监测站(四)(内附详细代码讲解!!!)
无论你身处何种困境,都要坚持下去,因为勇气和毅力是成功的基石。不要害怕失败,因为失败并不代表终结,而是为了成长和进步。相信自己的能力,相信自己的潜力,相信自己可以克服一切困难。成功需要付出努力和坚…...
【Flink系列】6. Flink中的时间和窗口
6. Flink中的时间和窗口 在批处理统计中,我们可以等待一批数据都到齐后,统一处理。但是在实时处理统计中,我们是来一条就得处理一条,那么我们怎么统计最近一段时间内的数据呢?引入“窗口”。 所谓的“窗口”ÿ…...
代码随想录算法训练营第三十五天-动态规划-01背包(二维)
动规五部曲 dp数组的含义,注意这是一个二维数组。dp[i][j] 第一维度代表“从0到第i个物品,而且包括选或不选的情况,即这一维度代表物品编号第二维度代表代表背包容量合在一起的意思是当背包容量是j时,从0到i个物品中选择任意物品…...
快速开发:用AI构造AI —— 打造属于个人的Copilot(M-聪明AI)
作品简介: 当今快速发展的AI时代,学会使用AI的同时,也可以融入AI,来打造自己的产品,我给我这个取名M-聪明, 是基于VUE 3 Spring Boot -Redis ChatGML RxJava SSE 的AI 服务平台。然后这款工具旨在为用户…...
Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];
AccessDeniedException 表明 Elasticsearch 容器无法访问或写入数据目录 /usr/share/elasticsearch/data/nodes。这是一个权限问题。 问题原因: 1、宿主机目录权限不足:映射到容器的数据目录 /data/es/data 在宿主机上可能没有足够的权限供容器访问。 …...
用公网服务器实现内网穿透
首先需要一个公网服务器 下载frp 搜索github下载到frp,服务端frps/客户端frpc。。下载的时候要注意自己本地内网机的cpu版本和服务端cpu架构 我的电脑是mac M1PRO版本 下载的是:darwinarm64 比如 服务端一般是Linux(Intel 64位CPU…...
Jmeter如何进行多服务器远程测试
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 JMeter是Apache软件基金会的开源项目,主要来做功能和性能测试,用Java编写。 我们一般都会用JMeter在本地进行测试,但是受到单…...
前端实习第二个月小结
时间飞快,第一次实习已经过去两个多月,作一些简单的总结和分享。 注:文章整体会比较轻松,提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务,技术栈:前端re…...
C# 并发和并行的区别--16
目录 并发和并行 一.并发 定义 特点 代码示例 代码解释 二.并行 定义 特点 在C#中的体现 代码示例 代码解释 三.并发和并行的区别 四 .如何在C#中选择并发还是并行 1.考虑任务类型 2.代码示例 3.注意事项 五.总结 并发和并行 在编程领域,并发和并行是两个密切…...
Python编程与在线医疗平台数据挖掘与数据应用交互性研究
一、引言 1.1 研究背景与意义 在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的…...
HBase实训:纸币冠字号查询任务
一、实验目的 1. 理解分布式数据存储系统HBase的架构和工作原理。 2. 掌握HBase表的设计原则,能够根据实际业务需求设计合理的表结构。 3. 学习使用HBase Java API进行数据的插入、查询和管理。 4. 实践分布式数据存储系统在大数据环境下的应用,…...
Java 读取 Windows 设备的唯一性标识及定位
在 Windows 系统中,获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法,如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。 1. 使用 JNA 库读取 DEVPKEY_Device_ContainerId 在 Windows 系统中&…...
UE控件学习
ListView: item设置:使能在list设置为Entry类 Grid Panel: 常用作背包,每个格子大小可不相同 WidgetSwitcher: 用于切换页签 Wrap_Box: 自动横向排版子节点,超过一定范围则自动换行…...
1.Spring AI 从入门到实践
Spring AI 从入门到实践 1.什么是Spring AI 2.使用Spring Boot&Spring AI快速构建AI应用程序 3.ChatClient&Chat Model简化与AI模型的交互 4.Spring AI Prompt:与大模型进行有效沟通 5.结构化输出大模型响应 6.实战:AI聊天机器人 Ben技术站关注Java技术&#x…...
2025年01月蓝桥杯Scratch1月stema选拔赛真题—美丽的图形
美丽的图形 编程实现美丽的图形具体要求: 1)点击绿旗,角色在舞台中心,如图所示; 2)1秒后,绘制一个边长为 140的红色大正方形,线条粗细为 3,正方形的中心为舞台中心,如图所示; 完整题目可点击下…...
FLASK创建下载
html用a标签 <!-- Button to download the image --> <a href"{{ url_for(download_file, filenameimage.png) }}"><button>Download Image</button> </a> 后端:url_for双大括号即是用来插入变量到模板中的语法。也就是绑…...
LDD3学习7--硬件接口I/O端口(以short为例)
1 理论 1.1 基本概念 目前对外设的操作,都是通过寄存器。寄存器的概念,其实就是接口,访问硬件接口,有I/O端口通信和内存映射I/O (Memory-Mapped I/O),I/O端口通信是比较老的那种,都是老的串口并口设备&am…...
MySQL(高级特性篇) 06 章——索引的数据结构
一、为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一样的道理,进行数据查找时,首先查看查询条件…...
【FlutterDart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)
动图更精彩 MVVM(Model-View-ViewModel) 特点 Model:负责数据管理和业务逻辑。 View:负责显示数据,通常是一个UI组件。 ViewModel:负责处理用户交互,更新Model,并将数据转换为View可…...
光谱相机的光谱分辨率可以达到多少?
多光谱相机 多光谱相机的光谱分辨率相对较低,波段数一般在 10 到 20 个左右,光谱分辨率通常在几十纳米到几百纳米之间,如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…...
.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)
一、UI效果 二、新建用户控件:VideoViewControl.axaml 需引用:VideoLAN.LibVLC.Windows包 Linux平台需安装:VLC 和 LibVLC (sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev) .axaml 代码 注…...
【论文阅读】基于空间相关性与Stacking集成学习的风电功率预测方法
文章目录 摘要0. 引言1. 空间相关性分析2. 风电功率预测模型2.1 Stacking 集成策略2.2 基学习器2.2.1 基于机器学习算法的基学习器2.2.2 基于神经网络的基学习器2.2.3 基于粒子群优化算法的超参数优化 2.3 元学习器2.4 基于空间相关性与Stacking集成学习的风电功率预测方法 3 算…...