Memcached简介

Memcached是一个专门用来做缓存的服务器,而且缓存的数据都在内存中。Memcached就相当于一个Dictionary键值对集合,保存的是键值对,然后根据key取value。

当然web服务器和Memcached之间还是要网络间通讯,效率还是没有进程内缓存效率高。Memcached程序重启之后数据就会消失。

32位系统 1.4.4版本:http://static.runoob.com/download/memcached-win32-1.4.4-14.zip

64位系统 1.4.4版本:http://static.runoob.com/download/memcached-win64-1.4.4-14.zip

32位系统 1.4.5版本:http://static.runoob.com/download/memcached-1.4.5-x86.zip

64位系统 1.4.5版本:http://static.runoob.com/download/memcached-1.4.5-amd64.zip

安装

在 1.4.5 版本以前 memcached 可以作为一个服务安装,而在 1.4.5 及之后的版本删除了该功能。因此我们以下介绍两个不同版本 1.4.4 及 1.4.5的不同安装方法:

memcached <1.4.5 版本安装

1、解压下载的安装包到指定目录。

2、在 1.4.5 版本以前 memcached 可以作为一个服务安装,使用管理员权限运行以下命令:

c:\memcached\memcached.exe -d install

注意:你需要使用真实的路径替代 c:\memcached\memcached.exe。

3、然后我们可以使用以下命令来启动和关闭 memcached 服务:

c:\memcached\memcached.exe -d start
c:\memcached\memcached.exe -d stop

4、如果要修改 memcached 的配置项, 可以在命令行中执行 regedit.exe 命令打开注册表并找到 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\memcached" 来进行修改。

如果要提供 memcached 使用的缓存配置 可以修改 ImagePath 为:

"c:\memcached\memcached.exe" -d runservice -m 512

-m 512 意思是设置 memcached 最大的缓存配置为512M。

此外我们还可以通过使用 "c:\memcached\memcached.exe -h" 命令查看更多的参数配置。

5、如果我们需要卸载 memcached ,可以使用以下命令:

c:\memcached\memcached.exe -d uninstall

.NET连接Memcached

安装Memcached 的.Net 开发包:Install-Package EnyimMemcached

写一个简陋的帮助类,后面再完善

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Enyim.Caching;
using Enyim.Caching.Configuration;
using Enyim.Caching.Memcached; namespace ConsoleApp1
{
public class MemCachedHelper<T>
{
private static string SERVER = "127.0.0.1:11211";
//过期时间:20分钟
private static int TimeSpanExpired = 20;
private static MemcachedClientConfiguration mcConfiguration = new MemcachedClientConfiguration();
static MemCachedHelper()
{
mcConfiguration.AddServer(SERVER);
} /// <summary>
/// Set设置key,value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Boolean SetKey(string key, object value)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
/*
* MemcachedClient.Store(StoreMode mode, string key, object value); 使用缓存键将项插入到缓存中, 以引用其位置。
* StoreMode mode 定义项在缓存中的存储方式。
*/
return client.Store(StoreMode.Set, key, value,TimeSpan.FromMinutes(TimeSpanExpired));
}
} /// <summary>
/// 获取值
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static T GetValue(string name)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
return (T)client.Get(name);
}
}
}
}

1.Memcache存入的是键值对。

Memcache存入数据的3中模式SetReplaceAdd

根据名字就能猜出来:

Set:存在则覆盖,不存在则新增

Replace:如果存在则覆盖,并且返回true;如果不存在则不处理,并且返回false;

Add:如果不存在则新增,并且返回true;如果存在则不处理,并且返回false;

没特殊要求一般用Set就可以了。

2.对象序列化

如果保存普通类对象,则对象必须可序列化(不同Memcached客户端保存对象的机制都不尽相同)。

例子:

    public class Student
{
public Student(int age, string name)
{
this.age = age;
this.name = name;
} private int age { get; set; }
private string name { get; set; }
}

这里

//返回false
Console.WriteLine(MemCachedHelper<Student>.SetKey("student", student));

应该添加

[Serializable]
public class Student
{
...
}

3.存入设置过期时间

设置最后一个TimeSpan类型的参数:

client.Store(Enyim.Caching.Memcached.StoreMode.Set, "name", "tangsansan",TimeSpan.FromSeconds(5));

4.读取:client.Get("name")

如果找不到,则返回null。当然也可以用public bool TryGet(string key, out object value)。还支持泛型的public T Get<T>(string key)

5.Remove(string key)

则是删除一个key对应的内容。

Key的长度最高是250个字符,Value最长1M(大约524288个字)。

6.ExecuteXXX

与Store、Get、Remove配套的还有ExecuteXXX方法,唯一区别就是返回值信息更详细。

7.Key的选择(命名)

