Выселение Hazelcast не работает с политикой FREE_HEAP_PERCENTAGE - PullRequest
0 голосов
/ 16 марта 2020

Я использую версию hazelcast 3.12.2. Ниже приведен фрагмент кода, который я использовал:

package com;

import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MaxSizeConfig;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.map.listener.EntryEvictedListener;

public class HazelcastMaxSizeTest {

    private static final String GROUP_NAME = "TEST";

    private static final String MAP_NAME = "test";

    private static final String MAP_NAME1 = "test1";

    private static final String MAP_NAME2 = "test2";

    private static MaxSizeConfig POLICY_THAT_DOES_NOT_WORK = new MaxSizeConfig(
            20,
            MaxSizeConfig.MaxSizePolicy.FREE_HEAP_PERCENTAGE);

    public static void main(String[] args) throws Exception {

        HazelcastInstance instance = startHazelcast("hazelcast1", POLICY_THAT_DOES_NOT_WORK);
        System.out.println("started " + instance.getName());

        IMap<Long, byte[]> map = createMap(instance, MAP_NAME, 10000000);
        System.out.println("map size: " + map.size());

        IMap<Long, byte[]> map1 = createMap(instance, MAP_NAME1, 15000000);
        System.out.println("map1 size: " + map1.size());

        IMap<Long, byte[]> map2 = createMap(instance, MAP_NAME2, 20000000);
        System.out.println("map2 size: " + map2.size());

        instance.shutdown();
    }

    private static IMap<Long, byte[]> createMap(HazelcastInstance instance, String mapname, int bytes) {

        IMap<Long, byte[]> map = instance.getMap(mapname);

        map.addEntryListener(new EntryEvictedListener<Long, byte[]>() {

            @Override
            public void entryEvicted(EntryEvent<Long, byte[]> event) {
                System.out.println("evicted " + event.getName() + ": " + event.getKey());
            }

        }, false);

        for (long i = 1; i <= 10; i++) {
            map.set(i, new byte[bytes]);
        }

        return map;
    }

    private static HazelcastInstance startHazelcast(String instanceName, MaxSizeConfig maxSizeConfig) {

        MapConfig mapConfig = new MapConfig(MAP_NAME);
        mapConfig.setMaxSizeConfig(maxSizeConfig);
        mapConfig.setStatisticsEnabled(false);
        mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
        mapConfig.setMinEvictionCheckMillis(0L);
        mapConfig.setBackupCount(1);

        MapConfig mapConfig1 = new MapConfig(MAP_NAME1);
        mapConfig.setMaxSizeConfig(maxSizeConfig);
        mapConfig.setStatisticsEnabled(false);
        mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
        mapConfig.setMinEvictionCheckMillis(0L);
        mapConfig.setBackupCount(1);

        MapConfig mapConfig2 = new MapConfig(MAP_NAME2);
        mapConfig.setMaxSizeConfig(maxSizeConfig);
        mapConfig.setStatisticsEnabled(false);
        mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
        mapConfig.setMinEvictionCheckMillis(0L);
        mapConfig.setBackupCount(1);

        Config config = new Config(instanceName);
        config.addMapConfig(mapConfig);
        config.addMapConfig(mapConfig1);
        config.addMapConfig(mapConfig2);
        config.getGroupConfig().setName(GROUP_NAME).setPassword(GROUP_NAME);
        return Hazelcast.getOrCreateHazelcastInstance(config);
    }

}

Когда я пытаюсь запустить приведенный выше код с 450 МБ кучи, он заканчивается ошибкой «Недостаточно памяти». После отладки я знал, что выселение не работает, даже если используемое пространство кучи составляет 80%. Пожалуйста, дайте мне знать, если я настроен неправильно. Любое предложение будет действительно полезным.

1 Ответ

0 голосов
/ 16 марта 2020

Этот код имеет ошибку вырезания и вставки

        MapConfig mapConfig1 = new MapConfig(MAP_NAME1);
        mapConfig.setMaxSizeConfig(maxSizeConfig);
        mapConfig.setStatisticsEnabled(false);
        mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
        mapConfig.setMinEvictionCheckMillis(0L);
        mapConfig.setBackupCount(1);

Должно быть

        MapConfig mapConfig1 = new MapConfig(MAP_NAME1);
        mapConfig1.setMaxSizeConfig(maxSizeConfig);
        mapConfig1.setStatisticsEnabled(false);
        mapConfig1.setEvictionPolicy(EvictionPolicy.LRU);
        mapConfig1.setMinEvictionCheckMillis(0L);
        mapConfig1.setBackupCount(1);

То же самое для mapConfig2.

Хотя это не помешает выселению первой из трех карт.

Обновление 1: Я могу заставить выселение работать. Вам нужно установить это перед созданием экземпляра Hazelcast, чтобы вместить небольшое количество ключей:

        config.setProperty("hazelcast.partition.count", "1");

Затем попробуйте этот код, если вы установите factor на 2, он работает, и произойдет выселение, установите его на 1 и это не так.

        int factor = 2;
        byte[] value = new byte[bytes / factor];
        for (long i = 1; i <= 10 * factor; i++) {
            System.out.println("Write " + i + " size " + value.length + " to " + mapname + " free memory " +
                   (Runtime.getRuntime().freeMemory() / (1024 * 1024)) + "MB");
            map.set(i, value);
        }

Однако, когда коэффициент установлен на 1 и -Xmx512m -Xms512m, я получаю OOME, когда 139 МБ свободно. Это более 20% свободной кучи, поэтому выселение не применимо.

Обновление 2 Я зарегистрировал эту проблему https://github.com/hazelcast/hazelcast/issues/16760 Вы можете получить OOME с большим количеством памяти осталось. Это то, что здесь произошло, выселение не было инициировано, так как объем свободной памяти был выше настроенного на 20%.

Обновление 3 Это проблема G1, см. Проблему Github из-за огромного пространства , Вы можете попробовать настроить, изменить G C или просто создать в 10 раз больше объектов, которые составляют 1/10 размера, и проблема исчезнет.

...