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);
    }
}
posted @ 2013-03-31 09:47  junchu25  阅读(1260)  评论(0编辑  收藏  举报