示例#1
0
 public void Close()
 {
     foreach (var kv in _instanceSettingDict)
     {
         RedisInstanceManager.Close(kv.Value);
     }
 }
示例#2
0
        /// <summary>
        /// GetDatabaseAsync
        /// </summary>
        /// <param name="instanceName"></param>
        /// <returns></returns>
        /// <exception cref="KVStoreException"></exception>
        private async Task <IDatabase> GetDatabaseAsync(string instanceName)
        {
            if (_instanceSettingDict.TryGetValue(instanceName, out RedisInstanceSetting? setting))
            {
                return(await RedisInstanceManager.GetDatabaseAsync(setting, _logger).ConfigureAwait(false));
            }

            throw Exceptions.NoSuchInstance(instanceName: instanceName);
        }
示例#3
0
        /// <summary>
        /// PublishAsync
        /// </summary>
        /// <param name="brokerName"></param>
        /// <param name="eventMessage"></param>
        /// <returns></returns>
        /// <exception cref="EventBusException"></exception>
        public async Task PublishAsync(string brokerName, string eventName, string jsonData)
        {
            RedisInstanceSetting instanceSetting = GetRedisInstanceSetting(brokerName);

            IDatabase database = await RedisInstanceManager.GetDatabaseAsync(instanceSetting, _logger).ConfigureAwait(false);

            EventMessageEntity entity = new EventMessageEntity(eventName, jsonData);

            await database.ListLeftPushAsync(QueueName(entity.EventName), SerializeUtil.ToJson(entity)).ConfigureAwait(false);
        }
示例#4
0
        /// <exception cref="CacheException"></exception>
        protected IDatabase GetDatabase(string?instanceName)
        {
            instanceName ??= DefaultInstanceName;

            if (_instanceSettingDict.TryGetValue(instanceName, out RedisInstanceSetting? setting))
            {
                return(RedisInstanceManager.GetDatabase(setting, _logger));
            }

            throw Exceptions.InstanceNotFound(instanceName);
        }
示例#5
0
        /// <exception cref="CacheException"></exception>
        protected async Task <IDatabase> GetDatabaseAsync(string?instanceName)
        {
            instanceName ??= DefaultInstanceName;

            if (_instanceSettingDict.TryGetValue(instanceName, out RedisInstanceSetting? setting))
            {
                return(await RedisInstanceManager.GetDatabaseAsync(setting, _logger).ConfigureAwait(false));
            }

            throw Exceptions.InstanceNotFound(instanceName: instanceName);
        }
示例#6
0
        internal static void InitLoadedLuas(RedisInstanceSetting redisInstanceSetting, ILogger logger)
        {
            IServer server = RedisInstanceManager.GetServer(redisInstanceSetting, logger);

            _loadedLuas = new LoadedLuas
            {
                LoadedLockLua   = server.ScriptLoad(_luaLock),
                LoadedUnLockLua = server.ScriptLoad(_luaUnlock),
                LoadedExtendLua = server.ScriptLoad(_luaExtend)
            };
        }
示例#7
0
        private void InitLoadedLuas()
        {
            foreach (RedisInstanceSetting setting in _options.ConnectionSettings)
            {
                IServer    server     = RedisInstanceManager.GetServer(setting, _logger);
                LoadedLuas loadedLuas = new LoadedLuas
                {
                    LoadedBatchAddLua    = server.ScriptLoad(_luaBatchAdd),
                    LoadedBatchUpdateLua = server.ScriptLoad(_luaBatchUpdate),
                    LoadedBatchDeleteLua = server.ScriptLoad(_luaBatchDelete),
                    LoadedBatchGetLua    = server.ScriptLoad(_luaBatchGet),
                    LoadedGetAllLua      = server.ScriptLoad(_luaGetAll)
                };

                _loadedLuaDict[setting.InstanceName] = loadedLuas;
            }
        }
