• Memcached,你懂的


    一、Memcached简介

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

    目前有多种平台的Memcached版本,比如Linux、FreeBSD、Solaris 、Mac OS X及Windows平台。

    可在官网下载到最新版本: http://memcached.org/ (LINUX) 。

    这里,官网上好像没有找到Memcached for windows
    我们安装Windows版本来演示。

    32bit:下载 memcached-win32-1.4.4-14.zip

    64bit:如果需要win64版,下载 memcached-win64-1.4.4-14.zip

    二、安装和启动

    首先,我解压文件路径
    D:MemcachedMemcached32

    安装命令
    以管理员身份运行 cmd.exe

    进入到解压文件
    D:>cd MemcachedMemcached32

    安装
    D:MemcachedMemcached32>memcached.exe -d install

    启动
    D:MemcachedMemcached32>memcached.exe -d start

    OK,命令咱们已经执行完了.怎么才知道Memcached服务已经安装成功并启动了呢?

    cmd  命令 services.msc

    有时候,为了方便起见,我们也不能每次安装,停止和启动服务的时候都打开cmd命令框吧

    常见的办法是做成批处理命令,如下:

    install.bat

    memcached.exe -d install

    start.bat

    memcached.exe -d start

    stop.bat

    memcached.exe -d stop

    unInstall.bat

    memcached.exe -d uninstall

    三、.net 项目中使用

    笔者查阅了相关资料,发现有很多支持Memcached的客户端,这里由于笔者的个人喜好,

    选择了EnyimMemcached.2.13

    可以通过Nuget安装

    PM> Install-Package EnyimMemcached

    笔者特意做了一个Demo来体验一下,EnyimMemcached使用

    首先,我们要连接到这个分布式数据库服务,类似以前的关系型数据库,这里也是需要配置连接的,配置如下

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <sectionGroup name="enyim.com">
          <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection,Enyim.Caching" />
        </sectionGroup>
        <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
      </configSections>
      <enyim.com>
        <memcached>
          <servers>
            <!-- put your own server(s) here-->
            <add address="127.0.0.1" port="11211" />
          </servers>
          <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
        </memcached>
      </enyim.com>
      <memcached keyTransformer="Enyim.Caching.TigerHashTransformer,Enyim.Caching">
        <servers>
          <add address="127.0.0.1" port="11211" />
        </servers>
        <socketPool minPoolSize="2" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
      </memcached>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
    </configuration>

    为了方便使用,可以再封装一下,便于调用,

    using Enyim.Caching;
    using Enyim.Caching.Configuration;
    using Enyim.Caching.Memcached;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MemcachdDemo.Helper
    {
        public sealed class MemCachedHelper
        {
            private static MemcachedClient MemClient;
            static readonly object padlock = new object();
    
            //线程安全的单例模式
            public static MemcachedClient getInstance()
            {
                if (MemClient == null)
                {
                    lock (padlock)
                    {
                        if (MemClient == null)
                        {
                            MemClientInit();
                        }
                    }
                }
                return MemClient;
            }
    
            static void MemClientInit()
            {
                try
                {
                    MemClient = new MemcachedClient();
                    /*MemcachedClientConfiguration config = new MemcachedClientConfiguration();
                    config.Servers.Add(new System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), 11211));
                    config.Protocol = MemcachedProtocol.Binary;
                    //config.Authentication.Type = typeof(PlainTextAuthenticator);
                    //config.Authentication.Parameters["userName"] = "memcache";
                    //config.Authentication.Parameters["password"] = "password";
                    MemClient = new MemcachedClient(config);*/
                    /*MemcachedClientConfiguration config = new MemcachedClientConfiguration();
                    //config.Servers.Add(new IPEndPoint("127.0.0.1", 11211));
                    config.Servers.Add(new System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), 11211));
                    config.Protocol = MemcachedProtocol.Binary;
                    config.Authentication.Type = typeof(PlainTextAuthenticator);
                    config.Authentication.Parameters["userName"] = "username";
                    config.Authentication.Parameters["password"] = "password";
                    config.Authentication.Parameters["zone"] = "";
    
                    MemClient = new MemcachedClient(config);*/
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            #region getAllKeys
    
            public static List<string> GetAllKeys(string ipString, int port)
            {
                List<string> allKeys = new List<string>();
                //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)
                {
                    if (!allKeys.Contains(key))
                        allKeys.Add(key);
                }
    
                return allKeys;
            }
    
            /// <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 
    ";
                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 = "
    ";
                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] 
    ";
                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 = "
    ";
                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);
            }
    
            #endregion
    
        }
    }

    因为EnyimMemcached帮我们封装的很好,剩下的就是调用了

    private void button3_Click(object sender, EventArgs e)
            {
                try
                {
                    if (String.IsNullOrEmpty(this.txtKey.Text))
                    {
                        MessageBox.Show("key不能为空!");
                        return;
                    }
                    else
                    {
                        var key = this.txtKey.Text.Trim();
                        var value = this.txtValue.Text.Trim();
                        var bRet = client.Store(StoreMode.Set, key.Trim(), txtValue.Text.Trim());
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

    截图如下

    由于是key-value存储,查询方法:

    var value = mc.Get("name");

    对于Memcached的安装,启动和基本使用,有了简单的介绍,希望对你有用, 有用的话,请支持一下哈!

  • 相关阅读:
    使用delphi 开发多层应用(十)安全访问服务器
    使用delphi 开发多层应用(十三)使用Basic4android 直接访问kbmMW server
    使用delphi 开发多层应用(十一)使用kbmMW 开发webserver
    basic4android 开发教程翻译(八)使用ListView
    使用delphi 连接国产数据库:达梦
    kbmMW 4.01.00 Beta 1发布了
    解决 ie 下 javascript 设置 table.tBodies.innerHTML 无法设置的问题
    用vs2010 把 vcf 转成 csv,再转入Nokia
    GAC 与 引用 程序集路径
    sqlserver 函数 之 进制转换
  • 原文地址:https://www.cnblogs.com/lucky_hu/p/4676734.html
Copyright © 2020-2023  润新知