'cache'에 해당되는 글 6건

  1. 2019.10.23 [Elasticsearch] Cache 에 대해 알아 봅시다.
  2. 2017.11.02 [Gradle] Dynamic version cache 설정하기
  3. 2016.03.22 [Redis] Master/Slave, Sentinel 구성 부터 Jedis 예제까지.
  4. 2015.05.26 [Elasticsearch] Circuit Breaker
  5. 2013.09.02 [Elasticsearch] IndexCacheModule...
  6. 2012.11.23 memcached 설치 따라하기.

[Elasticsearch] Cache 에 대해 알아 봅시다.

Elastic/Elasticsearch 2019. 10. 23. 09:58

저는 기본적으로 API 단에서 Elasticsearch 로 질의한 결과를 Cache 하도록 구현해서 사용하고 있습니다.

하지만 Elasticsearch 에서도 기본적으로 두 가지의 Cache 기능을 제공 하고 있으니 잘 활용 하시면 좋을 것 같아 기록해 봅니다.

 

한 줄로 정리 하면)

검색 결과 리스팅은 Query Cache에, 검색 결과에 대한 집계 는 Request Cache 에 저장 된다고 이해 하시면 됩니다.

 

1. Node Query Cache

공식문서)

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-cache.html

- 이 기능은 Query 에 따른 결과를 Cache하게 되며, LRU 정책으로 동작 합니다.

- 이 기능은 Node 레벨로 동작 합니다.

- 이 기능은 Filter Context 를 사용 했을 경우에만 동작 합니다.

 

- 아래 설정은 Cluster 내 모든 Data Node 에 설정을 반드시 해야 합니다.

indices.queries.cache.size

 

- 아래 설정은 Index 별로 설정을 해야 합니다.
index.queries.cache.enabled

 

2. Shard Request Cache

공식문서)

https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-request-cache.html

- 이 기능은 개별 Local Shard 의 결과를 Cache 합니다.

- 이 기능은 size=0 인 Request 의 결과만 Cache 합니다.

- 즉, Aggregations 와 Suggestions 결과를 Cache 하게 되며, hits 결과는 Cache 하지 않지만 hits.total 은 Cache 합니다.

- Date Range 또는 Histogram 질의 시 now 를 사용하게 되면 Cache 하지 않습니다.

 

- 이 기능은 Index 레벨로 설정을 합니다.

PUT /my_index
{
  "settings": {
    "index.requests.cache.enable": true
  }
}

 

- 아래 설정은 Node 레벨로 설정을 하는 것입니다.

indices.requests.cache.size

 

- 아래 설정은 Cache TTL 설정을 하는 것입니다. 

indices.requests.cache.expire

 

Code Sniff)

// IndicesRequestCache.java
    /**
     * A setting to enable or disable request caching on an index level. Its dynamic by default
     * since we are checking on the cluster state IndexMetaData always.
     */
    public static final Setting<Boolean> INDEX_CACHE_REQUEST_ENABLED_SETTING =
        Setting.boolSetting("index.requests.cache.enable", true, Property.Dynamic, Property.IndexScope);
    public static final Setting<ByteSizeValue> INDICES_CACHE_QUERY_SIZE =
        Setting.memorySizeSetting("indices.requests.cache.size", "1%", Property.NodeScope);
    public static final Setting<TimeValue> INDICES_CACHE_QUERY_EXPIRE =
        Setting.positiveTimeSetting("indices.requests.cache.expire", new TimeValue(0), Property.NodeScope);
        
// TimeValue.java        
   public static TimeValue parseTimeValue(String sValue, TimeValue defaultValue, String settingName) {
        settingName = Objects.requireNonNull(settingName);
        if (sValue == null) {
            return defaultValue;
        }
        final String normalized = sValue.toLowerCase(Locale.ROOT).trim();
        if (normalized.endsWith("nanos")) {
            return new TimeValue(parse(sValue, normalized, "nanos"), TimeUnit.NANOSECONDS);
        } else if (normalized.endsWith("micros")) {
            return new TimeValue(parse(sValue, normalized, "micros"), TimeUnit.MICROSECONDS);
        } else if (normalized.endsWith("ms")) {
            return new TimeValue(parse(sValue, normalized, "ms"), TimeUnit.MILLISECONDS);
        } else if (normalized.endsWith("s")) {
            return new TimeValue(parse(sValue, normalized, "s"), TimeUnit.SECONDS);
        } else if (sValue.endsWith("m")) {
            // parsing minutes should be case-sensitive as 'M' means "months", not "minutes"; this is the only special case.
            return new TimeValue(parse(sValue, normalized, "m"), TimeUnit.MINUTES);
        } else if (normalized.endsWith("h")) {
            return new TimeValue(parse(sValue, normalized, "h"), TimeUnit.HOURS);
        } else if (normalized.endsWith("d")) {
            return new TimeValue(parse(sValue, normalized, "d"), TimeUnit.DAYS);
        } else if (normalized.matches("-0*1")) {
            return TimeValue.MINUS_ONE;
        } else if (normalized.matches("0+")) {
            return TimeValue.ZERO;
        } else {
            // Missing units:
            throw new IllegalArgumentException("failed to parse setting [" + settingName + "] with value [" + sValue +
                    "] as a time value: unit is missing or unrecognized");
        }
    }        

 