示例#8
0
        /// <summary>
        /// 各服务器反复Load也没有关系
        /// </summary>
        protected void InitLoadedLuas()
        {
            foreach (RedisInstanceSetting setting in _options.ConnectionSettings)
            {
                IServer    server     = RedisInstanceManager.GetServer(setting, _logger);
                LoadedLuas loadedLuas = new LoadedLuas
                {
                    LoadedSetWithTimestampLua    = server.ScriptLoad(RedisCache.LUA_SET_WITH_TIMESTAMP),
                    LoadedRemoveWithTimestampLua = server.ScriptLoad(RedisCache.LUA_REMOVE_WITH_TIMESTAMP),
                    LoadedGetAndRefreshLua       = server.ScriptLoad(RedisCache.LUA_GET_AND_REFRESH),

                    LoadedEntitiesGetAndRefreshLua            = server.ScriptLoad(RedisCache.LUA_ENTITIES_GET_AND_REFRESH),
                    LoadedEntitiesGetAndRefreshByDimensionLua = server.ScriptLoad(RedisCache.LUA_ENTITIES_GET_AND_REFRESH_BY_DIMENSION),
                    LoadedEntitiesSetLua               = server.ScriptLoad(RedisCache.LUA_ENTITIES_SET),
                    LoadedEntitiesRemoveLua            = server.ScriptLoad(RedisCache.LUA_ENTITIES_REMOVE),
                    LoadedEntitiesRemoveByDimensionLua = server.ScriptLoad(RedisCache.LUA_ENTITIES_REMOVE_BY_DIMENSION),

                    LoadedEntitiesForcedRemoveLua            = server.ScriptLoad(RedisCache.LUA_ENTITIES_REMOVE_FORECED_NO_VERSION),
                    LoadedEntitiesForcedRemoveByDimensionLua = server.ScriptLoad(RedisCache.LUA_ENTITIES_REMOVE_BY_DIMENSION_FORCED_NO_VERSION),
                };

                _loadedLuaDict[setting.InstanceName] = loadedLuas;
            }
        }
示例#9
0
        private void InitLodedLua()
        {
            IServer server = RedisInstanceManager.GetServer(_instanceSetting, _logger);

            _loadedHistoryLua = server.ScriptLoad(_hISTORY_REDIS_SCRIPT);
        }
