Redis 数据结构与内存管理策略(下) (4)

noeviction:客户端尝试执行会让更多内存被使用的命令直接报错
allkeys-lru: 在所有key里执行lru算法
volatile-lru:在所有已经过期的key里执行lru算法
allkeys-random:在所有key里随机回收
volatile-random:在已经过期的key里随机回收
volatile-ttl:回收已经过期的key,并且优先回收存活时间(TTL)较短的键

关于 cache 的命中率可以通过 info 命令查看 键空间的命中率和未命中率。

# Stats keyspace_hits:33 keyspace_misses:5

maxmemory 在到达阈值的时候会采用一定的策略去释放内存,这些策略我们可以根据自己的业务场景来选择,默认是 noeviction

redis LRU 算法有一个取样的优化机制,可以通过一定的取样因子来加强回收的 key 的准确度。CONFIG GET maxmemory-samples 查看取样配置,具体可以参考更加详细的文章。

Redis 持久化方式

redis 本身提供持久化功能,有两种持久化机制,一种是数据持久化 RDB ,一种是命令持久化 AOF,这两种持久化方式各有优缺点,也可以组合使用,一旦组合使用 redis 在载入数据的时候会优先载入 aof 文件,只有当 AOF 持久化关闭的时候才会载入 rdb 文件。

RDB (Redis DataBase)

RDBredis 数据库,redis 会根据一个配置来触发持久化。

#save <seconds> <changes> save 900 1 save 300 10 save 60 10000 CONFIG GET save 1) "save" 2) "3600 1 300 100 60 10000"

表示在多少秒之类的变化次数,一旦达到这个触发条件 redis 将触发持久化动作。redis 在执行持久化的时候有两种模式 BGSAVE、SAVEBGSAVE 是后台保存,redisfork 出一个子进程来处理持久化,不会 block 用户的执行请求。而 SAVE 则会 block 用户执行请求。

struct redisServer { long long dirty;/* Changes to DB from the last save */ time_t lastsave; /* Unix time of last successful save */ long long dirty_before_bgsave; pid_t rdb_child_pid;/* PID of RDB saving child */ struct saveparam *saveparams; /* Save points array for RDB */ } struct saveparam { time_t seconds; int changes; };

redisServer 包含的信息很多,其中就包含了有关于 RDB 持久化的信息。redisServer->dirty 至上次 save 到目前为止的 change 数。redisServer->lastsave 上次 save 时间。

saveparam struct 保存了我们通过 save 命令设置的参数,time_t 是个 long 时间戳。

typedef __darwin_time_t time_t; typedef long __darwin_time_t; /* time() */ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { for (j = 0; j < server.saveparamslen; j++) { struct saveparam *sp = server.saveparams+j; if (server.dirty >= sp->changes && server.unixtime-server.lastsave > sp->seconds && (server.unixtime-server.lastbgsave_try > REDIS_BGSAVE_RETRY_DELAY || server.lastbgsave_status == REDIS_OK)) { redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...", sp->changes, (int)sp->seconds); rdbSaveBackground(server.rdb_filename); break; } } }

redis 事件循环会周期性的执行 serverCron 方法,这段代码会循环遍历 server.saveparams 参数链表。

如果 server.dirty 大于等于 我们参数里配置的变化并且 server.unixtime-server.lastsave 大于参数里配置的时间并且 server.unixtime-server.lastbgsave_try 减去 bgsave 重试延迟时间或者当前 server.lastbgsave_status==REDIS_OK 则执行 rdbSaveBackground 方法。

AOF (Append-only file)

AOF 持久化是采用对文件进行追加对方式进行,每次追加都是 redis 处理的 命令。有点类似 command sourcing 命令溯源 的模式。

只要我们可以将所有的命令按照执行顺序在重放一遍就可以还原最终的 redis 内存状态。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzjfw.html