柚子快報(bào)激活碼778899分享:在C#中使用Redis
柚子快報(bào)激活碼778899分享:在C#中使用Redis
NoSql
NoSql概念
NoSQL,泛指非關(guān)系型的數(shù)據(jù)庫(kù)。隨著互聯(lián)網(wǎng)web2.0網(wǎng)站的興起, 歷史中—中國(guó)的網(wǎng)站----馬云--- 中國(guó)黃頁(yè),只能展示;用戶只能看到 傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)在處理web2.0網(wǎng)站(可以看,也可以做到寫(xiě)),特 別是超大規(guī)模和高并 發(fā)的SNS類型的web2.0純動(dòng)態(tài)網(wǎng)站已經(jīng)顯得力 不從心,出現(xiàn)了 很多難以克服的問(wèn)題。 而非關(guān)系型的數(shù)據(jù)庫(kù)則由于其本身的特點(diǎn)得到了非常迅速的發(fā)展。 NoSQL數(shù)據(jù)庫(kù)的產(chǎn)生就是為了解決大規(guī)模數(shù)據(jù)集合多重?cái)?shù)據(jù)種 類帶來(lái)的挑戰(zhàn),特別是大數(shù)據(jù)應(yīng)用難題。
非關(guān)系----基本上單純的保存數(shù)據(jù)----不支持多種數(shù)據(jù)之間的關(guān)系關(guān)系;
NoSql特點(diǎn)
早期: 只能存儲(chǔ)數(shù)據(jù)在內(nèi)存,性能搞,讀取快,成本高; 不能固化存儲(chǔ);
現(xiàn)在:基本上也都可以固化到硬盤(pán)---也可以做到持久化存儲(chǔ);
Redis
什么是Redis
Remot Dictionary Server---遠(yuǎn)程字典服務(wù)器 字典:key-value
官方地址:https://redis.io/
Redis 是一種開(kāi)源(BSD 許可)、內(nèi)存中數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),用作數(shù)據(jù)庫(kù)、緩 存和消息代理。 Redis 提供了數(shù)據(jù)結(jié)構(gòu),例如字符串、散列、列表、集合、帶有范圍查詢的 排序集合、 位圖、超級(jí)日志、地理空間索引和流。Redis 內(nèi)置復(fù)制、Lua 腳本、LRU 驅(qū) 逐、事務(wù)和 不同級(jí)別的磁盤(pán)持久化,并通過(guò)Redis Sentinel 和Redis Cluster 自動(dòng)分區(qū)提 供高可用性
Redis環(huán)境搭建
可以在我資料里面找Redis文件:--僅限Windows
.NET程序?qū)覴edis
.NET 對(duì)接Redis的有三大組件 NuGet程序下載:
StackExchange.Redis庫(kù)(不支持哨兵,主從和集群)ServiceStack.Redis (不支持哨兵,主從和集群)CsRedis (支持哨兵,主從和集群)-首選
第一步打開(kāi)Redis服務(wù):
出現(xiàn)以下就是正確的:
第二步:打開(kāi)Redis 客戶端查看是否有效
路徑:
驗(yàn)證:
能使用和輸出就證明成功。
安裝Redis可視化工具:
創(chuàng)建連接
測(cè)試連接Success
默認(rèn)是有15個(gè)db庫(kù)
剛才寫(xiě)的數(shù)據(jù),就在db0里面:
Redis數(shù)據(jù)結(jié)構(gòu)
五大數(shù)據(jù)結(jié)構(gòu):string(字符串),hash(哈希),list(列表),set(無(wú)序集合)及zset(有序集合)。
String類型
Key-Value存儲(chǔ)
字符串類型是Redis中最基本的數(shù)據(jù)存儲(chǔ)類型,它是一個(gè)由字節(jié)組成的序列,在Rediss 中是二進(jìn)制安全的。這意味著該類型可以接受任何格式數(shù)據(jù),如JPEG圖像數(shù)據(jù)和Json 對(duì)象說(shuō)明信息。它是標(biāo)準(zhǔn)的key-value,通常用于存儲(chǔ)字符串、整數(shù)和浮點(diǎn)。Value可容 納高達(dá)512MB的數(shù)據(jù)。 由于所有數(shù)據(jù)都在單個(gè)對(duì)象中,Redis 中的字符串操作速度非??臁;镜?Redis 命令 (如 SET、GET 和 DEL)允許您對(duì)字符串值執(zhí)行基本操作。
SET 鍵值 – 設(shè)置指定鍵的值。
GET 鍵 – 檢索指定鍵的值。
DEL 鍵 – 刪除給定鍵的值。
在C#中使用: 安裝NuGet :Caching.CSRedis 是必不可少的
"localhost,defaultDatabase=3,poolsize=3,tryit=0":連接字符串
localhost:Redis的Ip
defaultDatabase:默認(rèn)是第幾個(gè)庫(kù)
poolsize:最大連接數(shù)量
tryit:嘗試次數(shù)
string redisConnectionString = "localhost,defaultDatabase=3,poolsize=3,tryit=0";
string key = "key";
using (CSRedisClient cSRedisClient = new CSRedisClient(redisConnectionString))
{
cSRedisClient.Set(key, "小海study~~");
string sResult = cSRedisClient.Get(key);
};
寫(xiě)一個(gè)父類,包含一些常用的方法和數(shù)據(jù)庫(kù)連接:
public class RedisBase
{
protected CSRedisClient rds = new CSRedisClient("127.0.0.1,defaultDatabase=0,poolsize=3,tryit=0");
public RedisBase()
{
//rds.NodesServerManager.FlushAll();
}
///
/// 配置操作哪個(gè)節(jié)點(diǎn)
///
///
public void ConfigNode(string nodeIndex)
{
}
///
/// 刪除所有節(jié)點(diǎn)信息
///
public void FlushAll()
{
rds.NodesServerManager.FlushAll();
}
}
應(yīng)用程序場(chǎng)景:非常常見(jiàn)的場(chǎng)景用于計(jì)算站點(diǎn)訪問(wèn)量、當(dāng)前在線人數(shù)等
秒殺案例:
超賣:訂單數(shù)超過(guò)商品
秒殺:10件商品,大用戶量的來(lái)參與秒殺,同時(shí)來(lái)?yè)屵@個(gè)商品; 肯定是多個(gè)線程同時(shí)來(lái)操作
如果商品保存在數(shù)據(jù)庫(kù)中:
程序設(shè)計(jì):a.獲取商品數(shù)量 b.判斷是否還有庫(kù)存 c.如果有庫(kù)存---提示秒殺成功--減庫(kù)存 d.庫(kù)存再設(shè)置上去
注意:防止超賣---10商品參與秒殺,如果下了20個(gè)訂單~~
public class OversellTest : RedisBase
{
private static object Object_locker = new object();
public void Show()
{
int count = 10; //初始化有10件商品
//應(yīng)為是秒殺,并發(fā)很高~~ 多線程~~
//如果秒殺成功---必然要減庫(kù)存~~
List
for (int i = 0; i < 5000; i++)
{
tasklist.Add(Task.Run(() =>
{
int k = i;
//判斷倉(cāng)庫(kù)數(shù)據(jù)量和減庫(kù)存必須是原子性操作;原子的:不能拆分;
lock (Object_locker)
{
if (count > 0) //獲取庫(kù)存,判斷是否還有庫(kù)存
{
//Thread.Sleep(new Random().Next(10, 30)); //隨機(jī)休息
count = count - 1; //減庫(kù)存
Console.WriteLine($"用戶{k}參與秒殺,秒殺成功了。。。");
}
else
{
Console.WriteLine($"秒殺結(jié)束了...count值:{count}");
}
}
}));
}
Task.WaitAll(tasklist.ToArray());
Console.WriteLine($"所有秒殺結(jié)束后,庫(kù)存應(yīng)該為0 ,這里的Count:{count}");
}
private static bool IsGoOn = true;//秒殺活動(dòng)是否結(jié)束
public void ShowRedis()
{
FlushAll();
rds.Set("Stock", 10); //初始化商品的庫(kù)存量
for (int i = 0; i < 5000; i++)
{
int k = i;
Task.Run(() =>//每個(gè)線程就是一個(gè)用戶請(qǐng)求
{
if (IsGoOn)
{
//
long index = rds.IncrBy("Stock", -1); //自減1并且返回 ---這個(gè)是原則性操作,不會(huì)出現(xiàn)中間值; 不會(huì)有超賣問(wèn)題
if (index >= 0)
{
Console.WriteLine($"{k.ToString("000")}秒殺成功,秒殺商品索引為{index}");
}
else
{
if (IsGoOn)
{
IsGoOn = false;
}
Console.WriteLine($"{k.ToString("000")}秒殺失敗,秒殺商品索引為{index}");
}
}
else
{
Console.WriteLine($"{k.ToString("000")}秒殺停止......");
}
});
}
Console.Read();
}
}
Hash類型
Key-Value存儲(chǔ)
Redis hash 是一個(gè)鍵值(key=>value)對(duì)集合。Redis hash 是一個(gè) string 類型的 field 和 value 的映射表,hash 特別適合用于存儲(chǔ)對(duì)象。Redis的Hash結(jié)構(gòu)可以使你像在數(shù)據(jù)庫(kù) 中Update一個(gè)屬性一樣只修改某一項(xiàng)屬性值。和String略像,但value中存放的是一張表, 一般用于多個(gè)個(gè)體的詳細(xì)事項(xiàng)排列,String也可以做到,但要比hash麻煩許多。 哈希命令允許您獨(dú)立訪問(wèn)和更改單個(gè)或多個(gè)字段。
HSET – 將值映射到哈希中的鍵。
HGET – 檢索與哈希中的鍵關(guān)聯(lián)的各個(gè)值。
HGETALL – 顯示整個(gè)哈希內(nèi)容。
HDEL – 從哈希中刪除現(xiàn)有的鍵值對(duì)。
Hash二次封裝:
public class RedisHashService : RedisBase
{
#region Hash
///
/// [redis-server 3.2.0] 返回hash指定field的value的字符串長(zhǎng)度,如果hash或者field不存在,返回0.
///
/// 不含prefix前輟
/// 字段
///
public long HStrLen(string key, string field) => rds.HStrLen(key, field);
///
/// 刪除一個(gè)或多個(gè)哈希表字段
///
/// 不含prefix前輟
/// 字段
///
public long HDel(string key, params string[] fields) => rds.HDel(key, fields);
///
/// 查看哈希表 key 中,指定的字段是否存在
///
/// 不含prefix前輟
/// 字段
///
public bool HExists(string key, string field) => rds.HExists(key, field);
///
/// 獲取存儲(chǔ)在哈希表中指定字段的值
///
/// 不含prefix前輟
/// 字段
///
public string HGet(string key, string field) => rds.HGet(key, field);
///
/// 獲取存儲(chǔ)在哈希表中指定字段的值
///
///
/// 不含prefix前輟
/// 字段
///
public T HGet
///
/// 獲取在哈希表中指定 key 的所有字段和值
///
/// 不含prefix前輟
///
public Dictionary
///
/// 獲取在哈希表中指定 key 的所有字段和值
///
///
/// 不含prefix前輟
///
public Dictionary
///
/// 為哈希表 key 中的指定字段的整數(shù)值加上增量 increment
///
/// 不含prefix前輟
/// 字段
/// 增量值(默認(rèn)=1)
///
public long HIncrBy(string key, string field, long value = 1) => rds.HIncrBy(key, field, value);
///
/// 為哈希表 key 中的指定字段的整數(shù)值加上增量 increment
///
/// 不含prefix前輟
/// 字段
/// 增量值(默認(rèn)=1)
///
public decimal HIncrByFloat(string key, string field, decimal value) => rds.HIncrByFloat(key, field, value);
///
/// 獲取所有哈希表中的字段
///
/// 不含prefix前輟
///
public string[] HKeys(string key) => rds.HKeys(key);
///
/// 獲取哈希表中字段的數(shù)量
///
/// 不含prefix前輟
///
public long HLen(string key) => rds.HLen(key);
///
/// 獲取存儲(chǔ)在哈希表中多個(gè)字段的值
///
/// 不含prefix前輟
/// 字段
///
public string[] HMGet(string key, params string[] fields) => rds.HMGet(key, fields);
///
/// 獲取存儲(chǔ)在哈希表中多個(gè)字段的值
///
///
/// 不含prefix前輟
/// 一個(gè)或多個(gè)字段
///
public T[] HMGet
///
/// 同時(shí)將多個(gè) field-value (域-值)對(duì)設(shè)置到哈希表 key 中
///
/// 不含prefix前輟
/// key1 value1 [key2 value2]
///
public bool HMSet(string key, params object[] keyValues)
{
return rds.HMSet(key, keyValues);
}
///
/// 將哈希表 key 中的字段 field 的值設(shè)為 value
///
/// 不含prefix前輟
/// 字段
/// 值
///
public bool HSet(string key, string field, object value)
{
return rds.HSet(key, field, value);
}
///
/// 只有在字段 field 不存在時(shí),設(shè)置哈希表字段的值
///
/// 不含prefix前輟
/// 字段
/// 值(string 或 byte[])
///
public bool HSetNx(string key, string field, object value)
{
return rds.HSetNx(key, field, value);
}
///
/// 獲取哈希表中所有值
///
/// 不含prefix前輟
///
public string[] HVals(string key) => rds.HVals(key);
///
/// 獲取哈希表中所有值
///
///
/// 不含prefix前輟
///
public T[] HVals
///
/// 迭代哈希表中的鍵值對(duì)
///
/// 不含prefix前輟
/// 位置
/// 模式
/// 數(shù)量
///
public RedisScan<(string field, string value)> HScan(string key, long cursor, string pattern = null, long? count = null)
{
return rds.HScan(key, cursor, pattern, count);
}
///
/// 迭代哈希表中的鍵值對(duì)
///
///
/// 不含prefix前輟
/// 位置
/// 模式
/// 數(shù)量
///
public RedisScan<(string field, T value)> HScan
{
return rds.HScan
}
#endregion
}
常見(jiàn)的使用:
RedisHashService rds = new RedisHashService();
{
rds.FlushAll();
{
// 同時(shí)將多個(gè) field-value (域-值)對(duì)設(shè)置到哈希表 key 中
rds.HMSet("TestHDel", "string1", "name", "bytes1", "25", "class1", new UserInfo() { Name = "XiaoHai", Id = 123 });
//刪除一個(gè)或多個(gè)哈希表字段
rds.HDel("TestHDel", "string1", "bytes1", "class1");
// 查看哈希表 key 中,指定的字段是否存在
bool exists = rds.HExists("TestHExists", "null1");
Console.WriteLine(exists);
//將哈希表 key 中的字段 field 的值設(shè)為 value
rds.HSet("TestHExists", "null1", 1);
//查看哈希表 key 中,指定的字段是否存在
exists = rds.HExists("TestHExists", "null1");
Console.WriteLine(exists);
//刪除一個(gè)或多個(gè)哈希表字段
rds.HDel("TestHExists", "null1");
//查看哈希表 key 中,指定的字段是否存在
exists = rds.HExists("TestHExists", "null1");
}
{
string result1 = rds.HGet("TestHGet", "null1");
}
}
應(yīng)用程序場(chǎng)景:存儲(chǔ)部分更改數(shù)據(jù),如用戶信息、會(huì)話共享。
因?yàn)樵谑褂肦edis的時(shí)候,盡可能的去完成原子性操作,對(duì)于一個(gè)業(yè)務(wù)處理,盡量不要去搞多個(gè)操作;
Redis在WPF中的應(yīng)用
緩存數(shù)據(jù)
在需要的ViewModel中集成RedisBase
在RedisBase中封裝為一個(gè)通用的方法:
///
/// 優(yōu)先獲取redis中的數(shù)據(jù),如果沒(méi)有想要獲取的數(shù)據(jù)的數(shù)據(jù),就執(zhí)行委托
///
///
/// redis的key
/// 包裝查詢數(shù)據(jù)庫(kù)的邏輯
///
protected T GetCacheData
{
// 如果rds中沒(méi)有數(shù)據(jù)就執(zhí)行委托(執(zhí)行數(shù)據(jù)庫(kù)),否則就執(zhí)行rds
T t = rds.Get
if (t == null) // redis里面沒(méi)有數(shù)據(jù)
{
t = func.Invoke();
rds.Set(key, t);
}
return t;
}
然后再ViewModel中調(diào)用這個(gè)方法:
List
string key = "scoreList";
scoreList = GetCacheData(key, () =>
{
return _scoreInfoService.Set
});
ScoreList.Clear();
//賦值
scoreList.ForEach(x => ScoreList.Add(x));
柚子快報(bào)激活碼778899分享:在C#中使用Redis
推薦文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。