本文介绍了Global RelCache的简介和使用方法。

背景信息

目前RelCache为Session私有,且无淘汰机制,导致连接数过多或者表个数过多时,RelCache消耗过多内存,甚至出现OOM的风险。

PolarDB PostgreSQL版采用Global RelCache + Local RelCache两层缓存架构。部分系统表都只会存在Local RelCache中,其他普通的用户表和大部分系统表都会自动加载到Global RelCache中,而Local RelCache日常只需要设置比较小的容量,在需要的时候从Global RelCache加载,如果Local RelCache容量超限,则按照淘汰策略进行淘汰。

简介

PostgreSQL的RelCache缓存了所有表的元数据信息,为每个进程私有,在连接数较多时消耗很多内存。Global RelCache将RelCache放到共享内存中,为所有进程共享,提高内存利用率。

参数说明

Global RelCache引入了以下GUC参数,在必要的时候可以通过参数开启或关闭Global RelCache和Local RelCache的相关功能,或者进行一些性能调优。

参数说明级别
polar_local_relcache_size用于设置Local RelCache的容量大小。取值范围:0 ~ INT_MAX,默认值为0(表示没有容量限制,不会开启淘汰能力)。单位为KB。
说明 建议根据活跃表的数量进行设置,一般使用默认值即可,无需修改,也可以参考监控中的查询命中率进行设置。
PGC_USERSET
polar_enable_global_relcache是否开启Global RelCache功能。取值范围:on(开启)/off(关闭),默认值为on。
说明
  • Global RelCache在绝大部分场景下对性能几乎无影响,但在极少数极端情况下仍然可能会有可见的性能损耗。如果确定RelCache不会消耗太多内存,可以通过该参数关闭Global RelCache功能,避免性能损耗。
  • polar_global_relcache_size设置为0时也可以禁用 Global RelCache ,但polar_global_relcache_size修改只能重启生效,所以不适合作为控制开关。
  • 该参数修改之后,各个session会待下个事务开始前再生效。
PGC_SIGHUP
polar_global_relcache_size用于设置Global RelCache的容量大小。取值范围:0 ~ INT_MAX,默认值为1024 ,单位为MB。
说明 建议该参数设置足够容纳所有表(包括索引、toast table、view 等),该内存为所有Session共享,并且在系统启动时进行初始化,所以需要重启生效。
PGC_POSTMASTER

运维

所有监控接口都在polar_grc插件中,如果需要使用请先执行create extension polar_grc;,主要的运维动作为create/drop extension

  • Local RelCache强制淘汰

    因为Local RelCache是被动且逐步淘汰的策略,如果遇到定时任务或者突发异常大流量之后又突然idle的session,Local RelCache可以通过定时机制快速的把内存降下来。但依然有部分场景可能需要手动去干预某个session的Local RelCache内存情况。

    例如,在运行过程中,发现Local RelCache设置的太大了,消耗了太多的内存,然后在线调低之后,有部分session已经占了超限的内存,但因为session处于idle的状态,如果有需要的话,可以通过该接口手动干预。
    说明 因为PostgreSQL的config reload是lazy模式,在收到SIGHUP信号之后,实际重新加载config file可能是在下一次执行SQL之前,对PostgreSQL而言这样操作是合理的,因为在这期间,调整了也不会使用。
    执行以下命令调用polar_relcache_evict函数,可以把指定backend进程淘汰Local RelCache中所有可以淘汰的relation,从而降低内存。
    select polar_relcache_evict($backend_pid);
  • 重置监控数据
    大多数监控数据的计数器会持续递增或者递减,可以在获取监控数据的函数中通过reset参数重置,也可以通过额外的重置接口。当然也可以在获取监控数据的同时通过polar_relcache_get_statpolar_relcache_get_partition_stat函数参数来直接重置。
    CREATE FUNCTION polar_relcache_reset_stat(
            OUT num_reset int4)
    RETURNS integer
    AS 'MODULE_PATHNAME', 'polar_relcache_reset_stat'
    LANGUAGE C;
    
    CREATE FUNCTION polar_grc_reset_stat(
            OUT num_reset int4)
    RETURNS integer
    AS 'MODULE_PATHNAME', 'polar_grc_reset_stat'
    LANGUAGE C;