각 설정 값들에 대한 최적화는

- 장비 스펙

- 질의 특성

- 문서 크기

등에 맞춰서 구성을 하셔야 합니다.

잘 모를 경우는 그냥 Elasticsearch 의 default 값을 사용하시면서 최적값을 찾으셔야 합니다.

 

Monitoring Cache Usage)

공식문서)

https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-stats.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-stats.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-stats.html

GET /_stats/request_cache?human
GET /_nodes/stats/indices/request_cache?human

 

함께 알아 두면 좋은것)

https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/doc-values.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-store.html

 

:

[Gradle] Dynamic version cache 설정하기

ITWeb/개발일반 2017. 11. 2. 21:45

지난 글과 함께 보시면 좋습니다.


[지난 글]

[Gradle] Dependency filename 구하기

[Gradle] Use latest version on dependency jar.


[참고문서]

https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html


[설정]

configurations {

dependencyFn

}


configurations.dependencyFn {

resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'

}


dependencies {

dependencyFn group: "org.apaceh.lucene.analysis.arirang", name: "arirang-dictionary", \

version: "+", changing: true

}


:

[Redis] Master/Slave, Sentinel 구성 부터 Jedis 예제까지.

ITWeb/개발일반 2016. 3. 22. 16:17

필요해서 구성해본 내용을 정리 합니다.

복습 차원에서 기록 하는 것이라 별 도움이 안될수 있습니다.


Redis 공식 사이트)


Redis 다운로드)


Redis 설치 on OSX)

# 다운로드 받은 후 tar 압축 해제 후 make 했습니다.

$ make

    LINK redis-check-dump

    CC redis-check-aof.o

    LINK redis-check-aof


Hint: It's a good idea to run 'make test' ;)

# 필요 하신 경우 make install 하시면 됩니다.


Redis Configure 참조)

- maxmemory 설정은 32bits 운영체제에서 최대 3GB 이며, 64bits 에서는 리소스 만큼 가능 하다고 합니다.

- expire 설정을 해주는 것 보다 그냥 LRU 설정을 사용하라고 합니다. (근데 이건 서비스 특성과 성능 테스트 후 결정 하는게 좋아 보입니다.)

- redis LRU 알고리즘이 완벽하지 않다(Redis LRU algorithm is not an exact implementation.)는 공식 문서의 설명이 있습니다. 그래서 maxmemory-samples 라는 설정을 하는 것 같습니다.

(http://redis.io/topics/lru-cache)

- 단순 휘발성 데이터에 대한 cache 용도 일때는 rdb, append 모드를 disable 하는게 좋습니다.

- sentinel 설정은 master, slave 구성 시 failover 지원을 하기 위함 입니다. (client 에서는 JedisSentinelPool 을 사용하세요.)

- master election 시 민주적으로 하기 위해 quorum 구성을 합니다.


Redis Master 설정)

daemonize yes

pidfile /redis-server/master/pidfile/redis.pid

port 6379

tcp-backlog 511

bind 127.0.0.1

loglevel debug

logfile /redis-server/master/log/redis.log

maxmemory 64MB

maxmemory-policy allkeys-lru

maxmemory-samples 5

appendonly no

save ""

requirepass redispassword


Redis Slave 설정)

daemonize yes

pidfile /redis-server/slave/pidfile/redis.pid

port 6479

tcp-backlog 511

bind 127.0.0.1

loglevel debug

logfile /redis-server/slave/log/redis.log

maxmemory 64MB

maxmemory-policy allkeys-lru

maxmemory-samples 5

appendonly no

save ""

slaveof 127.0.0.1 6379

masterauth redispassword


Redis Sentinel Quorum 설정)

Sentinel 1)

port 26379

dir "/tmp"

sentinel monitor redis-master 127.0.0.1 6379 2

sentinel auth-pass redis-master redispassword

sentinel down-after-milliseconds redis-master 30000

