/// <summary> /// 获取键键值列表 /// </summary> /// <param name="keys"></param> /// <returns></returns> public byte[][] GetByteKeys(params string[] keys) { if (keys.Length == 0) { throw new ArgumentException("keys"); } using (var redisWriter = new RedisWriter(this, keys.Length + 1, "MGET")) { foreach (var key in keys) { redisWriter.WriteArgument(key); } this.Connection.SendCommand(redisWriter); } return(this.Connection.ExpectMultiBulkReply()); }
/// <summary> /// 设置当前要操作的DB /// </summary> /// <param name="dbIndex"></param> /// <returns></returns> public bool Select(int dbIndex) { //SET key value using (var redisWriter = new RedisWriter(this, 2, "SELECT")) { redisWriter.WriteArgument(dbIndex.ToString()); this.Connection.SendCommand(redisWriter); } var result = this.Connection.ExpectSuccess(); if (result) { this.db = dbIndex; } return(result); }
/// <summary> /// 在指定位置添加元素 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="before">元素前后,true before,false after</param> /// <param name="pivot">位置元素</param> /// <returns>添加后元素数</returns> public int LInsert(string key, string value, string pivot, bool before) { //Integer reply: the length of the list after the insert operation, or -1 when the value pivot was not found. //LINSERT mylist BEFORE "World" "There" //LINSERT key BEFORE|AFTER pivot value using (var w = new RedisWriter(this.client, 5, "LINSERT")) { w.WriteArgument(key); w.WriteArgument(before ? "BEFORE" : "AFTER"); w.WriteArgument(pivot); w.WriteArgument(value); this.connection.SendCommand(w); } return(this.connection.ExpectInt()); }
/// <summary> /// 自加一个数值 /// </summary> /// <param name="key"></param> /// <param name="count"></param> /// <returns></returns> public int Increment(string key, int count) { if (key == null) { throw new ArgumentNullException("key"); } using (var redisWriter = new RedisWriter(this, 3, "INCRBY")) { redisWriter.WriteArgument(key); redisWriter.WriteArgument(count.ToString()); this.Connection.SendCommand(redisWriter); } return(this.Connection.ExpectInt()); }
/// <summary> /// 获取所有键列表 /// </summary> public string[] GetKeys() { using (var redisWriter = new RedisWriter(this, 2, "KEYS")) { redisWriter.WriteArgument("*"); this.Connection.SendCommand(redisWriter); } var keys = this.Connection.ExpectToStringArray(); return(keys); //var r = this.Connection.ExpectBulkReply(); //if (r.Length == 0) // return new string[0]; //return this.Encoding.GetString(r).Split(' '); }
/// <summary> /// 返回多个集合差集 /// </summary> /// <param name="keys"></param> /// <returns></returns> public string[] SDIFF(params string[] keys) { if (keys.Length == 0) { throw new ArgumentNullException("keys"); } using (var w = new RedisWriter(this.client, keys.Length + 1, "SDIFF")) { foreach (var key in keys) { w.WriteArgument(key); } this.connection.SendCommand(w); } return(this.connection.ExpectToStringArray(this.connection.ExpectMultiBulkReply())); }
/// <summary> /// 删除一批键 /// </summary> /// <param name="keys"></param> /// <returns>返回删除的个数</returns> public int Remove(params string[] keys) { if (keys == null) { throw new ArgumentNullException("args"); } using (var redisWriter = new RedisWriter(this, keys.Length + 1, "DEL")) { foreach (var key in keys) { redisWriter.WriteArgument(key); } this.Connection.SendCommand(redisWriter); } return(this.Connection.ExpectInt()); }
//public void SendCommand(string cmd, params object[] args) //{ // var s = args.Length > 0 ? String.Format(cmd, args) : cmd; // byte[] r = this.client.Encoding.GetBytes(s); // try // { // this.socket.Send(r); // } // catch (SocketException) // { // // timeout; // socket.Close(); // socket = null; // throw new IOException("Unable to connect"); // } //} public void SendCommand(RedisWriter redisWriter) { var data = redisWriter.GetBuffer(); var count = (int)redisWriter.Length; try { this.socket.Send(data, 0, count, SocketFlags.None); } catch (SocketException) { // timeout; socket.Close(); socket = null; throw new IOException("Unable to connect"); } }
/// <summary> /// 设置一组数据(MSET) /// </summary> /// <param name="dict"></param> public bool Set(IDictionary <string, byte[]> dict) { if (dict == null) { throw new ArgumentNullException("dict"); } //MSET key1 value1 key2 value2 using (var w = new RedisWriter(this, dict.Count * 2 + 1, "MSET")) { foreach (var item in dict) { w.WriteArgument(item.Key); w.WriteArgument(item.Value); } this.Connection.SendCommand(w); } return(this.Connection.ExpectSuccess()); }
/// <summary> /// 返回给定的分值范围元素列表 /// </summary> /// <param name="key"></param> /// <param name="min"></param> /// <param name="max"></param> /// <param name="offset">取出偏移量,需设置count有效</param> /// <param name="count">设置数量则offset有产效</param> /// <returns></returns> public SortedList <double, string> ZRANGEBYSCORE(string key, double min, double max, int offset, int count) { //ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] var size = 5; if (count > 0) { size += 3; } using (var w = new RedisWriter(this.client, size, "ZRANGEBYSCORE")) { w.WriteArgument(key); w.WriteArgument(min.ToString()); w.WriteArgument(max.ToString()); w.WriteArgument("WITHSCORES"); if (count > 0) { w.WriteArgument("LIMIT"); w.WriteArgument(offset.ToString()); w.WriteArgument(count.ToString()); } this.connection.SendCommand(w); } var b = this.connection.ExpectMultiBulkReply(); if (b.Length < 2) { return(new SortedList <double, string>(0)); } var r = new SortedList <double, string>(b.Length / 2); var d = 0d; for (int i = 0, l = b.Length; i < l; i += 2) { double.TryParse(this.client.Encoding.GetString(b[i + 1]), out d); r[d] = this.client.Encoding.GetString(b[i]); } return(r); }
/// <summary> /// 重命名一个键 /// </summary> /// <param name="oldKeyname"></param> /// <param name="newKeyname"></param> /// <returns></returns> public bool Rename(string oldKeyname, string newKeyname) { if (oldKeyname == null) { throw new ArgumentNullException("oldKeyname"); } if (newKeyname == null) { throw new ArgumentNullException("newKeyname"); } using (var redisWriter = new RedisWriter(this, 3, "RENAME")) { redisWriter.WriteArgument(oldKeyname); redisWriter.WriteArgument(newKeyname); this.Connection.SendCommand(redisWriter); } return(this.Connection.ExpectSuccess()); }
/// <summary> /// 获取元素的键项列表 /// </summary> /// <param name="key"></param> /// <returns></returns> public string[] HKEYS(string key) { //HKEYS myhash if (key == null) { throw new ArgumentNullException("key"); } using (var w = new RedisWriter(this.client, 2, "HKEYS")) { w.WriteArgument(key); this.connection.SendCommand(w); } //Array reply return(this.connection.ExpectToStringArray(this.connection.ExpectMultiBulkReply())); }
/// <summary> /// 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。 /// 具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。 /// 除了成员按 score 值递减的次序排列这一点外, ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一样 /// </summary> /// <param name="key"></param> /// <param name="min"></param> /// <param name="max"></param> /// <param name="withscores">是否返回分值</param> /// <param name="count">设置数量则offset有产效</param> /// <param name="offset">取出偏移量,需设置count有效</param> /// <returns></returns> private byte[][] ZREVRANGEBYSCOREByte(string key, double min, double max, bool withscores, int offset, int count) { //ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] if (key == null) { throw new ArgumentNullException("key"); } //Array reply: list of elements in the specified score range (optionally with their scores). var size = 4; if (withscores) { size++; } if (count > 0) { size += 3; } using (var w = new RedisWriter(this.client, size, "ZREVRANGEBYSCORE")) { w.WriteArgument(key); w.WriteArgument(max.ToString()); w.WriteArgument(min.ToString()); if (withscores) { w.WriteArgument("WITHSCORES"); } if (count > 0) { w.WriteArgument("LIMIT"); w.WriteArgument(offset.ToString()); w.WriteArgument(count.ToString()); } this.connection.SendCommand(w); } return(this.connection.ExpectMultiBulkReply()); }
/// <summary> /// 获取哈希表元素个数 /// </summary> /// <param name="key"></param> /// <returns></returns> public int HLEN(string key) { //HLEN key if (key == null) { throw new ArgumentNullException("key"); } using (var w = new RedisWriter(this.client, 2, "HLEN")) { w.WriteArgument(key); this.connection.SendCommand(w); } //Integer reply: number of fields in the hash, or 0 when key does not exist. return(this.connection.ExpectInt()); }
/// <summary> /// 设置一个值,当键已存在时则忽略 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public bool SetNX(string key, byte[] value) { if (key == null) { throw new ArgumentNullException("key"); } if (value == null) { throw new ArgumentNullException("value"); } if (value.Length > 1073741824) { throw new ArgumentException("value exceeds 1G", "value"); } using (var redisWriter = new RedisWriter(this, 3, "SETNX")) { redisWriter.WriteArgument(key); redisWriter.WriteArgument(value); this.Connection.SendCommand(redisWriter); } //Set key to hold string value if key does not exist. In that case, it is equal to SET. When key already holds a value, no operation is performed. SETNX is short for "SET if N ot e X ists". //Return value //Integer reply, specifically: //1 if the key was set //0 if the key was not set var r = this.Connection.ExpectInt(); if (r == 1) { return(true); } if (r == 0) { return(false); } throw new InvalidOperationException(string.Format("Unknown Result '{0}'", r)); }
/// <summary> /// 将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值. /// </summary> /// <param name="destkey"></param> /// <param name="sourcekeys"></param> /// <returns></returns> public bool PFMERGE(string destkey, params string[] sourcekeys) { if (string.IsNullOrEmpty(destkey)) { throw new ArgumentNullException("destkey"); } if (sourcekeys.Length == 0) { throw new ArgumentNullException("sourcekeys"); } using (var w = new RedisWriter(this.client, sourcekeys.Length + 2, "PFMERGE")) { w.WriteArgument(destkey); foreach (var member in sourcekeys) { w.WriteArgument(member); } this.connection.SendCommand(w); } return(this.connection.ExpectSuccess()); }
/// <summary> /// 将所有元素参数添加到 HyperLogLog 数据结构中 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns>"OK" 添加成功</returns> public int PFADD(string key, params string[] value) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } if (value == null || value.Length == 0) { throw new ArgumentNullException("value"); } using (var w = new RedisWriter(this.client, value.Length + 2, "PFADD")) { w.WriteArgument(key); foreach (var member in value) { w.WriteArgument(member); } this.connection.SendCommand(w); } return(this.connection.ExpectInt()); }
/// <summary> /// 删除一个积分范围元素 /// </summary> /// <param name="key"></param> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> public int ZREMRANGEBYSCORE(string key, double min, double max) { //ZREMRANGEBYSCORE key min max if (key == null) { throw new ArgumentNullException("key"); } //Integer reply: the number of elements removed. using (var w = new RedisWriter(this.client, 4, "ZREMRANGEBYRANK")) { w.WriteArgument(key); w.WriteArgument(min.ToString()); w.WriteArgument(max.ToString()); this.connection.SendCommand(w); } return(this.connection.ExpectInt()); }
/// <summary> /// 设置一组元素值 /// </summary> /// <param name="key"></param> /// <param name="dictionary"></param> public bool HMSET(string key, IDictionary <string, string> dictionary) { //HMSET key field value [field value ...] if (key == null) { throw new ArgumentNullException("key"); } if (dictionary == null) { throw new ArgumentNullException("dictionary"); } using (var w = new RedisWriter(this.client, dictionary.Count * 2 + 2, "HMSET")) { w.WriteArgument(key); var e = dictionary.GetEnumerator(); while (e.MoveNext()) { if (e.Current.Key == null) { throw new ArgumentNullException("dictionary", "dictionary key contains null, it's not allowed"); } if (e.Current.Value == null) { throw new ArgumentNullException("dictionary", "dictionary key " + e.Current.Key + " value is null"); } w.WriteArgument(this.client.Encoding.GetBytes(e.Current.Key)); w.WriteArgument(this.client.Encoding.GetBytes(e.Current.Value)); } this.connection.SendCommand(w); } //Simple string reply return(this.connection.ExpectSuccess()); }
/// <summary> /// 获取服务器信息 /// </summary> /// <returns></returns> public Dictionary <string, string> GetInfo() { using (var redisWriter = new RedisWriter(this, 1, "INFO")) { this.Connection.SendCommand(redisWriter); } byte[] r = this.Connection.ExpectBulkReply(); var dict = new Dictionary <string, string>(10); var v = this.Encoding.GetString(r); foreach (var line in v.Split('\n')) { int p = line.IndexOf(':'); if (p == -1) { continue; } dict.Add(line.Substring(0, p), line.Substring(p + 1)); } return(dict); }
/// <summary> /// 添加一个元素 /// </summary> /// <param name="key"></param> /// <param name="score"></param> /// <param name="member"></param> /// <returns>排序</returns> public int ZAdd(string key, double score, string member) { //ZADD myzset 1 "one" if (member == null) { throw new ArgumentNullException("member"); } using (var w = new RedisWriter(this.client, 4, "ZADD")) { w.WriteArgument(key); w.WriteArgument(score.ToString()); w.WriteArgument(member); this.connection.SendCommand(w); } //Integer reply, specifically: //The number of elements added to the sorted sets, not including elements already existing for which the score was updated. return(this.connection.ExpectInt()); }
/// <summary> /// 获取匹配的键列表 /// </summary> /// <param name="pattern">匹配规则</param> /// <returns></returns> public string[] GetKeys(string pattern) { if (pattern == null) { throw new ArgumentNullException("key"); } using (var redisWriter = new RedisWriter(this, 2, "KEYS")) { redisWriter.WriteArgument(pattern); this.Connection.SendCommand(redisWriter); } var keys = this.Connection.ExpectToStringArray(); return(keys); //var keys = this.Connection.ExpectBulkReply() ; //if (keys.Length == 0) // return new string[0]; //return this.Encoding.GetString(keys).Split(' '); }
/// <summary> /// 返回给定的区间元素列表 /// </summary> /// <param name="key"></param> /// <param name="start"></param> /// <param name="stop"></param> /// <param name="withscores">是否返回分值</param> /// <returns></returns> private byte[][] ZREVRANGEByte(string key, int start, int stop, bool withscores) { //ZREVRANGE key start stop [WITHSCORES] if (key == null) { throw new ArgumentNullException("key"); } //Array reply: list of elements in the specified range (optionally with their scores). if (withscores) { using (var w = new RedisWriter(this.client, 5, "ZREVRANGE")) { w.WriteArgument(key); w.WriteArgument(start.ToString()); w.WriteArgument(stop.ToString()); w.WriteArgument("WITHSCORES"); this.connection.SendCommand(w); } } else { using (var w = new RedisWriter(this.client, 4, "ZREVRANGE")) { w.WriteArgument(key); w.WriteArgument(start.ToString()); w.WriteArgument(stop.ToString()); this.connection.SendCommand(w); } } return(this.connection.ExpectMultiBulkReply()); }
/// <summary> /// 订阅指定KEY的消息,使用此方法请确保此实例仅会被当次使用 /// </summary> /// <param name="channels"></param> /// <param name="resultCallback"></param> public void Subscribe(Action <RedisSubscribeResult> resultCallback, params string[] channels) { if (channels.Length == 0) { throw new ArgumentException("channels"); } using (var redisWriter = new RedisWriter(this.client, channels.Length + 1, "SUBSCRIBE")) { foreach (var key in channels) { redisWriter.WriteArgument(key); } this.connection.SendCommand(redisWriter); } this.client.PoolAbandon = true; //禁用当前池实例,防止被重用 while (true) { var result = this.connection.ExpectSubscribeResult(); resultCallback(result); } }
/// <summary> /// 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。 /// 排名以 0 为底,也就是说, score 值最大的成员排名为 0 。 /// 使用 ZRANK 命令可以获得成员按 score 值递增(从小到大)排列的排名。 /// </summary> /// <param name="key"></param> /// <param name="member"></param> /// <returns></returns> public int?ZREVRANK(string key, string member) { //ZREVRANK key member if (key == null) { throw new ArgumentNullException("key"); } if (member == null) { throw new ArgumentNullException("member"); } //If member exists in the sorted set, Integer reply: the rank of member. //If member does not exist in the sorted set or key does not exist, Bulk string reply: nil. using (var w = new RedisWriter(this.client, 3, "ZREVRANK")) { w.WriteArgument(key); w.WriteArgument(member); this.connection.SendCommand(w); } return(this.connection.ExpectIntOrNil()); }
/// <summary> /// 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。 /// 默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之 和 。 /// </summary> /// <param name="destinationKey">目标键</param> /// <param name="keyWeights">键与乘法因子</param> /// <param name="aggregate">聚合方式</param> /// <returns>保存到 destination 的结果集的基数</returns> public int ZUNIONSTORE(string destinationKey, IDictionary <string, double> keyWeights, RedisAggregate aggregate) { //ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] //Integer reply: the number of elements in the resulting sorted set at destination. if (string.IsNullOrEmpty(destinationKey)) { throw new ArgumentNullException("destinationKey"); } if (keyWeights == null || keyWeights.Count == 0) { throw new ArgumentNullException("keyWeights"); } // var keys = new string[keyWeights.Count]; var weights = new double[keyWeights.Count]; var i = 0; var e = keyWeights.GetEnumerator(); while (e.MoveNext()) { keys[i] = e.Current.Key; weights[i] = e.Current.Value; i++; } //ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] using (var w = new RedisWriter(this.client, 6 + keyWeights.Count * 2, "ZUNIONSTORE")) { w.WriteArgument(destinationKey); w.WriteArgument(keyWeights.Count.ToString()); foreach (var key in keys) { w.WriteArgument(key); } w.WriteArgument("WEIGHTS"); foreach (var weight in weights) { w.WriteArgument(weight.ToString()); } w.WriteArgument("AGGREGATE"); w.WriteArgument(aggregate.ToString()); this.connection.SendCommand(w); } return(this.connection.ExpectInt()); //示例 // redis> ZRANGE programmer 0 -1 WITHSCORES //1) "peter" //2) "2000" //3) "jack" //4) "3500" //5) "tom" //6) "5000" //redis> ZRANGE manager 0 -1 WITHSCORES //1) "herry" //2) "2000" //3) "mary" //4) "3500" //5) "bob" //6) "4000" //redis> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 //(integer) 6 //redis> ZRANGE salary 0 -1 WITHSCORES //1) "peter" //2) "2000" //3) "jack" //4) "3500" //5) "tom" //6) "5000" //7) "herry" //8) "6000" //9) "mary" //10) "10500" //11) "bob" //12) "12000" }