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