將登陸信息和狀態(tài)保存到哪里一直是我困惑的。保存到cookie里面?不不,太不安全;保存到session?不不,處于進(jìn)程里影響性能降低還易丟失;保存到數(shù)據(jù)庫?我的確這樣想過也試過,安全又完整但是讀數(shù)據(jù)庫讓我不滿意;保存到HttpRunTime.Cache里面?
在查找一些資源后我了解到可以保存到緩存數(shù)據(jù)庫里面,memcache就是其中一款緩存數(shù)據(jù)庫,并且還擁有其他的好處。
在我們了解memcache之前,先了解以下信息:
Web程序在面臨海量數(shù)據(jù)、高并發(fā)請(qǐng)求時(shí),傳統(tǒng)的數(shù)據(jù)庫往往會(huì)面臨以下問題:
數(shù)據(jù)庫基本操作curd,死鎖是數(shù)據(jù)庫高并發(fā)的明顯問題:r要加S鎖(共享鎖,可以查看但是無法cud),cud要加X鎖(排他鎖,可以curd,其他事務(wù)無法再次加鎖),當(dāng)高并發(fā)請(qǐng)求,數(shù)據(jù)庫可能產(chǎn)生死鎖(數(shù)據(jù)庫阻塞,永遠(yuǎn)等待狀態(tài))。這是無法避免的問題。以下是解決死鎖的常見手段:
死鎖預(yù)防
使用數(shù)據(jù)庫邏輯上來預(yù)防死鎖,但是這顯然還會(huì)出現(xiàn)慢的問題。
讀寫分離
就是做數(shù)據(jù)庫集群,使用主從數(shù)據(jù)庫:將數(shù)據(jù)保存到多個(gè)主從數(shù)據(jù)庫里面,主數(shù)據(jù)庫負(fù)責(zé)cud,多個(gè)從數(shù)據(jù)庫負(fù)責(zé)r,這樣不僅避免死鎖,也提高了速度。但是同樣帶來了問題:
SqlServer
sqlserver在數(shù)據(jù)同步方面很弱,并不適合數(shù)據(jù)同步。主要有三種方法實(shí)現(xiàn):買中間件(不可靠)、發(fā)布訂閱(主庫生成數(shù)據(jù)庫快照給其他數(shù)據(jù)庫,但是有延遲)、代碼實(shí)現(xiàn)寫入多個(gè)數(shù)據(jù)庫(不好)。
Mysql
有很多第三方組件可以實(shí)現(xiàn),很多成功的例子。
Oracle
本身就支持?jǐn)?shù)據(jù)庫同步,只需要配置以下就好了。(另外Oracle因?yàn)闀?huì)最大程序占用資源,所以效率很高)
數(shù)據(jù)同步
多個(gè)數(shù)據(jù)庫要同步數(shù)據(jù),常見三種數(shù)據(jù)庫對(duì)數(shù)據(jù)同步的支持:
數(shù)據(jù)庫把數(shù)據(jù)保存到磁盤上,讀取慢,磁盤IO是一大原因,因?yàn)榇疟PIO是硬件問題。常見解決方式如下:
水平分布和垂直分布
相當(dāng)與分布式數(shù)據(jù)庫:水平分布是根據(jù)數(shù)據(jù)自定義規(guī)則(如userId的奇偶)保存到不同的數(shù)據(jù)庫,垂直分布是根據(jù)數(shù)據(jù)的類型(如圖片庫,收藏夾)保存到不同的數(shù)據(jù)庫。
使用NoSql中的內(nèi)存數(shù)據(jù)庫
NoSql定義
NoSQL(NoSQL = Not Only SQL ),意即“不僅僅是SQL”,非關(guān)系型數(shù)據(jù)庫,存儲(chǔ)數(shù)據(jù)更多的是保存數(shù)據(jù)本身,不需要預(yù)先定義數(shù)據(jù)格式。
內(nèi)存數(shù)據(jù)庫
memcache是分布式內(nèi)存數(shù)據(jù)庫,使用key-value存儲(chǔ)數(shù)據(jù)。將數(shù)據(jù)緩存到內(nèi)存中可以高速存取。因?yàn)橹皇莐ey-value集合即不會(huì)有死鎖。并且實(shí)現(xiàn)了數(shù)據(jù)共享,試想下某度貼吧和云盤反復(fù)當(dāng)你登陸,不是很好的感覺吧。
接下來使用控制臺(tái)應(yīng)用程序來操作memcache。
memcache官網(wǎng)
memcached是一種高性能,分布式的內(nèi)存對(duì)象緩存系統(tǒng),本質(zhì)上是通用的,但最初旨在通過減輕數(shù)據(jù)庫負(fù)載來加速動(dòng)態(tài)Web應(yīng)用程序。
內(nèi)存處理
惰性刪除
memcache并沒有提供數(shù)據(jù)監(jiān)控機(jī)制,而是查詢到某個(gè)數(shù)據(jù),如果過期才會(huì)刪除。
如果內(nèi)存滿了,就會(huì)策略LRU閑置>過期>最少訪問來清空刪除數(shù)據(jù)
內(nèi)存分區(qū)解決內(nèi)存碎片問題
memcache實(shí)現(xiàn)會(huì)對(duì)可用內(nèi)存進(jìn)行劃分分區(qū),每個(gè)區(qū)內(nèi)分成若干塊,同一個(gè)區(qū)內(nèi)塊的大小固定。當(dāng)進(jìn)行數(shù)據(jù)存儲(chǔ),就會(huì)自動(dòng)尋找適合的區(qū)存進(jìn)塊內(nèi)。最大的塊是1M。比如第一個(gè)區(qū)內(nèi)只存0.5M的塊,第二個(gè)塊只存0.6M的數(shù)據(jù),現(xiàn)在過來一個(gè)0.55M的數(shù)據(jù)就會(huì)存到第二個(gè)區(qū)內(nèi),占用0.6M的空間,雖然塊內(nèi)有空間浪費(fèi),但是塊與塊之間沒有縫隙。
客戶端實(shí)現(xiàn)分布式:
給memcache配置多個(gè)服務(wù)器ip,當(dāng)需要查詢時(shí)會(huì)尋找哪臺(tái)服務(wù)器或者添加一個(gè)數(shù)據(jù)時(shí)會(huì)保存到哪一個(gè)服務(wù)器上呢?memcache對(duì)key值進(jìn)行哈希計(jì)算然后對(duì)配置的服務(wù)器總數(shù)進(jìn)行取余,余數(shù)是幾就向第幾臺(tái)服務(wù)器進(jìn)行操作。這就導(dǎo)致了一個(gè)問題:當(dāng)服務(wù)器數(shù)量發(fā)生變化時(shí)會(huì)導(dǎo)致部分?jǐn)?shù)據(jù)丟失(查詢指向服務(wù)器錯(cuò)誤)。想要這種影響降低到最低,可以使用一致性哈希算法。
走socket
數(shù)據(jù)通信走的是socket。
這里引用IBM developerWorks里面的一篇文章部分內(nèi)容
基本 memcached 客戶機(jī)命令
您將使用五種基本 memcached 命令執(zhí)行最簡單的操作。這些命令和操作包括:
set add replace get delete
前三個(gè)命令是用于操作存儲(chǔ)在 memcached 中的鍵值對(duì)的標(biāo)準(zhǔn)修改命令。它們都非常簡單易用,且都使用清單 5 所示的語法:
清單 5. 修改命令語法
command key flags expiration time bytes
value
key key 用于查找緩存值
flags 可以包括鍵值對(duì)的整型參數(shù),客戶機(jī)使用它存儲(chǔ)關(guān)于鍵值對(duì)的額外信息
expiration time 在緩存中保存鍵值對(duì)的時(shí)間長度(以秒為單位,0 表示永遠(yuǎn))
bytes 在緩存中存儲(chǔ)的字節(jié)點(diǎn)
value 存儲(chǔ)的值(始終位于第二行)
其中key最大長度255字符。
memcache是項(xiàng)目的名字,memcached是項(xiàng)目被可執(zhí)行代碼的名字,一般指同一個(gè)東西。
可以將其視為應(yīng)用程序的短期內(nèi)存。不適合保存持久化數(shù)據(jù)。其是分布式系統(tǒng),數(shù)據(jù)分布在多個(gè)機(jī)器上遷移很麻煩。也不會(huì)記錄數(shù)據(jù)。這里用戶的登陸狀態(tài)并不需要專門保存,可以使用memcache保存。
memcache有客戶端和服務(wù)端之分,客戶端編程,需要引用相應(yīng)的dll文件;服務(wù)端開啟memcached服務(wù)。
memcache服務(wù)端本身不支持windows下使用,但是一些愛好者提供了windows下的exe程序來開啟這個(gè)服務(wù)。
請(qǐng)搜索Memcached.ClientLibrary來下載你需要使用的dll文件和exe服務(wù),我是在sourceforge這里下載的。
memcache經(jīng)常與redis進(jìn)行對(duì)比
相同點(diǎn):
都使用內(nèi)存;效率都很高,1s內(nèi)讀1w次,寫10w次都很平常;
不同點(diǎn):
線程
memcache是多線程,redis是單線程,所以寫多數(shù)據(jù)時(shí)memcache效率更好。
數(shù)據(jù)類型
memcached使用key-value存儲(chǔ),本身就是一個(gè)hash(哈希表)。
redis現(xiàn)階段提供五種數(shù)據(jù)類型:string(字符串類型)、list(鏈表)、set(集合)、zset(有序集合)、hash(哈希表)。
數(shù)據(jù)存儲(chǔ)
memcache是分布式系統(tǒng),每個(gè)服務(wù)器都值保存一部分?jǐn)?shù)據(jù),遷移很弱(memcache定位就是短期內(nèi)存,保存在memcache里面的數(shù)據(jù)本來就是不需要遷移的)。斷電丟失數(shù)據(jù)。
redis啟用內(nèi)存但是可以保證數(shù)據(jù)持久化、完整性和同步,即每個(gè)服務(wù)器都保存完整數(shù)據(jù)。這是因?yàn)閞edis的存儲(chǔ)分為內(nèi)存存儲(chǔ)、磁盤存儲(chǔ)和log文件三部分,配置文件中有三個(gè)參數(shù)對(duì)其進(jìn)行配置,斷電之后可以通過文件來恢復(fù)數(shù)據(jù);使用快照的方式進(jìn)行數(shù)據(jù)同步。
這一步相當(dāng)玉開啟服務(wù)端的memcache服務(wù)。在windows下開啟服務(wù)相當(dāng)簡單,直接打開這個(gè)exe程序就行了
如果只是布置服務(wù)端的話,上一步就已經(jīng)完成了。如果想要連接服務(wù)端的memcached服務(wù)并且使用命令的話,可以使用以下步驟:
1. 打開Telnet客戶端服務(wù)
然后就可以愉快地輸入你的命令了,如使用add命令來添加和get命令獲取值,key值已經(jīng)存在就會(huì)返回NOT_STORED提示,如果正確添加就會(huì)返回STORED提示。
注意:
命令無法退格,所以輸錯(cuò)就按enter重新輸入
memcached默認(rèn)端口11211
默認(rèn)memcache引用程序集會(huì)自帶一個(gè)log4net.dll文件以便錯(cuò)誤時(shí)可以記錄日志,這里并不需要記錄日志就不引用。
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客戶端提供的一個(gè)套接字連接池,是與Memcached服務(wù)器端交換數(shù)據(jù)的對(duì)象。 //SockIOPool在應(yīng)用程序啟動(dòng)時(shí)初始化一次就可以了,我們可以把這個(gè)工作放在 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","這是第一個(gè)數(shù)據(jù)",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
集群和分布式
數(shù)據(jù)庫集群:往往在同一局域網(wǎng),使用同一個(gè)IP,每個(gè)數(shù)據(jù)庫有完整數(shù)據(jù),難點(diǎn)是數(shù)據(jù)同步,遷移方便。
數(shù)據(jù)庫分布式:每個(gè)系統(tǒng)擁有部分?jǐn)?shù)據(jù),使用使用簡單,數(shù)據(jù)遷移麻煩。
Redis主從數(shù)據(jù)庫
主庫負(fù)責(zé)寫,從庫負(fù)責(zé)讀,壓力分流。
主庫掛掉,隨機(jī)選擇一個(gè)從庫成為主庫。
數(shù)據(jù)如何同步:快照。
memcache的key值最大255字符
memcached的塊最大1M
聯(lián)系客服