public void ArraysWithSameContentHaveSameHashCode() { var array1 = new RedisArray(new RedisInteger(1), new RedisInteger(2), new RedisInteger(3)); var array2 = new RedisArray(new RedisInteger(1), new RedisInteger(2), new RedisInteger(3)); Assert.Equal(array1.GetHashCode(), array2.GetHashCode()); }
/// <summary> /// 返回给定的有序集合键 <paramref name="key"/> 中,值介于 <paramref name="min"/> 和 <paramref name="max"/> 之间从低到高的顺序的成员。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">有序集的键名</param> /// <param name="min">最小成员值。可以为 null 值,表示负无限。</param> /// <param name="max">最大成员值。可以为 null 值,表示正无限。</param> /// <param name="exclusiveMin">指示最小是否为开区间(true 时表示不含最小值)。</param> /// <param name="exclusiveMax">指示最大值是否为开区间(true 时表示不含最大值)。</param> /// <param name="offset">返回结果的偏移量。</param> /// <param name="count">返回结果的数量。</param> /// <returns>返回一个从低到高的顺序列表,列表里面包含了有序集合在指定范围内的成员。</returns> public static BinaryValue[] ZRangeByLex(this IRedisClient client, string key , BinaryValue min, BinaryValue max , bool exclusiveMin = false, bool exclusiveMax = false , long?offset = null, long?count = null) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } IEnumerable <object> args = new object[] { key , RedisArgs.GetBinaryValue(min, exclusiveMin, "-") , RedisArgs.GetBinaryValue(max, exclusiveMax, "+") }; if (offset.HasValue && count.HasValue) { args = RedisArgs.ConcatAll(args, new[] { "LIMIT", offset.Value.ToString(), count.Value.ToString() }); } return(client.Execute(RedisArray.Create(new RedisValue("ZRANGEBYLEX", args.ToArray())))); }
/// <summary> /// 返回给定列表、集合、有序集合 key 中经过排序的元素。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">键名。</param> /// <param name="by">按其元素来排序。</param> /// <param name="offset">指定要跳过的元素数量。</param> /// <param name="count">指定跳过 <paramref name="offset"/> 个指定的元素之后,要返回多少个对象。</param> /// <param name="sort">排序方式。</param> /// <param name="alpha">表示对字符串进行排序。</param> /// <param name="get">根据排序的结果来取出相应的键值列表。</param> /// <returns>返回列表形式的排序结果。</returns> public static BinaryValue[] Sort(this IRedisClient client , string key, string by = null , long?offset = null, long?count = null , RedisSort?sort = null , bool?alpha = null , params string[] get) { List <string> args = new List <string>(); args.Add(key); if (by != null) { args.AddRange(new[] { "BY", by }); } if (offset.HasValue && count.HasValue) { args.AddRange(new[] { "LIMIT", offset.Value.ToString(), count.Value.ToString() }); } foreach (var pattern in get) { args.AddRange(new[] { "GET", pattern }); } if (sort.HasValue) { args.Add(sort.ToString().ToUpperInvariant()); } if (alpha.HasValue && alpha.Value) { args.Add("ALPHA"); } return(client.Execute(RedisArray.Create(new RedisValue("SORT", args.ToArray())))); }
private async ValueTask <RedisObject> Execute(Connection connection, RedisArray commandData, IBufferPool <byte> bufferPool) { var retryDelay = _config.LoadingRetryDelayMin; var retryTimeoutTime = MonotonicTime.Now + _config.LoadingRetryTimeout; while (true) { try { RedisObject result; try { ProtocolHandler.Write(connection.Output, commandData); await connection.Output.FlushAsync(); result = await ProtocolHandler.Read(connection.Input, bufferPool); } catch (Exception e) { if (WrapException(connection, e, out var redisException)) { throw redisException; } throw; } return(CheckError(result)); } catch (RedisClientException e) { if (e.Type == KnownRedisErrors.NoScript) { await Scripts.ReUploadAll(); continue; } // Right after start Redis server accepts connections immediately // but still not operation by some time while loading database // So it always returns error in response until fully loaded if (e.Type != KnownRedisErrors.Loading || MonotonicTime.Now > retryTimeoutTime) { throw; } await Task.Delay(retryDelay); retryDelay = retryDelay.Multiply(2); if (retryDelay > _config.LoadingRetryDelayMax) { retryDelay = _config.LoadingRetryDelayMax; } } } }
protected override string PackageCommand(string commandName, params string[] args) { BulkString[] cmd = new BulkString[args.Length + 1]; cmd[0] = new BulkString(commandName); for (int i = 0; i < args.Length; i++) { cmd[i + 1] = new BulkString(args[i]); } return(RedisArray.Package(cmd)); }
public void ArraysWithDifferentContentAreNotEqual() { var array1 = new RedisArray(new RedisInteger(1), new RedisInteger(2), new RedisInteger(3)); var array2 = new RedisArray(new RedisInteger(3), new RedisInteger(2), new RedisInteger(1)); Assert.False(array1.Equals(array2)); Assert.False(array2.Equals(array1)); Assert.True(array1 != array2); Assert.True(array2 != array1); }
private static List <TItem> CreateList <TItem>(RedisArray value) { var items = value.Items; var result = new List <TItem>(items.Count); foreach (var item in items) { result.Add(item.To <TItem>()); } return(result); }
public void ArraysWithSameContentAreEqual() { var array1 = new RedisArray(new RedisInteger(1), new RedisInteger(2), new RedisInteger(3)); var array2 = new RedisArray(new RedisInteger(1), new RedisInteger(2), new RedisInteger(3)); Assert.True(array1.Equals(array2)); Assert.True(array2.Equals(array1)); Assert.True(array1 == array2); Assert.True(array2 == array1); }
private static TItem[] CreateArray <TItem>(RedisArray value) { var items = value.Items; var result = new TItem[items.Count]; for (var i = 0; i < items.Count; ++i) { result[i] = items[i].To <TItem>(); } return(result); }
/// <summary> /// 查找所有符合给定模式 <paramref name="pattern"/> 的键 。 /// <para>KEYS 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的键,你最好还是用 Redis 的集合结构(set)来代替。</para> /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="pattern">模式表达式。 /// <para>1、KEYS * 匹配数据库中所有 key 。</para> /// <para>2、KEYS h?llo 匹配 hello ,hallo 和 hxllo 等。</para> /// <para>3、KEYS h*llo 匹配 hllo 和 heeeeello 等。</para> /// <para>4、KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。</para> /// <para>5、特殊符号用 \ 隔开。</para> /// </param> /// <returns>返回符合给定模式的键列表。</returns> public static string[] Keys(this IRedisClient client, string pattern) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(pattern)) { throw new ArgumentNullException("pattern"); } return(client.Execute(RedisArray.Create(new RedisString("KEYS", pattern)))); }
/// <summary> /// 查找哈希表 <paramref name="key"/> 所有的域名。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">键名</param> /// <returns> <paramref name="key"/> 所有的域名。当 <paramref name="key"/> 不存在时,返回一个空数组。</returns> public static string[] HKeys(this IRedisClient client, string key) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } return(client.Execute(RedisArray.Create(new RedisString("HKEYS", key)))); }
/// <summary> /// 取得运行中的 Redis 服务器的配置参数。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="parameter">搜索关键字,查找所有匹配的配置参数。</param> /// <returns>给定配置参数和值。</returns> public static RedisKeyItem[] ConfigGet(this IRedisClient client, string parameter) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(parameter)) { throw new ArgumentNullException(nameof(parameter)); } return(client.Execute(RedisArray.Create(new RedisItem <RedisKeyItem>(false, "CONFIG GET", parameter), 2))); }
/// <summary> /// 查找哈希表 <paramref name="key"/> 所有的域值。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">键名</param> /// <returns> <paramref name="key"/> 所有的域值。当 <paramref name="key"/> 不存在时,返回一个空数组。</returns> public static BinaryValue[] HVals(this IRedisClient client, string key) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } return(client.Execute(RedisArray.Create(new RedisValue("HVALS", key)))); }
/// <summary> /// 返回有序集 <paramref name="key"/> 中,指定区间内的成员(含成员的权重值)。 /// <para>1、其中成员的位置按权重值递减(从大到小)来排列。</para> /// <para>2、具有相同权重值的成员按字典序的逆序(reverse lexicographical order)排列。</para> /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">有序集的键名。</param> /// <param name="start">开始索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <param name="stop">结束索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <returns>返回指定区间内的有序集成员(含成员的权重值)的列表。</returns> public static RedisScoreItem[] ZRevRangeWithScores(this IRedisClient client, string key, long start, long stop) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } return(client.Execute(RedisArray.Create(new RedisItem <RedisScoreItem>(false, "ZREVRANGE", key, start, stop, "WITHSCORES"), 2))); }
/// <summary> /// 返回列表 <paramref name="key"/> 中指定区间内的元素,区间以偏移量 <paramref name="start"/> 和 <paramref name="stop"/> 指定。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">列表的键名。</param> /// <param name="start">开始索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <param name="stop">结束索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <returns>包含指定区间内的元素。</returns> public static BinaryValue[] LRange(this IRedisClient client, string key, long start, long stop) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } return(client.Execute(RedisArray.Create(new RedisValue("LRANGE", key, start, stop)))); }
/// <summary> /// 返回集合中的一组随机成员。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">集合的键名。</param> /// <param name="count">数组的长度。 /// <para>1、如果 <paramref name="count"/> 为正数,且小于集合基数,那么命令返回一个包含 <paramref name="count"/> 个元素的数组,数组中的元素各不相同。如果 <paramref name="count"/> 大于等于集合基数,那么返回整个集合。</para> /// <para>2、如果 <paramref name="count"/> 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 <paramref name="count"/> 的绝对值。</para> /// </param> /// <returns>一组的随机成员。当 <paramref name="key"/> 不存在或 <paramref name="key"/> 是空集时,返回空数组。</returns> public static BinaryValue[] SRandMember(this IRedisClient client, string key, long count) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } return(client.Execute(RedisArray.Create(new RedisValue("SRANDMEMBER", key, count)))); }
/// <summary> /// 返回有序集 <paramref name="key"/> 中,指定区间内的成员。 /// <para>1、其中成员的位置按权重值递减(从大到小)来排列。</para> /// <para>2、具有相同权重值的成员按字典序的逆序(reverse lexicographical order)排列。</para> /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">有序集的键名。</param> /// <param name="start">开始索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <param name="stop">结束索引(含)。负数偏移量表示从值最后开始计数,-1 表示最后一个,-2 表示倒数第二个,以此类推。</param> /// <returns>返回指定区间内的有序集成员的列表。</returns> public static BinaryValue[] ZRevRange(this IRedisClient client, string key, long start, long stop) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } return(client.Execute(RedisArray.Create(new RedisValue("ZREVRANGE", key, start, stop)))); }
/// <summary> /// 返回哈希表 <paramref name="key"/> 中所有的域和值。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">哈希表的键名。</param> /// <returns> <paramref name="key"/> 所有的域和值。</returns> public static RedisFieldItem[] HGetAll(this IRedisClient client, string key) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } return(client.Execute(RedisArray.Create(new RedisItem <RedisFieldItem>(false, "HGETALL", key), 2))); }
/// <summary> /// 返回一个集合的全部成员。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">集合的键名。</param> /// <returns>返回一个集合的所有成员。</returns> public static BinaryValue[] SMembers(this IRedisClient client, string key) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } return(client.Execute(RedisArray.Create(new RedisValue("SMEMBERS", key)))); }
private static HashSet <TItem> CreateSet <TItem>(RedisArray value) { var items = value.Items; #if NETSTANDARD2_0 var result = new HashSet <TItem>(); #else var result = new HashSet <TItem>(items.Count); #endif foreach (var item in items) { result.Add(item.To <TItem>()); } return(result); }
/// <summary> /// 返回一个或多个键的值。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="keys">键的数组。</param> /// <returns>返回值的数组。如果给定的键里面,有某个键不存在,那么这个键对应的值为 null 值 。</returns> public static BinaryValue[] MGet(this IRedisClient client, params string[] keys) { if (client == null) { throw new ArgumentNullException("client"); } if (keys == null) { throw new ArgumentNullException("keys"); } if (keys.Length == 0) { return(new BinaryValue[0]); } return(client.Execute(RedisArray.Create(new RedisValue("MGET", keys)))); }
/// <summary> /// 给定一个或多个脚本的 SHA1 校验和,表示校验和所指定的脚本是否已经被保存在缓存当中。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="scripts">sha1 校验码列表。</param> /// <returns>返回一个数组。脚本已经被保存在缓存当中为 true,否则为 false。</returns> public static bool[] ScriptExists(this IRedisClient client, params string[] scripts) { if (client == null) { throw new ArgumentNullException("client"); } if (scripts == null) { throw new ArgumentNullException("scripts"); } if (scripts.Length == 0) { return(new bool[0]); } return(client.Execute(RedisArray.Create(new RedisBoolean("SCRIPT EXISTS", scripts)))); }
/// <summary> /// 返回一个集合的全部成员,该集合是所有给定集合之间的差集。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="keys">集合的键名数组。</param> /// <returns>包含差集成员列表。</returns> public static BinaryValue[] SDiff(this IRedisClient client, params string[] keys) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (keys == null) { throw new ArgumentNullException(nameof(keys)); } if (keys.Length == 0) { return(new BinaryValue[0]); } return(client.Execute(RedisArray.Create(new RedisValue("SDIFF", keys)))); }
private async Task WriteAsync(RedisArray value, CancellationToken cancellationToken) { var header = DefaultEncoding.GetBytes($"{RedisType.Array.Prefix()}{value.Length}"); await _stream.WriteAsync(header, 0, header.Length, cancellationToken); await _stream.WriteAsync(EncodedNewLine, 0, EncodedNewLine.Length, cancellationToken); if (value == RedisArray.Null) { return; } foreach (var element in value.Value) { await WriteAsync(element, cancellationToken); } }
/// <summary> /// 返回有序集 <paramref name="key"/> 中,权重值在 <paramref name="min"/> 和 <paramref name="max"/> 之间的成员。 /// <para>1、其中成员的位置按权重值递减(从大到小)来排列。</para> /// <para>2、具有相同权重值的成员按字典序的逆序(reverse lexicographical order)排列。</para> /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">有序集的键名。</param> /// <param name="min">权重最小值。<paramref name="min"/> 可以是 <see cref="Double.MinValue"/> -或- <see cref="Double.NegativeInfinity"/>,表示有序集的最小值。</param> /// <param name="max">权重最大值。<paramref name="max"/> 可以是 <see cref="Double.MaxValue"/> -或- <see cref="Double.PositiveInfinity"/>,表示有序集的最高值。</param> /// <param name="exclusiveMin">指示最小值是否为开区间(true 时表示不含最小值)。</param> /// <param name="exclusiveMax">指示最大值是否为开区间(true 时表示不含最大值)。</param> /// <param name="offset">返回结果的偏移量。</param> /// <param name="count">返回结果的数量。</param> /// <returns>权重值包含指定区间的成员。</returns> public static BinaryValue[] ZRevRangeByScore(this IRedisClient client, string key, double min, double max , bool exclusiveMin = false, bool exclusiveMax = false , long?offset = null, long?count = null) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } IEnumerable <object> args = new object[] { key, RedisArgs.GetScore(min, exclusiveMin), RedisArgs.GetScore(max, exclusiveMax) }; if (offset.HasValue && count.HasValue) { args = RedisArgs.ConcatAll(args, new[] { "LIMIT", offset.Value.ToString(), count.Value.ToString() }); } return(client.Execute(RedisArray.Create(new RedisValue("ZREVRANGEBYSCORE", args.ToArray())))); }
/// <summary> /// 返回有序集 <paramref name="key"/> 中,权重值在 <paramref name="min"/> 和 <paramref name="max"/> 之间的成员(含成员的权重值)。 /// <para>1、其中成员的位置按权重值递减(从大到小)来排列。</para> /// <para>2、具有相同权重值的成员按字典序的逆序(reverse lexicographical order)排列。</para> /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">有序集的键名。</param> /// <param name="min">权重最小值。<paramref name="min"/> 可以是 <see cref="System.Double.MinValue"/> -或- <see cref="System.Double.NegativeInfinity"/>,表示有序集的最小值。</param> /// <param name="max">权重最大值。<paramref name="max"/> 可以是 <see cref="System.Double.MaxValue"/> -或- <see cref="System.Double.PositiveInfinity"/>,表示有序集的最高值。</param> /// <param name="exclusiveMin">指示最小值是否为开区间(true 时表示不含最小值)。</param> /// <param name="exclusiveMax">指示最大值是否为开区间(true 时表示不含最大值)。</param> /// <param name="offset">返回结果的偏移量。</param> /// <param name="count">返回结果的数量。</param> /// <returns>返回权重值包含指定区间的成员(含成员的权重值)。</returns> public static RedisScoreItem[] ZRevRangeByScoreWithScores(this IRedisClient client, string key, double min, double max , bool exclusiveMin = false, bool exclusiveMax = false , long?offset = null, long?count = null) { if (client == null) { throw new ArgumentNullException("client"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } IEnumerable <object> args = new object[] { key, RedisArgs.GetScore(min, exclusiveMin), RedisArgs.GetScore(max, exclusiveMax), "WITHSCORES" }; if (offset.HasValue && count.HasValue) { args = RedisArgs.ConcatAll(args, new[] { "LIMIT", offset.Value.ToString(), count.Value.ToString() }); } return(client.Execute(RedisArray.Create(new RedisItem <RedisScoreItem>(false, "ZREVRANGEBYSCORE", args.ToArray()), 2))); }
public static RedisIsMasterDownInfo Parse(RedisArray array) { var result = new RedisIsMasterDownInfo(); if (!ReferenceEquals(array, null)) { var items = array.Value; if (items != null) { var count = items.Count; if (count > 0) { var item = items[0]; if (!ReferenceEquals(item, null) && item.Type == RedisResultType.Integer) { result.IsDown = ((RedisInteger)item).Value == RedisConstants.One; if (count > 1) { item = items[1]; if (!ReferenceEquals(item, null) && item.Type == RedisResultType.Bytes) { result.LeaderRunId = ((RedisBytes)item).Value.ToUTF8String() ?? "*"; if (count > 2) { item = items[2]; if (!ReferenceEquals(item, null) && item.Type == RedisResultType.Integer) { result.LeaderEpoch = ((RedisInteger)item).Value; } } } } } } } } return(result); }
/// <summary> /// 返回哈希表 <paramref name="key"/> 中一个或多个域的值。 /// </summary> /// <param name="client">Redis 客户端。</param> /// <param name="key">键名</param> /// <param name="fields">哈希表域的数组。</param> /// <returns>值的数组。如果给定的域里面,有某个域不存在,那么这个域对应的值为 null 值。</returns> public static BinaryValue[] HMGet(this IRedisClient client, string key, params string[] fields) { if (client == null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(nameof(key)); } if (fields == null) { throw new ArgumentNullException(nameof(fields)); } if (fields.Length == 0) { return(new BinaryValue[0]); } var args = RedisArgs.ConcatFirst(key, fields).ToArray(); return(client.Execute(RedisArray.Create(new RedisValue("HMGET", args)))); }
protected override void ParseInfo(RedisArray array) { if (!ReferenceEquals(array, null)) { var list = array.Value; if (list != null) { var count = list.Count; if (count > 1) { var item = list[1]; if (!ReferenceEquals(item, null) && item.Type == RedisResultType.Bytes) { IPAddress = ((RedisBytes)item).Value.ToUTF8String(); } if (count > 2) { item = list[2]; if (!ReferenceEquals(item, null)) { if (item.Type == RedisResultType.Integer) { Port = (int)((RedisInteger)item).Value; } else if (item.Type == RedisResultType.Bytes) { var data = ((RedisBytes)item).Value.ToUTF8String(); if (!string.IsNullOrEmpty(data)) { long l; if (data.TryParse(out l)) { Port = (int)l; } } } } if (count > 3) { item = list[3]; if (!ReferenceEquals(item, null) && item.Type == RedisResultType.Bytes) { State = ((RedisBytes)item).Value.ToUTF8String(); } if (count > 4) { item = list[4]; if (!ReferenceEquals(item, null)) { if (item.Type == RedisResultType.Integer) { DataReceived = ((RedisInteger)item).Value; } else if (item.Type == RedisResultType.Bytes) { var data = ((RedisBytes)item).Value.ToUTF8String(); if (!string.IsNullOrEmpty(data)) { long l; if (data.TryParse(out l)) { DataReceived = l; } } } } } } } } } } }
public RedisTransaction(RedisConnector connector) { _connector = connector; _execCommand = RedisCommands.Exec(); }