sentinel parallel-syncs redis-master 1

daemonize yes

pidfile "/redis-server/sentinel1/pidfile/sentinel.pid"

logfile "/redis-server/sentinel1/log/sentinel.log"


Sentinel 2)

port 26479

dir "/tmp"

sentinel monitor redis-master 127.0.0.1 6379 2

sentinel auth-pass redis-master redispassword

sentinel down-after-milliseconds redis-master 30000

sentinel parallel-syncs redis-master 1

daemonize yes

pidfile "/redis-server/sentinel2/pidfile/sentinel.pid"

logfile "/redis-server/sentinel2/log/sentinel.log"


Sentinel 3)

port 26579

dir "/tmp"

sentinel monitor redis-master 127.0.0.1 6379 2

sentinel auth-pass redis-master redispassword

sentinel down-after-milliseconds redis-master 30000

sentinel parallel-syncs redis-master 1

daemonize yes

pidfile "/redis-server/sentinel3/pidfile/sentinel.pid"

logfile "/redis-server/sentinel3/log/sentinel.log"


Redis Master/Slave/Sentinel 실행)

$ src/redis-server /redis-server/master/conf/redis.conf

$ src/redis-server /redis-server/slave/conf/redis.conf

$ src/redis-server /redis-server/sentinel1/conf/sentinel.conf --sentinel

$ src/redis-server /redis-server/sentinel2/conf/sentinel.conf --sentinel

$ src/redis-server /redis-server/sentinel3/conf/sentinel.conf --sentinel


Jedis 공식 사이트)


Jedis 샘플 코드)

- JedisSentinelPoolTest 참조



:

[Elasticsearch] Circuit Breaker

Elastic/Elasticsearch 2015. 5. 26. 11:33

참고 문서)

https://www.elastic.co/guide/en/elasticsearch/guide/current/_limiting_memory_usage.html#circuit-breaker

https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-fielddata.html#fielddata-circuit-breaker

https://www.elastic.co/guide/en/elasticsearch/guide/current/_monitoring_individual_nodes.html#_circuit_breaker

https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html#_field_data_circuit_breaker

https://www.elastic.co/guide/en/elasticsearch/resiliency/current/index.html#_circuit_breaker_fielddata_status_done_v1_0_0


결국 하나의 문서만 보셔도 됩니다.

https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-fielddata.html


[Circuit Breaker 요약]

- fielddata cache 와 연관된 기능으로 OOM에 대한 대응 방법으로 제공하고 있습니다.

- circuit breaker limit size는 cache size 보다 커야 합니다.

- circuit breaker는 query에 필요로 하는 memory 크기를 예측/평가 하여 사전에 OOM 문제를 경험하지 않도록 해줍니다.

    즉, 요청한 Query를 중시 시킵니다.


[Geek Igor]

http://igor.kupczynski.info/2015/04/06/fielddata.html

:

[Elasticsearch] IndexCacheModule...

Elastic/Elasticsearch 2013. 9. 2. 17:40

index cache module 뭐가 있는지 한번 볼까요?


        new FilterCacheModule(settings).configure(binder());

        new IdCacheModule(settings).configure(binder());

        new QueryParserCacheModule(settings).configure(binder());

        new DocSetCacheModule(settings).configure(binder());


검색 질의와 결과 셋에 대한 cache 가 위에서 보면

        new QueryParserCacheModule(settings).configure(binder());

        new DocSetCacheModule(settings).configure(binder());

이 두 놈이 비슷해 보입니다.


근데 소스 들어가서 보면 정말 원하는 내용은 아니라는 걸 알 수 있습니다.

QueryParserCacheModule 은 요청한 질의에 대한 Query 를 매번 만들지 않고 cache 에서 가져 올 수 있는 기능이라 뭐 괜찮아 보이구요.

DocSetCacheModule 은 docId 기반의 cache 라서 ㅎㅎ document 단위로 cache 정보를 읽어 오는 기능 입니다.

즉, 검색 질의에 대한 결과셋을 cache 하고 싶으신 경우는 그냥 memcached 나 redis 같은걸 이용해서 cache 하시면 되겠습니다.

:

memcached 설치 따라하기.

ITWeb/개발일반 2012. 11. 23. 12:00

