• redis主从同步异常


    前几天遇到了一个主从同步异常的问题,主库是3.0版本,从库3.0只读,主库key已经过期了,但是从库还能查到。

    对于过期key,只读从库不会主动删除,当key过期后,如果主库对过期key处理的不及时,那么从库还是会读到这个key。

    小于3.2版本的redis会存在这个问题,大于等于3.2版本的redis有优化,在从库读取key时,会判断key是否过期,如果已经过期,

    会返回nil,但是从库荣然不会主动delkey,还是依赖主库的清除过期key时,同步到从库的del操作。

    /***
        redis-3.2.13
    ***/
    int expireIfNeeded(redisDb *db, robj *key) {
        mstime_t when = getExpire(db,key);
        mstime_t now;
    
        if (when < 0) return 0; /* No expire for this key */
    
        /* Don't expire anything while loading. It will be done later. */
        if (server.loading) return 0;
    
        /* If we are in the context of a Lua script, we claim that time is
         * blocked to when the Lua script started. This way a key can expire
         * only the first time it is accessed and not in the middle of the
         * script execution, making propagation to slaves / AOF consistent.
         * See issue #1525 on Github for more information. */
        now = server.lua_caller ? server.lua_time_start : mstime();
    
        /* If we are running in the context of a slave, return ASAP:
         * the slave key expiration is controlled by the master that will
         * send us synthesized DEL operations for expired keys.
         *
         * Still we try to return the right information to the caller,
         * that is, 0 if we think the key should be still valid, 1 if
         * we think the key is expired at this time. */
        if (server.masterhost != NULL) return now > when;
    
        /* Return when this key has not expired */
        if (now <= when) return 0;
    
        /* Delete the key */
        server.stat_expiredkeys++;
        propagateExpire(db,key);
        notifyKeyspaceEvent(NOTIFY_EXPIRED,
            "expired",key,db->id);
        return dbDelete(db,key);
    }
    robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
        robj *val;
    
        if (expireIfNeeded(db,key) == 1) {
            /* Key expired. If we are in the context of a master, expireIfNeeded()
             * returns 0 only when the key does not exist at all, so it's safe
             * to return NULL ASAP. */
            if (server.masterhost == NULL) return NULL;
    
            /* However if we are in the context of a slave, expireIfNeeded() will
             * not really try to expire the key, it only returns information
             * about the "logical" status of the key: key expiring is up to the
             * master in order to have a consistent view of master's data set.
             *
             * However, if the command caller is not the master, and as additional
             * safety measure, the command invoked is a read-only command, we can
             * safely return NULL here, and provide a more consistent behavior
             * to clients accessign expired values in a read-only fashion, that
             * will say the key as non exisitng.
             *
             * Notably this covers GETs when slaves are used to scale reads. */
            if (server.current_client &&
                server.current_client != server.master &&
                server.current_client->cmd &&
                server.current_client->cmd->flags & CMD_READONLY)
            {
                return NULL;
            }
        }
        val = lookupKey(db,key,flags);
        if (val == NULL)
            server.stat_keyspace_misses++;
        else
            server.stat_keyspace_hits++;
        return val;
    }
  • 相关阅读:
    使用zabbix监控sql server的发布订阅
    MySQL执行计划
    3.MongoDB恢复探究:为什么oplogReplay参数只设置了日志应用结束时间oplogLimit,而没有设置开始时间?
    面试官看完我手写的单例直接惊呆了!
    故事:坐在我隔壁的小王问我什么是HyperLogLog
    JDK15就要来了,你却还不知道JDK8的新特性!
    不要再问我 in,exists 走不走索引了
    JVM性能调优(4) —— 性能调优工具
    JVM性能调优(3) —— 内存分配和垃圾回收调优
    JVM性能调优(2) —— 垃圾回收器和回收策略
  • 原文地址:https://www.cnblogs.com/chenyang920/p/12736632.html
Copyright © 2020-2023  润新知