Memcached就相当于一个大键值对,不同系统放到Memcached中的数据都是不隔离的,因此设定Key的时候要选择好Key,这样就不容易冲突。

建议规则“系统名字_模块名字_业务Key”,比如“Shop_Admin_FilterWords”

8. Increment、Decrement

是用来对计数器进行增减的,不过用得少。用Redis更合适。

2.CAS(乐观锁)

用来解决并发问题:读出一个值,做一些判断或者处理,再写回,有可能有并发的问题。

Cas是Memcached 1.2.5之后引入的特性,类似于数据库的“乐观锁”,查询的时候查出一个cas值,在写入的时候带着这个cas值,如果发现cas值已经变了,则说明已经有别人改过了。

辅助类

namespace ConsoleApp1
{
public class MemCachedHelper<T>
{
private static string SERVER = "127.0.0.1:11211";
//过期时间:20分钟
private static int TimeSpanExpired = 20;
private static MemcachedClientConfiguration mcConfiguration = new MemcachedClientConfiguration();
static MemCachedHelper()
{
mcConfiguration.AddServer(SERVER);
} /// <summary>
/// Set设置key,value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool SetKey(string key, object value)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
/*
* MemcachedClient.Store(StoreMode mode, string key, object value); 使用缓存键将项插入到缓存中, 以引用其位置。
* StoreMode mode 定义项在缓存中的存储方式。
*/
return client.Store(StoreMode.Set, key, value, TimeSpan.FromMinutes(TimeSpanExpired));
}
} /// <summary>
/// 设置Cas
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="cas"></param>
/// <returns></returns>
public static CasResult<bool> SetCas(string key, object value, ulong cas)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
/*
* MemcachedClient.Cas(StoreMode mode, string key, object value, TimeSpan validFor, ulong cas);
* StoreMode mode 定义项在缓存中的存储方式。
*/
return client.Cas(StoreMode.Set, key, value, TimeSpan.FromMinutes(TimeSpanExpired), cas);
}
} /// <summary>
/// 获取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static T GetValue(string key)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
return (T)client.Get(key);
}
} /// <summary>
/// Cas获取值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static CasResult<T> GetCasValue(string key)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
return client.GetWithCas<T>(key);
}
} /// <summary>
/// 删除Key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static Boolean Remove(string key)
{
using (MemcachedClient client = new MemcachedClient(mcConfiguration))
{
return client.Remove(key);
}
}
}
}

实例:

           var res = MemCachedHelper<string>.GetCasValue("student");
Console.WriteLine("Result:{0},Cas:{1},StatusCode:{2}", res.Result, res.Cas, res.StatusCode);
Console.ReadKey();
CasResult<bool> casR = MemCachedHelper<string>.SetCas("student", "acc", res.Cas);
if (casR.Result)
{
Console.WriteLine("更新成功,cas值:{0}",casR.Cas);
}
else
{
Console.WriteLine("更新失败,已经有人先更新了,cas值:{0}",casR.Cas);
}
Console.ReadKey();

3.集群

memcached重启之后短时间内大量的请求会涌入数据库,给数据库造成压力,解决这个的方法就是使用集群,有多台Memcached服务器提供服务。

当memcached服务器压力大了之后也有必要搞memcached集群来分担压力。

3.1 “雪崩”问题

Memcached服务器的“雪崩”问题:如果所有缓存设置过期时间一样,那么每隔一段时间就会造成一次数据库访问的高峰.

解决的方法:

就是缓存时间设置不一样,比如加上一个随机数

3.2 集群方法

Memcached的集群实现很简单,集群节点直接不进行通讯、同步,只要在多个服务器上启动多个Memcached服务器即可,客户端决定把数据写入不同的实例,不搞主从复制,每个数据库实例保存一部分内容。

然后mcConfig.AddServer("127.0.0.1:11211");添加多个服务器ip地址,然后客户端根据自己的算法决定把数据写入哪个Memcached实例,取数据库的时候再根据同样的定位算法去哪台服务器上去取。

3.3 节点定位算法

节点定位算法有很多种,最常用的有两种 Ketama、VBucket。建议用Ketama就可以了。节点定位算法会自动处理故障服务器。

mcConfig.NodeLocatorFactory = new KetamaNodeLocatorFactory()。

缓存要求都不高。

Consistent Hashing最大限度地抑制了hash键的重新分布。另外要取得比较好的负载均衡的效果,往往在服务器数量比较少的时候需要增加虚拟节点来保证服务器能均匀的分布在圆环上。因为使用一般的hash方法,服务器的映射地点的分布非常不均匀。使用虚拟节点的思想,为每个物理节点(服务器)在圆上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点代表的实际物理服务器上。

一致性Hash算法(KetamaHash)的c#实现