[Memcached 설치]
    ※ Reference
        http://code.google.com/p/memcached/wiki/NewInstallFromSource
        http://yupmin.net/install-memcached
    ※ 설치
        (root권한)
            sudo yum install libevent libevent-devel
        (user권한)
            cd dist
            wget http://memcached.org/latest
            tar -zxvf memcached-1.x.x.tar.gz
            cd memcached-1.x.x
            ./configure --prefix=/usr/local/memcached --with-libevent=/usr/lib/
            make && make test
        (root권한)
            sudo make install
    ※ 설정
        cd /etc
        sudo vi memcached.conf
            -m 16
            -p 11311
            -u nobody
            -l 127.0.0.1
    ※ init script 생성
        (user권한)
        mkdir -p /home/USER/dist/memcached_script
        cd /home/USER/dist/memcached_script
            wget http://yupmin.net/wp-content/uploads/2010/08/memcached_script.tar.gz
            tar xvfz memcached_script.tar.gz
            chmod 755 /usr/local/bin/start-memcached
            chmod 755 /etc/init.d/memcached
        (root 권한)
            cd /usr/local/bin
            sudo ln -s /usr/local/memcached/bin/memcached memcached
            cd /home/USER/dist/memcached_script
            sudo mv start-memcached /usr/local/bin/start-memcached
            sudo mv memcached /etc/init.d/memcached
    ※ 실행
        sudo /usr/local/bin/start-memcached or
        /usr/local/memcached/bin/memcached -d -r -m 64 -l 서버IP(10.101.254.223) -p 11211
        - 실행 권한 root or user
        - 단일 서버에 Multi instance 실행
            /usr/local/memcached/bin/memcached -d -r -m 64 -l 서버IP(10.101.254.223) -p 11211
            /usr/local/memcached/bin/memcached -d -r -m 64 -l 서버IP(10.101.254.223) -p 11311
            /usr/local/memcached/bin/memcached -d -r -m 64 -l 서버IP(10.101.254.223) -p 11411
    ※ 실행 스크립트
        #!/usr/bin/perl -w
 
        # start-memcached
        # 2003/2004 - Jay Bonci <jaybonci@debian.org>
        # This script handles the parsing of the /etc/memcached.conf file
        # and was originally created for the Debian distribution.
        # Anyone may use this little script under the same terms as
        # memcached itself.
 
        use strict;
 
        if ($> != 0 and $< != 0) {
                print STDERR "Only root wants to run start-memcached.\n";
                exit;
        }
 
        my $etcfile = shift || "/etc/memcached.conf";
        my $params = [];
        my $etchandle;
 
        # This script assumes that memcached is located at /usr/bin/memcached, and
        # that the pidfile is writable at /var/run/memcached.pid
 
        my $memcached = "/usr/local/bin/memcached";
        my $pidfile = "/var/run/memcached.pid";
 
        # If we don't get a valid logfile parameter in the /etc/memcached.conf file,
        # we'll just throw away all of our in-daemon output. We need to re-tie it so
        # that non-bash shells will not hang on logout. Thanks to Michael Renner for
        # the tip
        my $fd_reopened = "/dev/null";
 
        sub handle_logfile {
                my ($logfile) = @_;
                $fd_reopened = $logfile;
        }
 
        sub reopen_logfile {
                my ($logfile) = @_;
                open *STDERR, ">>$logfile";
                open *STDOUT, ">>$logfile";
                open *STDIN, ">>/dev/null";
                $fd_reopened = $logfile;
        }
 
        # This is set up in place here to support other non -[a-z] directives
 
        my $conf_directives = {
                "logfile" => \&handle_logfile
        };
 
        if (open $etchandle, $etcfile) {
                foreach my $line (<$etchandle>) {
                        $line =~ s/\#.*//go;
                        $line = join ' ', split ' ', $line;
                        next unless $line;
                        next if $line =~ /^\-[dh]/o;
 
                        if ($line =~ /^[^\-]/o) {
                                my ($directive, $arg) = $line =~ /^(.*?)\s+(.*)/;
                                $conf_directives->{$directive}->($arg);
                                next;
                        }
                        push @$params, $line;
                }
        }
 
        unshift @$params, "-u root" unless (grep $_ eq '-u', @$params);
        $params = join " ", @$params;
 
        if (-e $pidfile) {
                open PIDHANDLE, "$pidfile";
                my $localpid = <PIDHANDLE>;
                close PIDHANDLE;
 
                chomp $localpid;
                if (-d "/proc/$localpid") {
                        print STDERR "memcached is already running.\n";
                        exit;
                } else {
                        `rm -f $localpid`;
                }
        }
 
        my $pid = fork();
 
        if ($pid == 0) {
                reopen_logfile($fd_reopened);
                exec "$memcached $params";
                exit(0);
        } elsif (open PIDHANDLE,">$pidfile") {
                print PIDHANDLE $pid;
                close PIDHANDLE;
        } else {
                print STDERR "Can't write pidfile to $pidfile.\n";
        }

: