Memcache的使用(c#)

祁嘉言
2023-12-01

一、服务端安装

1.本机windows环境安装

memcached-win64-1.4.29-msys2.0.zip

文件上传到csdn备份下http://download.csdn.net/detail/shujudeliu/9921782

cmd进入memcache文件目录

安装:memcached.exe -d install

启动:memcached.exe -d start

停止:memcached.exe -d stop

卸载:memcached.exe -d uninstall

ps,因为win环境的memcache是以服务形式安装的,因此测试卸载时候需先执行停止然后才能卸载

2.虚拟机Linux-Centos 6环境下(本例IP:192.168.200.133)

安装:yum -y install memcached

启动:service memcached start

测试telnet连接不上时注意防火墙是否关闭(或开启允许11211端口访问)

二、客户端调用

1.nuget添加EnyimMemcached的引用,本文使用EnyimMemcached 2.16.0

2.web.config配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="enyim.com">
      <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
    </sectionGroup>
  </configSections>

  <enyim.com>
    <memcached protocol="Text">
      <servers>
        <add address="127.0.0.1" port="11211" />
        <add address="192.168.200.133" port="11211" />
      </servers>
      <socketPool minPoolSize="10" maxPoolSize="20" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
    </memcached>
  </enyim.com>
</configuration>


3.Memcache操作类


    public class MemCachedHelper
    {
        private static readonly MemcachedClient _uniqueInstance = new MemcachedClient();
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">缓存key</param>
        /// <param name="obj">缓存value</param>
        /// <param name="timeout">超时时间</param>
        public static bool Add(string key, object value, TimeSpan timeout)
        {
            return _uniqueInstance.Store(StoreMode.Add, key, value, timeout);
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key">缓存key</param>
        /// <param name="obj">缓存value</param>
        /// <param name="timeout">过期时间</param>
        public static bool Set(string key, object value, TimeSpan timeout)
        {
            return _uniqueInstance.Store(StoreMode.Set, key, value, timeout);
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key">缓存key</param>
        public static T Get<T>(string key)
        {
            return _uniqueInstance.Get<T>(key); ;
        }
        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key">缓存key</param>
        public static object Get(string key)
        {
            return _uniqueInstance.Get(key); ;
        }
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key">缓存key</param>
        public static bool Remove(string key)
        {
            return _uniqueInstance.Remove(key);
        }
    }

调用代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        MemCachedHelper.Add("test", "1111", new TimeSpan(0, 0, 300));
        var test = MemCachedHelper.Get("test");   
            Console.ReadKey();
        }
    }
}

测试时分别用telnet链接2台安装了memcache的机器,然后用测试程序多add/set几个值,观察缓存存放的位置


踩坑如下:

Store(StoreMode mode, string key, object value, DateTime expiresAt)

调用该重载方法时返回结果一直为true,实际却get不到值,查看了源码以后找到了问题如下:

        
        public bool Store(StoreMode mode, string key, object value, DateTime expiresAt)
        {
            int num2;
            ulong cas = 0L;
            return this.PerformStore(mode, key, value, GetExpiration(expiresAt), ref cas, out num2).Success;
        }
        
        public bool Store(StoreMode mode, string key, object value, TimeSpan validFor)
        {
            int num2;
            ulong cas = 0L;
            return this.PerformStore(mode, key, value, GetExpiration(validFor), ref cas, out num2).Success;
        }

		#region [ Expiration helper            ]

		protected const int MaxSeconds = 60 * 60 * 24 * 30;
		protected static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1);

		protected static uint GetExpiration(TimeSpan validFor)
		{
			// convert timespans to absolute dates
			// infinity
			if (validFor == TimeSpan.Zero || validFor == TimeSpan.MaxValue) return 0;

			uint seconds = (uint)validFor.TotalSeconds;
			if (seconds > MaxSeconds)
				return GetExpiration(DateTime.Now.Add(validFor));

			return seconds;
		}

		protected static uint GetExpiration(DateTime expiresAt)
		{
			if (expiresAt < UnixEpoch) throw new ArgumentOutOfRangeException("expiresAt", "expiresAt must be >= 1970/1/1");

			// accept MaxValue as infinite
			if (expiresAt == DateTime.MaxValue) return 0;

			uint retval = (uint)(expiresAt.ToUniversalTime() - UnixEpoch).TotalSeconds;

			return retval;
		}

		#endregion

GetExpiration(DateTime expiresAt)这个重载方法代码有bug,设置的过期时间是与1970/1/1的毫秒差值,

过期时间值过大导致无效,memcache的缓存有效期最大为30天

在github上也找到了相关问题描述:https://github.com/enyim/EnyimMemcached/pull/172/commits/94021c56c2bf335977c0e63392ced655a0912a47

修改后的方法如下:

        protected static uint GetExpiration(DateTime expiresAt)
        {
            if (expiresAt < UnixEpoch) throw new ArgumentOutOfRangeException("expiresAt", "expiresAt must be >= 1970/1/1");

            // accept MaxValue as infinite
            if (expiresAt == DateTime.MaxValue) return 0;

            //uint retval = (uint)(expiresAt.ToUniversalTime() - UnixEpoch).TotalSeconds;//bug代码
            uint retval = (uint)(expiresAt.ToUniversalTime() - DateTime.Now.ToUniversalTime()).TotalSeconds;
            return retval;
        }






 类似资料: