How to get memcached all keys
1、通过发送"stats items STAT items:0:number 0 \r\n"获取所有的slab,并从中解析出slabId。返回结果参考如下:
STAT items:1:number 7 STAT items:1:age 966591 STAT items:1:evicted 0 STAT items:1:outofmemory 0 STAT items:2:number 32 STAT items:2:age 1206400 STAT items:2:evicted 0 STAT items:2:outofmemory 0
2、上面的数字1、2就是所谓的slabId,通过发送"stats cachedump [slabId] 200000 ITEM views.decorators.cache.cache_header..cc7d9 [6 b; 1256056128 s] \r\n"获取每个slab存储的所有键项。返回结果参考如下:
ITEM razor_html[depend][webim][all][union_standard] [10 b; 1365091199 s]
示例代码:
/// <summary> /// 程序 /// </summary> class Program { /// <summary> /// 主入口 /// </summary> /// <param name="args">参数</param> static void Main(String[] args) { var ipString = "127.0.0.1"; var port = 11211; var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(new IPEndPoint(IPAddress.Parse(ipString), port)); var slabIdIter = QuerySlabId(socket); var keyIter = QueryKeys(socket, slabIdIter); socket.Close(); foreach (String key in keyIter) Console.Write(key + " "); Console.Read(); } /// <summary> /// 执行返回字符串标量 /// </summary> /// <param name="socket">套接字</param> /// <param name="command">命令</param> /// <returns>执行结果</returns> static String ExecuteScalarAsString(Socket socket, String command) { var sendNumOfBytes = socket.Send(Encoding.UTF8.GetBytes(command)); var bufferSize = 0x1000; var buffer = new Byte[bufferSize]; var readNumOfBytes = 0; var sb = new StringBuilder(); while (true) { readNumOfBytes = socket.Receive(buffer); sb.Append(Encoding.UTF8.GetString(buffer)); if (readNumOfBytes < bufferSize) break; } return sb.ToString(); } /// <summary> /// 查询slabId /// </summary> /// <param name="socket">套接字</param> /// <returns>slabId遍历器</returns> static IEnumerable<String> QuerySlabId(Socket socket) { var command = "stats items STAT items:0:number 0 \r\n"; var contentAsString = ExecuteScalarAsString(socket, command); return ParseStatsItems(contentAsString); } /// <summary> /// 解析STAT items返回slabId /// </summary> /// <param name="contentAsString">解析内容</param> /// <returns>slabId遍历器</returns> static IEnumerable<String> ParseStatsItems(String contentAsString) { var slabIds = new List<String>(); var separator = "\r\n"; var separator2 = ':'; var items = contentAsString.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (Int32 i = 0; i < items.Length; i += 4) { var itemParts = items[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries); if (itemParts.Length < 3) continue; slabIds.Add(itemParts[1]); } return slabIds; } /// <summary> /// 查询键 /// </summary> /// <param name="socket">套接字</param> /// <param name="slabIdIter">被查询slabId</param> /// <returns>键遍历器</returns> static IEnumerable<String> QueryKeys(Socket socket, IEnumerable<String> slabIdIter) { var keys = new List<String>(); var cmdFmt = "stats cachedump {0} 200000 ITEM views.decorators.cache.cache_header..cc7d9 [6 b; 1256056128 s] \r\n"; var contentAsString = String.Empty; foreach (String slabId in slabIdIter) { contentAsString = ExecuteScalarAsString(socket, String.Format(cmdFmt, slabId)); keys.AddRange(ParseKeys(contentAsString)); } return keys; } /// <summary> /// 解析stats cachedump返回键 /// </summary> /// <param name="contentAsString">解析内容</param> /// <returns>键遍历器</returns> static IEnumerable<String> ParseKeys(String contentAsString) { var keys = new List<String>(); var separator = "\r\n"; var separator2 = ' '; var prefix = "ITEM"; var items = contentAsString.Split(separator, StringSplitOptions.RemoveEmptyEntries); foreach (var item in items) { var itemParts = item.Split(separator2, StringSplitOptions.RemoveEmptyEntries); if ((itemParts.Length < 3) || !String.Equals(itemParts.FirstOrDefault(), prefix, StringComparison.OrdinalIgnoreCase)) continue; keys.Add(itemParts[1]); } return keys; } } /// <summary> /// String扩展函数 /// </summary> static class StringExtension { /// <summary> /// 切割 /// </summary> /// <param name="str">字符串</param> /// <param name="separator">分隔符</param> /// <param name="options">选项</param> /// <returns>切割结果</returns> public static String[] Split(this String str, Char separator, StringSplitOptions options) { return str.Split(new Char[] { separator }, options); } /// <summary> /// 切割 /// </summary> /// <param name="str">字符串</param> /// <param name="separator">分隔符</param> /// <param name="options">选项</param> /// <returns>切割结果</returns> public static String[] Split(this String str, String separator, StringSplitOptions options) { return str.Split(new String[] { separator }, options); } }