private StackRedis.RedisResult Eval(ScriptType scriptType, StackRedis.RedisKey redisKey, StackRedis.RedisValue[] values = null, StackRedis.CommandFlags flags = StackRedis.CommandFlags.None) { if (!this.scriptsLoaded) { lock (this.loadScriptLock) { if (!this.scriptsLoaded) { this.LoadScripts(); this.scriptsLoaded = true; } } } StackRedis.LoadedLuaScript script; if (!this.shaScripts.TryGetValue(scriptType, out script)) { throw new InvalidOperationException("Something went wrong during loading scripts to the server."); } try { return(this.Database.ScriptEvaluate(script.Hash, new[] { redisKey }, values, flags)); } catch (StackRedis.RedisServerException ex) when(ex.Message.StartsWith("NOSCRIPT", StringComparison.OrdinalIgnoreCase)) { this.LoadScripts(); // retry throw; } }
private StackRedis.RedisResult Eval(ScriptType scriptType, StackRedis.RedisKey redisKey, StackRedis.RedisValue[] values = null, StackRedis.CommandFlags flags = StackRedis.CommandFlags.None) { if (!this.scriptsLoaded) { lock (this.lockObject) { if (!this.scriptsLoaded) { this.LoadScripts(); this.scriptsLoaded = true; } } } StackRedis.LoadedLuaScript script; if (!this.shaScripts.TryGetValue(scriptType, out script)) { this.Logger.LogCritical("Something is wrong with the Lua scripts. Seem to be not loaded."); this.scriptsLoaded = false; throw new InvalidOperationException("Something is wrong with the Lua scripts. Seem to be not loaded."); } try { return(this.connection.Database.ScriptEvaluate(script.Hash, new[] { redisKey }, values, flags)); } catch (StackRedis.RedisServerException ex) when(ex.Message.StartsWith("NOSCRIPT", StringComparison.OrdinalIgnoreCase)) { this.Logger.LogInfo("Received NOSCRIPT from server. Reloading scripts..."); this.LoadScripts(); // retry throw; } }
public CommandKeyValueValueValueMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue value0, RedisValue value1, RedisValue value2) : base(db, flags, command, key) { value0.AssertNotNull(); value1.AssertNotNull(); value2.AssertNotNull(); this.value0 = value0; this.value1 = value1; this.value2 = value2; }
public CommandKeyValuesMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue[] values) : base(db, flags, command, key) { for (int i = 0; i < values.Length; i++) { values[i].AssertNotNull(); } this.values = values; }
public CommandKeyValueMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue value) : base(db, flags, command, key) { value.AssertNotNull(); this.value = value; }
public CommandKeyMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key) : base(db, flags, command, key) { }
public CommandKeyKeysMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisKey[] keys) : base(db, flags, command, key) { for (int i = 0; i < keys.Length; i++) { keys[i].AssertNotNull(); } this.keys = keys; }
/// <summary> /// Create a key associated with a value that is obtained by deserializing the provided serialized value (obtained via DUMP). /// If ttl is 0 the key is created without any expire, otherwise the specified expire time(in milliseconds) is set. /// </summary> /// <param name="key">The key to restore.</param> /// <param name="value">The value of the key.</param> /// <remarks>https://redis.io/commands/restore</remarks> public Task RestoreAsync(StackExchange.Redis.RedisKey key, byte[] value) { return(RedisDb.KeyRestoreAsync(KeyName, value)); }
internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key0, RedisValue[] values, RedisKey key1) { if (values == null) { throw new ArgumentNullException("values"); } return(new CommandKeyValuesKeyMessage(db, flags, command, key0, values, key1)); }
internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue[] values) { if (values == null) { throw new ArgumentNullException("values"); } switch (values.Length) { case 0: return(new CommandKeyMessage(db, flags, command, key)); case 1: return(new CommandKeyValueMessage(db, flags, command, key, values[0])); case 2: return(new CommandKeyValueValueMessage(db, flags, command, key, values[0], values[1])); case 3: return(new CommandKeyValueValueValueMessage(db, flags, command, key, values[0], values[1], values[2])); case 4: return(new CommandKeyValueValueValueValueMessage(db, flags, command, key, values[0], values[1], values[2], values[3])); default: return(new CommandKeyValuesMessage(db, flags, command, key, values)); } }
internal static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisKey[] keys) { switch (keys.Length) { case 0: return(new CommandKeyMessage(db, flags, command, key)); case 1: return(new CommandKeyKeyMessage(db, flags, command, key, keys[0])); case 2: return(new CommandKeyKeyKeyMessage(db, flags, command, key, keys[0], keys[1])); default: return(new CommandKeyKeysMessage(db, flags, command, key, keys)); } }
public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisValue value, RedisKey key) { return(new CommandValueKeyMessage(db, flags, command, value, key)); }
public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key, RedisValue value0, RedisValue value1, RedisValue value2, RedisValue value3) { return(new CommandKeyValueValueValueValueMessage(db, flags, command, key, value0, value1, value2, value3)); }
public static Message Create(int db, CommandFlags flags, RedisCommand command, RedisKey key0, RedisKey key1, RedisKey key2) { return(new CommandKeyKeyKeyMessage(db, flags, command, key0, key1, key2)); }
/// <summary> /// Serialize the value stored at key in a Redis-specific format and return it to the user. The returned value can be synthesized back into a Redis key using the RESTORE command. /// </summary> /// <param name="key">The key to dump.</param> /// <returns>the serialized value.</returns> /// <remarks>https://redis.io/commands/dump</remarks> public Task <byte[]> DumpAsync(StackExchange.Redis.RedisKey key) { return(RedisDb.KeyDumpAsync(KeyName)); }
internal void AutoConfigure(PhysicalConnection connection) { if (serverType == ServerType.Twemproxy) { // don't try to detect configuration; all the config commands are disabled, and // the fallback master/slave detection won't help return; } var commandMap = Multiplexer.CommandMap; #pragma warning disable CS0618 const CommandFlags flags = CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect; #pragma warning restore CS0618 var features = GetFeatures(); Message msg; #pragma warning disable CS0618 if (commandMap.IsAvailable(RedisCommand.CONFIG)) { if (Multiplexer.RawConfig.KeepAlive <= 0) { msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.timeout); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); } msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.slave_read_only); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.databases); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); } if (commandMap.IsAvailable(RedisCommand.INFO)) { lastInfoReplicationCheckTicks = Environment.TickCount; if (features.InfoSections) { msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.replication); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.server); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); } else { msg = Message.Create(-1, flags, RedisCommand.INFO); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); } } else if (commandMap.IsAvailable(RedisCommand.SET)) { // this is a nasty way to find if we are a slave, and it will only work on up-level servers, but... RedisKey key = Multiplexer.UniqueId; msg = Message.Create(0, flags, RedisCommand.SET, key, RedisLiterals.slave_read_only, RedisLiterals.PX, 1, RedisLiterals.NX); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.AutoConfigure); } if (commandMap.IsAvailable(RedisCommand.CLUSTER)) { msg = Message.Create(-1, flags, RedisCommand.CLUSTER, RedisLiterals.NODES); msg.SetInternalCall(); WriteDirectOrQueueFireAndForgetSync(connection, msg, ResultProcessor.ClusterNodes); } #pragma warning restore CS0618 }
/// <summary> /// 锁住可用的资源,此方法是发布订阅模式,性能较好,推荐使用 /// </summary> /// <param name="connectionMultiplexer">连接转换器,此处的连接器必须是可写的DB</param> /// <param name="key">键</param> /// <param name="action">动作</param> /// <param name="dbIndex">数据库索引</param> /// <param name="timeoutMilliSecond">超时毫秒,默认为5秒</param> /// <param name="flags">命令标记</param> public static void LockTake(this IConnectionMultiplexer connectionMultiplexer, RedisKey key, Action action, int dbIndex = -1, int timeoutMilliSecond = 5000, CommandFlags flags = CommandFlags.None) { var channel = StringUtil.NewShortGuid(); var subscriber = connectionMultiplexer.GetSubscriber(); var db = connectionMultiplexer.GetDatabase(dbIndex); // 将进入的都加入到队列里,将频道唯一值作为队列值 var count = db.ListLeftPush(key, channel, flags: flags); // 如果大于1,说明已经被其他地方锁定资源,需要监听等待触发释放锁 if (count > 1) { // 线程互斥对象 var auto = new AutoResetEvent(false); // 是否已执行业务 var isExecuted = false; subscriber.SubscribeAsync(channel, (myChannel, channelValue) => { if (isExecuted) { subscriber.UnsubscribeAsync(channel, flags: flags); return; } isExecuted = true; subscriber.UnsubscribeAsync(channel, flags: flags); auto.Set(); ExecLockAction(subscriber, db, key, action, flags); }, flags: flags); // 等待超时,如果超时后还未执行,则手动执行,预防死锁 auto.WaitOne(timeoutMilliSecond); if (isExecuted) { return; } else { isExecuted = true; // 移除队列的元素 db.ListRemoveAsync(key, channel, flags: flags); subscriber.UnsubscribeAsync(channel, flags: flags); ExecLockAction(subscriber, db, key, action, flags); } } else { // 排除第1个队列值 db.ListRightPop(key, flags: flags); ExecLockAction(subscriber, db, key, action, flags); } }
public CommandKeyBase(int db, CommandFlags flags, RedisCommand command, RedisKey key) : base(db, flags, command) { key.AssertNotNull(); this.Key = key; }
public CommandKeyKeyMessage(int db, CommandFlags flags, RedisCommand command, RedisKey key0, RedisKey key1) : base(db, flags, command, key0) { key1.AssertNotNull(); this.key1 = key1; }
public ServerEndPoint Select(int db, RedisCommand command, RedisKey key, CommandFlags flags) { int slot = serverType == ServerType.Cluster ? HashSlot(key) : NoSlot; return(Select(slot, command, flags)); }