Skip to content

支持持久内存 & 动态阈值控制数据分布 代码变更

Patryk Kaminski edited this page Apr 14, 2022 · 2 revisions

动态阈值控制在redis.conf中的配置

memory-alloc-policy only-dram

  1. only-dram: 只使用DRAM而不去使用PMem。
  2. only-pmem: 只使用PMem而不使用DRAM。
  3. threshold:使用PMem和DRAM,使用静态的阈值。
  4. ratio: 使用PMem和DRAM,使用动态阈值来控制数据的分布,以保证数据的分布可以保持PMem和DRAM的使用比列。 默认的配置是使用 “memory-alloc-policy only-dram”。

static-threshold 64 如果内存的分配策略是threshold,那么使用静态的threshold。这个静态的threshold将由这个配置来指定。大于或等于阈值的数据将会放到PMem中,而小于阈值的数据将放到内存。这个值可以在运行的过程中进行修改。

dram-pmem-ratio X Y 如果内存的分配策略是ratio,那么dram-pmem-ratio <dram_value> <pmem_value>可以明确的表示redis instance想需要的内存和持久内存的比列。比如 dram-pmem-ratio 1 3 表示你所有的数据由25%在DRAM中,75%的数据将在持久内存里,要保证数据保持这样的比列,我们需要考虑使用动态的阈值来控制。

initial-dynamic-threshold 64 动态阈值控制的情况下,系统一开始可以有一个初始的阈值,可以设定,默认可以是64. 如果你比较清楚你的数据的patten,你可以通过这个初始值更快,更好的收敛到系统配置的比例。

dynamic-threshold-min 24 对于动态阈值的最小值也可以有一个配置,你可以将其设置为0。

动态算法设计

memKeyDB可以通过统计alloc, free, realloc等分配函数来计算DRAM和PMem的使用情况,在Redis Cron中定时(每100ms)检查DRAM和PMEM的使用情况,并计算初当前的DRAM和PMem的使用比例。

  1. 比较当前的DRAM和PMem的使用比例和我们目标设定的比例。如果当前比例还远离目标设定,将以一个较大的步长来动态调整(增加或者减少)阈值。
  2. 比较当前的DRAM和PMem的使用比例和100ms之前的DRAM和PMem的使用比例。如果趋势向好,及这次更接近于目标,则保持之前的调整节奏。如果相较100ms之前的比例,离目标更远,则使用更大的步长来调整阈值,比如使用之前步长的5倍来继续调整。这样可以加快收敛的速度。
void adjustPmemThresholdCycle(void) {
    if (server.memory_alloc_policy == MEM_POLICY_RATIO) {
        run_with_period(server.ratio_check_period) {
            /* Difference between target ratio and current ratio in last checkpoint*/
            static double ratio_diff_checkpoint;
            /* PMEM and DRAM utilization in last checkpoint*/
            static size_t total_memory_checkpoint;
            size_t pmem_memory = zmalloc_used_pmem_memory();
            size_t dram_memory = zmalloc_used_memory();
            size_t total_memory_current = pmem_memory + dram_memory;
            // do not modify threshold when change in memory usage is too small
            if (absDiff(total_memory_checkpoint, total_memory_current) > 100) {
                double current_ratio = (double)pmem_memory/dram_memory;
                double current_ratio_diff = fabs(current_ratio - server.target_pmem_dram_ratio);
                if (current_ratio_diff > 0.02) {
                    //current ratio is worse than moment before
                    double variableMultipler = current_ratio/server.target_pmem_dram_ratio;
                    double step = (current_ratio_diff < ratio_diff_checkpoint) ?
                                  variableMultipler*THRESHOLD_STEP_NORMAL : variableMultipler*THRESHOLD_STEP_AGGRESIVE;
                    size_t threshold = zmalloc_get_threshold();
                    if (server.target_pmem_dram_ratio < current_ratio) {
                        size_t higher_threshold = THRESHOLD_UP(threshold,step);
                        if (higher_threshold <= server.dynamic_threshold_max)
                            zmalloc_set_threshold(higher_threshold);
                    } else {
                        size_t lower_threshold = THRESHOLD_DOWN(threshold,step);
                        if (lower_threshold >= server.dynamic_threshold_min)
                            zmalloc_set_threshold(lower_threshold);
                    }
                }
                ratio_diff_checkpoint = current_ratio_diff;
            }
            total_memory_checkpoint = total_memory_current;
        }
    }
}

性能优化