监控

Global RelCache和Local RelCache提供了若干函数和视图,函数是视图的超集,视图只是为了方便使用而创建。所有函数和视图的定义都在 polar_grc插件中。

  • Local RelCache
    • polar_relcache_get_stat函数和polar_relcache_stat视图

      polar_relcache_get_stat函数和polar_relcache_stat视图的输出完全一致,主要用于输出Local RelCache内部的各种状态和统计信息。

      不同的是函数带了一个输入参数reset,表示是否重置统计计数器。绝大部分统计信息都是一个计数器,如果不重置的话,计数器会一直累加,如果想获取特定时间区间内的状态情况,可以在开始时对状态进行重置。

      指标说明:
      指标说明
      reset表示是否需要重置所有的统计计数器。取值如下:
      • true:表示需要重置所有的统计计数器。在返回本次结果之后会清零所有计数器。
      • false:表示不需要重置所有的统计计数器。
      backend_pid表示统计信息所属的backend进程。
      num_entry表示当前Local RelCache中缓存了多少个Relation。
      count_insert表示Local RelCache从上次计数器重置开始到现在插入的次数。
      count_delete表示Local RelCache从上次计数器重置开始到现在删除的次数。
      count_nailed_lookup表示Local RelCache从上次计数器重置到现在nailed table查询次数。
      count_lookup表示Local RelCache从上次计数器重置到现在查询的次数。
      说明 此处只包含非nailed表的次数。这个指标和上一个count_nailed_lookup加起来表示整个Local RelCache的查询次数。
      count_lookup_miss表示Local RelCache从上次计数器重置到现在查询未命中的次数。
      说明 count_nailed_lookup和count_lookup两个指标包含了命中和不命中的查询次数,这个指标表示不命中的次数,通过 (count_lookup - count_lookup_miss) / count_lookup可以计算出非nailed table的缓存命中率,而(count_lookup + count_nailed_lookup - count_lookup_miss) / count_lookup 可以计算出整个Local RelCache所有查询的命中率。一般来说,前一个命中率更有意义。
      count_evict表示Local RelCache从上次计数器重置到现在一共淘汰了多少个Relation。
      count_forced_evict表示Local RelCache从上次计数器重置到现在通过polar_relcache_evict函数强制淘汰了多少个Relation。
      count_timeout_evict表示Local RelCache从上次计数器重置到现在通过timeout机制一共淘汰了多少个Relation。
      说明 对活跃连接来说,这个值一般为0,count_timeout_evict + count_evict 反映了Local RelCache正常淘汰的个数。
      count_evictcycle表示Local RelCache从上次计数器重置到现在一共淘汰了多少次。
      count_empty_evictcycle表示Local RelCache从上次计数器重置到现在一共有多少淘汰是空扫的,也就是徒劳的。正常情况下该值为0。
      avg_step_length表示Local RelCache从上次计数器重置到现在平均每次淘汰的Relation个数。
      说明 一般情况下这个值不会很大,因为淘汰算法会让淘汰尽量平缓。
      max_step_length表示Local RelCache从上次计数器重置到现在最多一次淘汰了多少个Relation。
      说明 在突发大流量的情况可能出现该值比较大的情况。
      avg_idletime表示Local RelCache从上次计数器重置到现在所有淘汰的Relation平均空闲时间。
      说明 该值越小表示目前Local RelCache的淘汰压力越大,说明polar_local_relcache_size设置偏低,允许的情况下可以适当调高阈值。
      max_idletime表示Local RelCache从上次计数器重置到现在所有淘汰的Relation中最大的空闲时间。
      说明 该指标反映了当前的Local RelCache淘汰压力,如果这个值很大,说明当前容量设置是很充裕的,可以适当调小。如果这个值非常小,说明容量设置有些偏小。
      avg_evict_time表示Local RelCache从上次计数器重置到现在平均每次用于淘汰消耗的时间。
      max_evict_time表示Local RelCache从上次计数器重置到现在单次淘汰最大消耗的时间。
      说明 该指标和avg_evict_time一起反映淘汰算法本身的性能情况,一般情况下,这两个值都非常低,如果出现比较高的值,属于非预期的异常情况,需要进行排查。
      memory_context_total_space表示当前RelCache MemoryContext总共分配的内存,单位为Bytes。
      memory_context_free_space表示当前RelCache MemoryContext内部空闲内存。包括未使用完的block和空闲的chunk。
      说明 该指标和memory_context_total_space一起用于评估当前的内存占用,以及内部碎片情况。
    • polar_relcache_get_relation函数和polar_relcache_relation视图

      polar_relcache_get_relation函数和polar_relcache_relation视图用于将Local RelCache中当前缓存的Relation都输出出来。因为Local RelCache是每个Sesion私有的,所以只能输出自己Session中缓存的。主要作用是用于调试和问题排查、定位等用途。

  • Global RelCache

    polar_grc_get_stat函数和polar_grc_stat视图

    与polar_relcache_stat类似,主要用于输出Global RelCache内部的各种状态和统计信息。视图和函数输出的结果一致,只是额外多一个输入参数,用于控制是否重置统计计数器。
    CREATE FUNCTION polar_grc_get_stat(
            IN    reset boolean,
            OUT num_entry int8,
            OUT count_insert int8,
            OUT count_update int8,
            OUT count_delete int8,
            OUT count_lookup int8,
            OUT count_lookup_miss int8,
            OUT count_OOM int8,
            OUT    count_invalid_lookup int8,
            OUT    count_error_clean int8,
            OUT num_partitions int4,
            OUT shm_free_space int8,
            OUT shmaset_total_space int8,
            OUT shmaset_free_space int8
    )
    RETURNS record
    AS 'MODULE_PATHNAME', 'polar_grc_get_stat'
    LANGUAGE C;
    
    CREATE VIEW polar_grc_stat AS
        SELECT * FROM polar_grc_get_stat(false);
    指标说明:
    指标说明
    num_entry表示Global RelCache中缓存的Relation个数,包含所有数据库。
    count_insert表示Global RelCache从上次重置到现在插入的次数。
    count_update表示Global RelCache从上次重置到现在更新的次数。
    count_delete表示Global RelCache从上次重置到现在删除的次数。
    count_lookup表示Global RelCache从上次重置到现在查询的次数。
    count_lookup_miss表示Global RelCache从上次重置到现在查询未命中的次数。
    说明 通过 (count_lookup - count_lookup_miss) / count_lookup可以得到Global RelCache的查询命中率,一般来说,在缓存预热之后,Global RelCache的命中率会稳定在高水平。
    count_OOM表示Global RelCache从上次重置到现在发生OOM的次数。
    说明 因为Shared Memory内存在集群启动时初始化且容量固定,所以如果容量设置不合理,在使用期间shared memory不够用的话,会发生Global RelCache的插入和更新失败,该值记录了发生OOM的次数。
    count_invalid_lookup表示Global RelCache查询命中数。
    说明 如果该Relation正在被其他Session并发更新,目前的状态为invalid,所以本次查询无效。正常情况下,该值为0或者很小;如果出现比较大的值,除非特殊业务场景,否则需要进行排查。
    count_error_clean进程异常退出或者事务提交过程中出现ERROR,在回滚或者进程退出之前会清理Global RelCache中维护的relation信息,该指标记录了发生这种异常清理的次数。
    说明 如果这个指标非常高,表示当前集群的处于不太正常的状态。
    num_partitions表示Global RelCache使用的分区哈希表数量。
    说明 正常情况下,这个值等于polar_global_relcache_partitions配置的值,如果该值比配置要小,说明如果发生了OOM,部分哈希分区被停用了。
    shm_free_space表示Global RelCache剩余的共享内存字节数。
    说明 如果该值很小,表示polar_global_relcache_size设置的太小了,最好调大,否则可能会发生OOM,进而影响性能。
    shmaset_total_space表示Global RelCache使用的Memory Context共分配的内存大小。
    说明 shmaset_total_space + shm_free_space = polar_global_relcache_size
    shmaset_free_space表示Global RelCache使用的Memory Context内部的空闲内存。
    说明 该指标和shmaset_total_space一起反映共享内存的使用情况以及内部碎片。