示例#10
0
        /// <summary>
        /// CosumeTaskProcedure
        /// </summary>


        private async Task CosumeAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    long now = TimeUtil.UtcNowUnixTimeSeconds;

                    //1, Get Entity
                    IDatabase database = await RedisInstanceManager.GetDatabaseAsync(_instanceSetting, _logger).ConfigureAwait(false);

                    RedisValue redisValue = await database.ListRightPopLeftPushAsync(RedisEventBusEngine.QueueName(_eventType), RedisEventBusEngine.HistoryQueueName(_eventType)).ConfigureAwait(false);

                    if (redisValue.IsNullOrEmpty)
                    {
                        _logger.LogTrace("ConsumeTask Sleep, {InstanceName}, {eventType}", _instanceSetting.InstanceName, _eventType);

                        await Task.Delay(_cONSUME_INTERVAL_SECONDS * 1000, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    EventMessageEntity?entity = SerializeUtil.FromJson <EventMessageEntity>(redisValue);

                    if (entity == null)
                    {
                        _logger.LogCritical("有空EventMessageEntity, {eventType}, {value}", _eventType, redisValue);
                        continue;
                    }

                    using IDistributedLock distributedLock = await _lockManager.NoWaitLockAsync(
                              "eBusC_" + entity.Guid,
                              TimeSpan.FromSeconds(_options.EventBusConsumerAckTimeoutSeconds),
                              false,
                              cancellationToken).ConfigureAwait(false);

                    if (!distributedLock.IsAcquired)
                    {
                        //竟然有人在检查entity.Guid,好了,这下肯定有人在处理了,任务结束。哪怕那个人没处理成功,也没事,等着history吧。
                        continue;
                    }

                    //2, 过期检查

                    if (now - entity.Timestamp > _eventBusEventMessageExpiredSeconds)
                    {
                        _logger.LogCritical("有EventMessage过期,{eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));

                        await distributedLock.DisposeAsync().ConfigureAwait(false);

                        continue;
                    }

                    //3, 防重检查

                    string AcksSetName = RedisEventBusEngine.AcksSetName(_eventType);

                    bool?isExist = await IsAcksExistedAsync(database, AcksSetName, entity.Guid).ConfigureAwait(false);

                    if (isExist == null || isExist.Value)
                    {
                        _logger.LogInformation("有EventMessage重复,{eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));

                        await distributedLock.DisposeAsync().ConfigureAwait(false);

                        continue;
                    }

                    //4, Handle Entity
                    try
                    {
                        await _eventHandler.HandleAsync(entity.JsonData, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogCritical(ex, "处理消息出错, {_eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));
                    }

                    //5, Acks
                    await AddAcksAsync(now, database, AcksSetName, entity.Guid, entity.Timestamp).ConfigureAwait(false);

                    _logger.LogTrace("Consume Task For {eventType} Stopped.", _eventType);
                }
                catch (RedisConnectionException ex)
                {
                    _logger.LogError(ex, "Consume 中出现Redis链接问题. {eventType}", _eventType);
                    await Task.Delay(5000, cancellationToken).ConfigureAwait(false);
                }
                catch (RedisTimeoutException ex)
                {
                    _logger.LogError(ex, "Consume 中出现Redis超时问题. {eventType}", _eventType);
                }
                catch (Exception ex)
                {
                    _logger.LogCritical(ex, "Consume 出现未知问题. {eventType}", _eventType);
                }
            }
        }
示例#11
0
        private async Task ScanHistoryAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    RedisKey[] redisKeys = new RedisKey[] {
                        RedisEventBusEngine.HistoryQueueName(_eventType),
                        RedisEventBusEngine.AcksSetName(_eventType),
                        RedisEventBusEngine.QueueName(_eventType)
                    };

                    RedisValue[] redisArgvs = new RedisValue[] {
                        TimeUtil.UtcNowUnixTimeSeconds,
                        _options.EventBusConsumerAckTimeoutSeconds
                    };

                    IDatabase database = await RedisInstanceManager.GetDatabaseAsync(_instanceSetting, _logger).ConfigureAwait(false);

                    int result = (int)await database.ScriptEvaluateAsync(
                        _loadedHistoryLua,
                        redisKeys,
                        redisArgvs).ConfigureAwait(false);

                    if (result == 0)
                    {
                        //还没有数据,等会吧
                        _logger.LogTrace("ScanHistory {InstanceName} 中,还没有数据,,EventType:{eventType}", _instanceSetting.InstanceName, _eventType);
                        await Task.Delay(10 * 1000, cancellationToken).ConfigureAwait(false);
                    }
                    else if (result == 1)
                    {
                        //时间太早,等会再检查
                        _logger.LogTrace("ScanHistory {InstanceName} 中,数据还太新,一会再检查,,EventType:{eventType}", _instanceSetting.InstanceName, _eventType);
                        await Task.Delay(10 * 1000, cancellationToken).ConfigureAwait(false);
                    }
                    else if (result == 2)
                    {
                        //成功
                        _logger.LogTrace("ScanHistory {InstanceName} 中,消息已被处理,现在移出History,EventType:{eventType}", _instanceSetting.InstanceName, _eventType);
                    }
                    else if (result == 3)
                    {
                        //重新放入队列再发送
                        _logger.LogWarning("ScanHistory {InstanceName} 中,消息可能被遗漏, 重新放入队列,,EventType:{eventType}", _instanceSetting.InstanceName, _eventType);
                    }
                    else
                    {
                        //出错
                    }
                }
                catch (RedisServerException ex) when(ex.Message.StartsWith("NOSCRIPT", StringComparison.InvariantCulture))
                {
                    _logger.LogError(ex, "NOSCRIPT, will try again.");

                    InitLodedLua();

                    continue;
                }
                catch (RedisConnectionException ex)
                {
                    _logger.LogError(ex, "Scan History 中出现Redis链接问题. {EventType}", _eventType);
                    await Task.Delay(5000, cancellationToken).ConfigureAwait(false);
                }
                catch (RedisTimeoutException ex)
                {
                    _logger.LogError(ex, "Scan History 中出现Redis超时问题. {EventType}", _eventType);
                }
                catch (Exception ex)
                {
                    _logger.LogCritical(ex, "Scan History 出现未知问题. {EventType}", _eventType);
                }
            }

            _logger.LogTrace("History Task For {eventType} Stopped.", _eventType);
        }
示例#12
0
 internal static IDatabase GetDatabase(RedisInstanceSetting redisInstanceSetting, ILogger logger)
 {
     return(RedisInstanceManager.GetDatabase(redisInstanceSetting, logger));
 }
示例#13
0
 internal static async Task <IDatabase> GetDatabaseAsync(RedisInstanceSetting redisInstanceSetting, ILogger logger)
 {
     return(await RedisInstanceManager.GetDatabaseAsync(redisInstanceSetting, logger).ConfigureAwait(false));
 }