public void Close() { foreach (var kv in _instanceSettingDict) { RedisInstanceManager.Close(kv.Value); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
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) }; }
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; } }
/// <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; } }
private void InitLodedLua() { IServer server = RedisInstanceManager.GetServer(_instanceSetting, _logger); _loadedHistoryLua = server.ScriptLoad(_hISTORY_REDIS_SCRIPT); }
/// <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); } } }
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); }
internal static IDatabase GetDatabase(RedisInstanceSetting redisInstanceSetting, ILogger logger) { return(RedisInstanceManager.GetDatabase(redisInstanceSetting, logger)); }
internal static async Task <IDatabase> GetDatabaseAsync(RedisInstanceSetting redisInstanceSetting, ILogger logger) { return(await RedisInstanceManager.GetDatabaseAsync(redisInstanceSetting, logger).ConfigureAwait(false)); }