memcache讲解和在.net中初使用
2017年10月17日 22:51:36 等待临界 阅读数:503
前言
将登陆信息和状态保存到哪里一直是我困惑的。保存到cookie里面?不不,太不安全;保存到session?不不,处于进程里影响性能降低还易丢失;保存到数据库?我的确这样想过也试过,安全又完整但是读数据库让我不满意;保存到httpruntime.cache里面?
在查找一些资源后我了解到可以保存到缓存数据库里面,memcache就是其中一款缓存数据库,并且还拥有其他的好处。
在我们了解memcache之前,先了解以下信息:
传统数据库面临的问题
Web程序在面临海量数据、高并发请求时,传统的数据库往往会面临以下问题:
数据库死锁
数据库基本操作curd,死锁是数据库高并发的明显问题:r要加S锁(共享锁,可以查看但是无法cud),cud要加X锁(排他锁,可以curd,其他事务无法再次加锁),当高并发请求,数据库可能产生死锁(数据库阻塞,永远等待状态)。这是无法避免的问题。以下是解决死锁的常见手段:
- 死锁预防
使用数据库逻辑上来预防死锁,但是这显然还会出现慢的问题。 -
读写分离
就是做数据库集群,使用主从数据库:将数据保存到多个主从数据库里面,主数据库负责cud,多个从数据库负责r,这样不仅避免死锁,也提高了速度。但是同样带来了问题:
磁盘IO
数据库把数据保存到磁盘上,读取慢,磁盘IO是一大原因,因为磁盘IO是硬件问题。常见解决方式如下:
接下来使用控制台应用程序来操作memcache。
正文
了解memcache
memcache官网
memcached是一种高性能,分布式的内存对象缓存系统,本质上是通用的,但最初旨在通过减轻数据库负载来加速动态Web应用程序。
原理
- 内存处理
- 客户端实现分布式:
给memcache配置多个服务器ip,当需要查询时会寻找哪台服务器或者添加一个数据时会保存到哪一个服务器上呢?memcache对key值进行哈希计算然后对配置的服务器总数进行取余,余数是几就向第几台服务器进行操作。这就导致了一个问题:当服务器数量发生变化时会导致部分数据丢失(查询指向服务器错误)。想要这种影响降低到最低,可以使用一致性哈希算法。 - 走socket
数据通信走的是socket。
基本命令
这里引用IBM developerWorks里面的一篇文章部分内容
基本 memcached 客户机命令
您将使用五种基本 memcached 命令执行最简单的操作。这些命令和操作包括:
set add replace get delete
前三个命令是用于操作存储在 memcached 中的键值对的标准修改命令。它们都非常简单易用,且都使用清单 5 所示的语法:
清单 5. 修改命令语法
command +key +flags +expiration time+ bytes+
value
key key 用于查找缓存值
flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息
expiration time 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes 在缓存中存储的字节点
value 存储的值(始终位于第二行)
其中key最大长度255字符。
memcache与memcached
memcache是项目的名字,memcached是项目被可执行代码的名字,一般指同一个东西。
memcache的适用范围
可以将其视为应用程序的短期内存。不适合保存持久化数据。其是分布式系统,数据分布在多个机器上迁移很麻烦。也不会记录数据。这里用户的登陆状态并不需要专门保存,可以使用memcache保存。
memcache的客户端和服务端
memcache有客户端和服务端之分,客户端编程,需要引用相应的dll文件;服务端开启memcached服务。
memcache服务端本身不支持windows下使用,但是一些爱好者提供了windows下的exe程序来开启这个服务。
请搜索Memcached.ClientLibrary来下载你需要使用的dll文件和exe服务,我是在sourceforge这里下载的。
memcache与redis异同
memcache经常与redis进行对比
- 相同点:
都使用内存;效率都很高,1s内读1w次,写10w次都很平常; - 不同点:
- 线程
memcache是多线程,redis是单线程,所以写多数据时memcache效率更好。 - 数据类型
memcached使用key-value存储,本身就是一个hash(哈希表)。
redis现阶段提供五种数据类型:string(字符串类型)、list(链表)、set(集合)、zset(有序集合)、hash(哈希表)。 - 数据存储
memcache是分布式系统,每个服务器都值保存一部分数据,迁移很弱(memcache定位就是短期内存,保存在memcache里面的数据本来就是不需要迁移的)。断电丢失数据。
redis启用内存但是可以保证数据持久化、完整性和同步,即每个服务器都保存完整数据。这是因为redis的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置,断电之后可以通过文件来恢复数据;使用快照的方式进行数据同步。
- 线程
简单使用memcached
打开memcache服务
这一步相当玉开启服务端的memcache服务。在windows下开启服务相当简单,直接打开这个exe程序就行了
使用memcached命令
如果只是布置服务端的话,上一步就已经完成了。如果想要连接服务端的memcached服务并且使用命令的话,可以使用以下步骤:
1. 打开Telnet客户端服务
然后就可以愉快地输入你的命令了,如使用add命令来添加和get命令获取值,key值已经存在就会返回NOT_STORED提示,如果正确添加就会返回STORED提示。
注意:
命令无法退格,所以输错就按enter重新输入
memcached默认端口11211
添加引用
默认memcache引用程序集会自带一个log4net.dll文件以便错误时可以记录日志,这里并不需要记录日志就不引用。
程序代码
using Memcached.ClientLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MemcachedDemo
{
class Program
{
static void Main(string[] args)
{
//SockIOPool是Memcached客户端提供的一个套接字连接池,是与Memcached服务器端交换数据的对象。
//SockIOPool在应用程序启动时初始化一次就可以了,我们可以把这个工作放在 GLOBAL.ASAX.CS的Application_Start方法里。
try
{
MemcachedClient mc = new MemcachedClient();
mc.EnableCompression = false;
string[] serverlist = {"127.0.0.1:11211"};
SockIOPool pool = SockIOPool.GetInstance();
//初始化
pool.SetServers(serverlist);
pool.InitConnections = 3;
pool.MinConnections = 3;
pool.MaxConnections = 50;
pool.socketConnectTimeout = 1000;
pool.socketTimeout = 3000;
pool.MaintenanceSleep = 30;
pool.Failover = true;
pool.Nagle = false;
pool.Initialize();
mc.Add("key1","这是第一个数据",0);
string value= mc.Get("key1") as string;
Console.WriteLine(value);
}
catch (Exception err)
{
//这里可以用Log4Net记录Error
}
Console.ReadLine();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
运行效果
引申
- 集群和分布式
数据库集群:往往在同一局域网,使用同一个IP,每个数据库有完整数据,难点是数据同步,迁移方便。
数据库分布式:每个系统拥有部分数据,使用使用简单,数据迁移麻烦。 - Redis主从数据库
主库负责写,从库负责读,压力分流。
主库挂掉,随机选择一个从库成为主库。
数据如何同步:快照。
总结
- memcache的key值最大255字符
- memcached的块最大1M