广告位联系
返回顶部
分享到

redis淘汰策略的几种实现介绍

Redis 来源:互联网 作者:佚名 发布时间:2024-05-22 21:44:32 人浏览
摘要

redis内存数据数据集大小升到一定大的时候,就会实行数据淘汰策略(回收策略)。 1,volatile-lru:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个key,然后在选到的key中用lru算法淘

redis内存数据数据集大小升到一定大的时候,就会实行数据淘汰策略(回收策略)。

1,volatile-lru:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个key,然后在选到的key中用lru算法淘汰最近最少使用的数据

2,allkey-lru:从所有key的哈希表(server.db[i].dict)中随机挑选多个key,然后再选到的key中利用lru算法淘汰最近最少使用的数据

3,volatile-ttl:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选多个key,然后在选到的key中选择过期时间最小的数据淘汰掉。

4,volatile-random:从已设置过期时间的哈希表(server.db[i].expires)中随机挑选key淘汰掉。

5,allkey-random:从所有的key的哈希表(server.db[i].dict)中随机挑数据淘汰

6,no-eviction(驱逐):内存达到上限,不淘汰数据。

redis确认驱逐某个键值对后,会删除这个数据,并将这个数据变更消息发布到本地(AOF持久化)和从机(主从连接)。

 LRU数据淘汰机制是这样的:在数据集中随机挑选几个键值对,去除其中最近最少使用的键值对淘汰。所以Redis并不是保证取得所有数据集中最少最少使用的键值对,而只是在随机挑选的几个键值对中。

TTL数据淘汰机制:从国企时间redisDB.expires表中随机挑选几个键值对,取出其中最快过期的键值对淘汰。所以Redis并不保证取得所有过期时间表中最快过期的键值对,而是随机挑选的几个键值对中。

无论是什么机制,都是从所有的键值对中挑选合适的淘汰。

在哪里开始淘汰数据:

Redis服务器每执行一次命令的时候,会检测使用的内存是否超额。如果超额,即进行数据淘汰。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

int freeMemoryIfNeeded(void) {

    /**

     * noeviction 不淘汰数据,什么都不做

     */

    if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION)

        return C_ERR;

    while (mem_freed < mem_tofree) {

        int j, k, keys_freed = 0;

        for (j = 0; j < server.dbnum; j++) {

            /**

             * 选择操作的哈希表,Redis另外维护着一个保存过期时间的key=>expire关联的哈希表

             */

            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||

                server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM)

            {

                dict = server.db[j].dict;

            } else {

                dict = server.db[j].expires;

            }

            /**

             * 分支一:全局哈希表随机或者过期时间哈希表中,随机淘汰一个key

             */

            if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM ||

                server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM)

            {

                de = dictGetRandomKey(dict);

                bestkey = dictGetKey(de);

            }

            /**

             * 分支二:全局哈希表随机或者过期时间哈希表中,随机采样多个数据,再运用lru算法挑选一个淘汰

             */

            else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||

                server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU)

            {

                /* 样本集 */

                struct evictionPoolEntry *pool = db->eviction_pool;

                while(bestkey == NULL) {

                    /*

                     * 采样,更新和维护样本集;

                     * 样本集开始是空的,每次操作完并不会清空样本集;

                     * 而且每次采样,都会采集多个数据,同时和样本集中已有的数据进行比较,新增或者更新样本集;

                     */

                    evictionPoolPopulate(dict, db->dict, db->eviction_pool);

                    /**

                     * 开始对样本集使用lru算法,淘汰样本集中访问时间最晚的key

                     */

                    for (k = MAXMEMORY_EVICTION_POOL_SIZE-1; k >= 0; k--) {

                        if (pool[k].key == NULL) continue;

                        de = dictFind(dict,pool[k].key);

                        /* 把选取到的key从样本集中移除 */

                        sdsfree(pool[k].key);

                        memmove(pool+k,pool+k+1,

                            sizeof(pool[0])*(MAXMEMORY_EVICTION_POOL_SIZE-k-1));

                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].key = NULL;

                        pool[MAXMEMORY_EVICTION_POOL_SIZE-1].idle = 0;

                        /* pool样本集内的key,只是样本,不一定和db内保持一致,也不必,可能在db中已经被删除的,所以要作判断 */

                        if (de) {

                            bestkey = dictGetKey(de);

                            break;

                        } else {

                            /* Ghost... */

                            continue;

                        }

                    }

                }

            }

            /**

             * 分支三:在设置了过期时间的哈希表里面随机选择多个key,在挑选到的key中选择过期时间最小的一个淘汰掉

             */

            else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) {

                for (k = 0; k < server.maxmemory_samples; k++) {

                    sds thiskey;

                    long thisval;

                    de = dictGetRandomKey(dict);

                    thiskey = dictGetKey(de);

                    thisval = (long) dictGetVal(de);

                    if (bestkey == NULL || thisval < bestval) {

                        bestkey = thiskey;

                        bestval = thisval;

                    }

                }

            }

            if (bestkey) {

                long long delta;

                robj *keyobj = createStringObject(bestkey,sdslen(bestkey));

                // 命令扩散,把删除key的命令同步到所有从库slave

                propagateExpire(db,keyobj);

                // 删除key

                dbDelete(db,keyobj);

            }

        }

    }

    return C_OK;

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • redis生成全局id的实现步骤
    使用redis生成全局id 在现代软件开发中,生成全局唯一的标识符是非常常见的需求。这些全局唯一ID在分布式系统中尤其重要,用于标识各种
  • Redis锁的过期时间小于业务的执行时间如何续期

    Redis锁的过期时间小于业务的执行时间如何续期
    假设我们给锁设置的过期时间太短,业务还没执行完成,锁就过期了,这块应该如何处理呢?是否可以给分布式锁续期? 解决方案:先设置
  • Redis分布式锁及4种常见实现方法
    线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有
  • redis淘汰策略的几种实现介绍
    redis内存数据数据集大小升到一定大的时候,就会实行数据淘汰策略(回收策略)。 1,volatile-lru:从已设置过期时间的哈希表(server.db[i].e
  • Redis中过期键删除的三种方法

    Redis中过期键删除的三种方法
    Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期。 那么一个过期的键是
  • redis并发之跳表的实现
    跳表(Skip List)是一种用于实现有序集合(Sorted Set)的数据结构,在 Redis 中被广泛应用。跳表的设计旨在提供高效的有序集合操作,可以将
  • 保证Redis中存储的Token安全性的介绍
    确保Redis中存储的Token安全性是一个多层面的任务,涉及到网络、应用、数据和操作等多个方面的安全措施。以下是一些更详细的实践建议和
  • redis和redisson实现分布式锁的操作方法介绍

    redis和redisson实现分布式锁的操作方法介绍
    基于setnx命令的分布式锁 1. 加锁 使用 Redis 实现分布式锁,最直接的想法是利用 setnx 和 expire 命令实现加锁。 在 Redis 中,setnx 是「set if no
  • Redisson分布式限流的实现原理介绍

    Redisson分布式限流的实现原理介绍
    我们目前在工作中遇到一个性能问题,我们有个定时任务需要处理大量的数据,为了提升吞吐量,所以部署了很多台机器,但这个任务在运
  • 宝塔中ThinkPHP框架使用Redis的一系列教程介绍

    宝塔中ThinkPHP框架使用Redis的一系列教程介绍
    Redis是一种常用的非关系型数据库,主要用作数据缓存,数据保存形式为key-value,键值相互映射。它的数据存储跟MySQL不同,它数据存储在内存之中
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计