3.3.1 Ketama(常用)

Ketama是根据Key算出一个hash值,根据hash值再算到服务器;

3.3.2 VBucket

VBucket也是根据key算出hash值,但是不是直接根据hash值算出服务地址,而是维护一个VBucket表,在表中指定不同的hash值由不同的服务器处理,还可以临时改变指向。

Memcached 快速入门的更多相关文章

  1. 分布式缓存系统 Memcached 快速入门

    Memcached介绍   官网地址      Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提 ...

  2. Memcached快速入门

    1.基本概念 基于高性能的key-value的内存数据库.单进程多线程,协议简单,使用文本行的协议,支持数据类型简单,不支持持久化,轻量级锁CAS机制,集群互不通信,缓存策略(LRU,FIFO,LFU ...

  3. [你必须知道的NOSQL系列]专题二:Redis快速入门

    一.前言 在前一篇博文介绍了MongoDB基本操作,本来打算这篇博文继续介绍MongoDB的相关内容的,例如索引,主从备份等内容的,但是发现这些内容都可以通过官方文档都可以看到,并且都非常详细,所以这 ...

  4. Redis快速入门:安装、配置和操作

    本文是有关Redis的系列技术文章之一.在之前的文章中介绍了<Redis快速入门:初识Redis>,对Redis有了一个初步的了解.今天继续为大家介绍Redis如何安装.配置和操作. 系列 ...

  5. 二:Redis快速入门及应用

    Redis的使用难吗?不难,Redis用好容易吗?不容易.Redis的使用虽然不难,但与业务结合的应用场景特别多.特别紧,用好并不容易.我们希望通过一篇文章及Demo,即可轻松.快速入门并学会应用. ...

  6. kolla-ansible快速入门

    kolla-ansible快速入门 kolla-ansible是一个结构相对简单的项目,它通过一个shell脚本,根据用户的参数,选择不同的playbook和不同的参数调用ansible-playbo ...

  7. Redis快速入门及应用

    Redis的使用难吗?不难,Redis用好容易吗?不容易.Redis的使用虽然不难,但与业务结合的应用场景特别多.特别紧,用好并不容易.我们希望通过一篇文章及Demo,即可轻松.快速入门并学会应用.一 ...

  8. 中小型研发团队架构实践五:Redis快速入门及应用

    Redis的使用难吗?不难,Redis用好容易吗?不容易.Redis的使用虽然不难,但与业务结合的应用场景特别多.特别紧,用好并不容易.我们希望通过一篇文章及Demo,即可轻松.快速入门并学会应用. ...

  9. 中小型研发团队架构实践:Redis快速入门及应用

    Redis的使用难吗?不难,Redis用好容易吗?不容易.Redis的使用虽然不难,但与业务结合的应用场景特别多.特别紧,用好并不容易.我们希望通过一篇文章及Demo,即可轻松.快速入门并学会应用. ...

随机推荐

  1. shell脚本 统计一段程序运行时间【转】

    转自:https://bbs.csdn.net/topics/391943383#include <stdio.h> #include <stdlib.h> #include ...

  2. js加密转python3

    //add by wangp at 2018-01-23 密码加密方法 start function encrypt(pwd){ var key = "MIIBIjANBgkqhkiG9w0 ...

  3. C++中for_each的应用

    C++中for_each的应用   for each语法是方便的,也是很自然的,这也是为什么很多语言都有这样的语法,就我所知,包括java(jdk5.0以上),python,php,asp.net等语 ...

  4. 修改主机IP地址

    IP:由192.168.1.1~192.168.1.254. 先使用电脑以动态IP的方式自动获取ip地址联网,然后通过以下方法查询子网掩码和默认网关地址:

  5. hibernate框架学习之数据类型

  6. 解决genymotion-arm-translation.zip无法拖拽安装的问题

    1.问题由来 适用情况一:当我们启动了Genymotion模拟器后,在AndroidStudio运行app时,弹出如下错误: INSTALL_FAILED_CPU_ABI_INCOMPATIABLE ...

  7. button 去掉原生边框

    button按钮触发 hover 时,自带边框会显示,尤其是 button 设置圆角时,如图: 解决办法: outline: 0;

  8. C# 后台请求api

    /// <summary> /// 指定Post地址使用Get 方式获取全部字符串 /// </summary> /// <param name="url&qu ...

  9. css中input框不可点击+首行缩进

    Css 1)text-indent::首行缩进 2)disabled="true"设置input框不可以点击 3)Css:xx!important:声明提前优先级最高..!impo ...

  10. js学习——基础知识

    数据类型 函数.方法 变量作用域 运算符 条件语句 break和continue typeof 错误(异常) 变量提升 严格模式 JSON void(0) JavaScript            ...