<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[GeekerJava的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/GeekerJava</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; GeekerJava]]></copyright><item><title><![CDATA[记一次ES写入优化]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/143866029</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/143866029</guid><author>GeekerJava</author><pubDate>Sun, 24 Nov 2024 19:26:41 +0800</pubDate><description><![CDATA[在translog文件被 fsync 到磁盘前，如果发生重启则被写入的文件就会丢失，因此如果你的系统对于丢失 sync_interval 时间段的数据也无所谓，那将translog的刷盘操作修改为异步对写入性能提高很有帮助，虽然sync_interval设置的很小，但是如果是批量写入数据系统宕机情况下丢失数据量也是很大的，需要慎重依据自己的场景使用，避免数据丢失。我们系统通过ES存储告警数据，性能测试过程中测试反馈有一台单机环境ES数据有延迟，随着运行时间增长，延迟越来越明显，影响了正常功能需要解决。]]></description><category></category></item><item><title><![CDATA[lucene数据写入-03数据刷盘]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/142911382</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/142911382</guid><author>GeekerJava</author><pubDate>Sat, 16 Nov 2024 18:17:32 +0800</pubDate><description><![CDATA[回到org.apache.lucene.index.FreqProxTermsWriter#flush方法，写入成功调用close方法，最终调用的还是org.apache.lucene.codecs.blocktree.BlockTreeTermsWriter#close方法。继续跟踪执行org.apache.lucene.index.DocumentsWriter#doFlush方法，最终调用org.apache.lucene.index.DefaultIndexingChain#flush方法。]]></description><category></category></item><item><title><![CDATA[lucene数据写入-02倒排数据缓存组织]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/142910742</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/142910742</guid><author>GeekerJava</author><pubDate>Sat, 26 Oct 2024 15:03:38 +0800</pubDate><description><![CDATA[term的docID+freqs信息，文档号为2，出现了3次，存储为[docid<<1+0, freq]，docid取差值为1，因而存储为[2, 3]，但是存储docID和freqs的空间已经满了，一样需要进行扩容，这里新分配的快层级为2，空间长度为14，结束符号为17，重新的尾部分配空间，将原来分隔符前的三个字节copy到新位置，原来的分隔符和空出来的空间组成一个int保存指针信息。然后写入文档1的第一个common的位置信息，0<<1 + 0 = 0，写入到下标为21的位置。]]></description><category></category></item><item><title><![CDATA[lucene数据写入-01写入流程]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/142909529</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/142909529</guid><author>GeekerJava</author><pubDate>Sat, 19 Oct 2024 16:32:44 +0800</pubDate><description><![CDATA[文件结构




名称
扩展名
数据结构
说明




Segments File
segments.gen segments_N
SegmentInfos
保存当前索引中所有的段信息的集合，索引中所有可用的段信息都存储在段文件segment_N


Lock File
write.lock

写锁，用于阻止多个IndexWriter写同一个索引文件


Segment Info
.si
Lucene70SegmentInfoFormat
segment的元数据信息，指明这个segment都包含哪些文件

]]></description><category></category></item><item><title><![CDATA[记一次knife4j文档请求异常 SyntaxError: Unexpected token ‘＜‘, ... is not valid JSON]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/141984089</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/141984089</guid><author>GeekerJava</author><pubDate>Sat, 07 Sep 2024 11:21:54 +0800</pubDate><description><![CDATA[其实上面描述的问题只是一个很小很小的疏忽导致在线接口文档无法访问，还好没有影响到生产环境其他功能。本篇文章也只是记录一下生产过程中的一个小问题的定位和处理过程，但是每个人的情况都不尽相同，希望对您在遇到相同问题时候有一点帮助。回头再看一下报错信息，你会发现其实已经给出了具体提示，只是一开始我们没有理解而已。以此记录一下，希望自己下次可以关注细节。]]></description><category></category></item><item><title><![CDATA[lucene学习-FST源码分析]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/140296025</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/140296025</guid><author>GeekerJava</author><pubDate>Sat, 10 Aug 2024 14:11:54 +0800</pubDate><description><![CDATA[第三步插入do/17,do和deep有公共字符d可以将字符p和字符e写入FST，这里字符p的flags和上面字符t的flags相同为15，表明arc对应字符是term最后一个字符，arc是当前节点最后一条边，arc连接的两个节点是临近节点不需要记录target，arc的目标节点是一个终止节点，字符e的flags和上面的字符a的flags相同，表明arc是当前节点最后一条边而且arc连接的两个节点是临近节点。将父节点指向冻结后的节点，冻结后的节点就是compileNode，该方法就是将节点转变为冻结节点。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-08Serch查询流程]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139865787</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139865787</guid><author>GeekerJava</author><pubDate>Sat, 03 Aug 2024 15:11:46 +0800</pubDate><description><![CDATA[这里可以看到首先会执行lucene的查询，然后对查询结果进行打分、执行聚合逻辑，然后生成SearchPhaseResult返回。和Get查询一样，请求会经过转发dispatchRequest，查询路由对应的handler处理类，然后执行处理。数据节点查询数据后返回协调节点，我们继续回到executePhaseOnShard方法执行回调。search操作会发送请求到索引下的所有分片，相同分片只会发送到主分片或副本分片。这里收集本集群和跨集群及其他集群需要查询的索引，这里我们主要是分析本集群搜索。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-07GET查询流程]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139703311</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139703311</guid><author>GeekerJava</author><pubDate>Sat, 27 Jul 2024 14:52:27 +0800</pubDate><description><![CDATA[而TransportGetAction继承了TransportSingleShardAction最终调用它的doExecute方法。ES的读取分为Get和search两种，get是根据id从索引中获取内容，而search是根据关键词从倒排索引中获取内容。就是将请求转发到其他节点执行，处理逻辑和上面的逻辑一致，其他节点执行后会把数据返回，然后节点把数据返回给用户请求。获取线程池然后执行，最终都会调用processMessageReceived方法。get请求的处理在actionModule中进行注册。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-06索引恢复]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139702897</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139702897</guid><author>GeekerJava</author><pubDate>Sat, 20 Jul 2024 23:27:11 +0800</pubDate><description><![CDATA[索引恢复
allocation阶段最后会向集群发布一个新的集群状态，状态发布后会进入IndicesClusterStateService的applyClusterState应用集群状态
@Override
public synchronized void applyClusterState(final ClusterChangedEvent event) {
    if (!lifecycle.started()) {
        return;
    }

    final ClusterSta]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-05分片分配]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139702707</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139702707</guid><author>GeekerJava</author><pubDate>Sat, 13 Jul 2024 14:05:10 +0800</pubDate><description><![CDATA[副本分片分配也需要获取一次shard信息，但是之前主分片分配已经获取了一次数据，副本分片分配可以直接使用上次执行获取分片的结果，如果没有node可以分配则查看是否延迟分配，然后执行initialize方法。主分分配器primaryShardAllocator和replicaShardAllocator都继承了BaseGatewayShardAllocator方法，在执行allocateUnassigned时主分片分配和副本分片分配会执行相同的方法，只是会执行不同的决策。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-04集群状态发布]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139866149</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139866149</guid><author>GeekerJava</author><pubDate>Sat, 06 Jul 2024 14:32:45 +0800</pubDate><description><![CDATA[es使用二阶段提交来实现状态发布，第一步是push及先将状态数据发送到node节点，但不应用，如果得到超过半数的节点的返回确认，则执行第二步commit及发送提交请求，二阶段提交不能保证节点收到commit请求后可以正确应用，也就是它只能保证发了commit请求，但是无法保证单个节点上的状态应用是成功还是失败的。回到MasterService的runTasks方法中新的集群状态已经生成并返回，然后判断集群状态和之前的集群状态是否相同，如果发生变化则将进入集群状态发布阶段，将最新的集群状态广播到所有节点。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-03选举集群状态]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139702581</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139702581</guid><author>GeekerJava</author><pubDate>Sat, 29 Jun 2024 12:05:36 +0800</pubDate><description><![CDATA[首先判断只有主节点可以执行状态选举，然后判断是否已经在执行了状态恢复任务了，如果是则直接返回；遍历所有节点选择返回的索引元数据版本最高的节点作为索引级元数据，然后将索引级元数据添加到metadataBuilder中。从磁盘读取构建索引级元数据和集群级元数据，用于构建集群状态对象ClusterState。开始通过版本号选择集群层元数据,比较版本号，选择版本号最大的集群状态。构造集群状态，删除索引信息，下面会选择索引级元数据。我们继续回到每个节点发送请求的返回处理。构造恢复后的集群级元数据和索引级元数据。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-02选举主节点]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139702369</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139702369</guid><author>GeekerJava</author><pubDate>Sun, 23 Jun 2024 09:45:10 +0800</pubDate><description><![CDATA[NodesFaultDetection运行在master节点，master也是定时发送心跳ping请求给非master节点，如果发送失败则先重试,重试达到一定次数调用notifyNodeFailure，如果返回连接错误则调用handleTransportDisconnect(node)如果选择的master节点是本节点加入的节点则设置选举结束。首先会比较两个候选节点的集群状态版本信息，如果版本信息比较新则排在前面，如果版本号相同则需要比较两个节点的节点id，然后选择排在最前面的一个节点为master。]]></description><category></category></item><item><title><![CDATA[elasticsearch源码分析-01服务启动]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/139701975</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/139701975</guid><author>GeekerJava</author><pubDate>Sat, 15 Jun 2024 14:36:17 +0800</pubDate><description><![CDATA[1.服务启动
服务启动入口类为Elasticsearch
/**
* Main entry point for starting elasticsearch
*/
public static void main(final String[] args) throws Exception {
    LogConfigurator.registerErrorListener();
    final Elasticsearch elasticsearch = new Elasticsearch();
    ]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-09流量整形控制器]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132513613</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132513613</guid><author>GeekerJava</author><pubDate>Sat, 26 Aug 2023 17:35:51 +0800</pubDate><description><![CDATA[这里首先计算两个请求之间的间隔时间costTime，通过costTime计算下次请求可以通过的时间expectedTime，如果expectedTime <= currentTime说明当前时间已经到达expectedTime ，则请求可以正常通过，否则说明当前时间请求需要等待，计算等待时间waitTime，如果waitTime比设置的最大等待时间大则直接不允许通过，如果没有达到最大排队时间则等待waitTime后通过。关注控制每秒传入请求的计数，类似于令牌桶算法。]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-08流量数据统计]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132382517</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132382517</guid><author>GeekerJava</author><pubDate>Sat, 26 Aug 2023 17:01:25 +0800</pubDate><description><![CDATA[这里就是将时间按照窗口数量化分成相同大小的环形桶，当前请求过来时，根据请求的时间查看落在那个时间窗口内，这里我们以成功通过后的数据统计为入口。我们可以看到统计节点主要是保存三种实时统计指标，每秒统计信息、每分钟的统计信息、并发线程数。ArrayMetric底层又是通过LeapArray来完成数据的统计，其中几个重要的属性。这里通过当前时间获取有效结果的时间窗集合，然后遍历所有时间窗集合然后或的成功的请求总数。这里array可以理解就是一个环形的桶，首先计算当前时间落在那个桶中，及计算索引值。]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-07GatewayFlowSlot网关限流]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132381332</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132381332</guid><author>GeekerJava</author><pubDate>Sat, 19 Aug 2023 17:55:02 +0800</pubDate><description><![CDATA[如果没有设置pattern则直接返回取值结果，如果设置pattern则可能是针对某类参数生效，支持3种模式精确匹配、子串匹配和正则匹配，如果匹配成功则返回参数值否则返回默认值$NM，它会匹配热点参数规则的参数例外项，但是例外项的阈值是100万，等同于直接放行。解析设置的参数放入参数数组，如果有没有参数的规则，则将参数数组的最后一位设置成默认参数$D，为了进行资源的所有无参数例外项的热点规则流控校验。这里设置了两个分组，并设置了对应匹配分组的规则。将无参网关流控规则，转换为热点参数规则。]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-06热点参数限流]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132381290</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132381290</guid><author>GeekerJava</author><pubDate>Sat, 19 Aug 2023 16:27:21 +0800</pubDate><description><![CDATA[这里是一个简单的令牌桶，每次执行逻辑查看是否需要限流时，计算上次添加令牌的时间距离当前时间差，如果时间大于一个周期，则重置令牌桶令牌数量，然后立即使用acquireCount个令牌，如果已经存在令牌桶则计算上次添加时间到当前时间差可以放入的令牌数和剩余令牌数之和是否能够支持acquireCount个令牌，如果达不到则需要限流。热点参数限流会统计传入参数中的热点参数，并根据配置的限流阈值与模式，对包含热点参数的资源调用进行限流。这里获取热点数据流控规则，通过配置规则中的设置的索引获取对应需要限流的热点参数。]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-05核心链路调用]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132380964</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132380964</guid><author>GeekerJava</author><pubDate>Sat, 19 Aug 2023 16:24:12 +0800</pubDate><description><![CDATA[这里可能是为了高并发考虑，使用copyOnWrite操作，clusterNodeMap是使用static volatile修饰的，如果直接put其他线程无法感知到map内容的变化，通过copyOnWrite操作重新赋值，会使clusterNodeMap地址发生改变，其他线程会感知到变化，保证数据一致性，同时起到读写分离的效果，提高读写并发，同时创建的临时map进行了初始容量的赋值，不会因为扩容导致性能波动。资源调用会创建一个CtEntry，然后开始执行上面创建的执行链。]]></description><category></category></item><item><title><![CDATA[sentinel源码分析-04核心概念介绍]]></title><link>https://blog.youkuaiyun.com/GeekerJava/article/details/132251651</link><guid>https://blog.youkuaiyun.com/GeekerJava/article/details/132251651</guid><author>GeekerJava</author><pubDate>Sat, 12 Aug 2023 18:22:19 +0800</pubDate><description><![CDATA[sentinel中的资源类，可以通过注解SentinelResource指定资源，具体的资源类是ResourceWrapper，包装了name和entryType属性，用户可以为需要保护的对象创建一个资源类，然后再配置相对于的规则就可以实现对资源的保护，同时资源和规则是解耦的，而且规则可以在运行时进行修改。]]></description><category></category></item></channel></rss>