Redis 介紹學習

来源:https://www.cnblogs.com/whitebai/archive/2019/10/14/11670631.html
-Advertisement-
Play Games

1、Redis 簡介 Redis 是一個支持數據結構更多的鍵值對資料庫。它的值不僅可以是字元串等基本數據 類型,也可以是類對象,更可以是 Set、List、計數器等高級的數據結構。 Memcached 也可以保存類似於 Set、List 這樣的結構,但是如果說要向 List 中增加元素, Memca ...


1、Redis 簡介

Redis 是一個支持數據結構更多的鍵值對資料庫。它的值不僅可以是字元串等基本數據

類型,也可以是類對象,更可以是 Set、List、計數器等高級的數據結構。
Memcached 也可以保存類似於 Set、List 這樣的結構,但是如果說要向 List 中增加元素, Memcached 則需要把 List 全部元素取出來,然後再把元素增加進去,然後再保存回去,不 僅效率低,而且有併發訪問問題。

Redis 內置的 Set、List 等可以直接支持增加、刪除元素的操作,效率很高,操作是原子的。

Memcached 數據存在記憶體中,memcached 重啟後數據就消失;而 Redis 會把數據持久

化到硬碟中,Redis 重啟後數據還存在。
2、Redis 的安裝
redis for windows >=2.8 的版本支持直接安裝為 windows 服務 https://github.com/MicrosoftArchive/redis
如果下載 msi 自動裝完服務,如果下載 zip 需要按照下麵的方法安裝為服務: https://raw.githubusercontent.com/MSOpenTech/redis/3.0/Windows%20Service%20Documenta tion.md 

3、redis 的優點:

  1. 1)  支持 string、list、set、geo 等複雜的數據結構。

  2. 2)  高命中的數據運行時是在記憶體中,數據最終還是可以保存到磁碟中,這樣伺服器重啟之後數據還在。

  3. 3)  伺服器是單線程的,來自所有客戶端的所有命令都是串列執行的,因此不用擔心併發修改(串列操作當然還是有併發問題)的問題,編程模型簡單;

  4. 4)  支持消息訂閱/通知機制,可以用作消息隊列;

  5. 5)  Key、Value 最大長度允許 512M;

4、redis 的缺點:

  1. 1)  Redis 是單線程的,因此單個 Redis 實例只能使用一個 CPU 核,不能充分發揮伺服器的性能。可以在一臺伺服器上運行多個 Redis 實例,不同實例監聽不同埠,再互相組成集群。

  2. 2)  做緩存性能不如 Memcached;

5、Memcached 的優點:
       1) 多線程,可以充分利用 CPU 多核的性能;

       2) 做緩存性能最高;

6、Memcached 的缺點:

  1. 1)  只能保存鍵值對數據,鍵值對只能是字元串,如果有對象數據只能自己序列化成 json字元串;

  2. 2)  數據保存在記憶體中,重啟後會丟失;

  3. 3)  Key 最大長度 255 個字元,Value 最長 1M。

7、總結
      Memcached 只能當緩存伺服器用,也是最合適的;Redis 不僅可以做緩存伺服器(性能沒有 Memcached 好),還可以存儲業務數據。

8、redis 命令行管理客戶端:

       1)直接啟動 redis 安裝目錄下的 redis-cli 即可。不用管噁心的自動提示。 執行 set name yzk,就是設置鍵值對 name=yzk 執行 get name 就是查找名字是 name 的值;  keys *是查找所有的 key  key *n*是查找所有名字中含有 n 的 key

       2) 和 Redis 一樣,Redis 也是不同系統放到 Redis 中的數據都是不隔離的,因此設定 Key 的 時候也要選擇好 Key。
       3) Redis 伺服器預設建了 16 個資料庫,Redis 的想法是讓大家把不同系統的數據放到不同 的資料庫中。但是建議大家不要這樣用,因為 Redis 是單線程的,不同業務都放到同一個 Redis 實例的話效率就不高,建議放到不同的實例中。

          因此儘量只用預設的 db0資料庫命令行下可以用 select0、select1 這樣的指令切換資料庫,最高為15。試試在不同數據 庫下新建、查詢數據。

       4) 瞭解的常用的幾個命令就可以。所有對數據的操作都可以通過命令行進行,後面講 的.net 操作 Redis 的驅動其實就是對這些命令的封裝。

9、redis GUI 管理客戶端

     GUI 客戶端非常多,個人推薦使用 RedisDesktopManager安裝後點擊【Connect to Redis Server】連接伺服器。展開節點可以看到所有的 Key,雙擊 Key 可以查看 Key 的值。在根節點上點右鍵,選擇 【Console】,這樣就可以輸入命令。

10、.net 操作 Redis

     用 StackExchange.Redis ,而不是 ServiceStack.Redis,因為 StackExchange.Redis 依賴組件 少,而且操作更接近原生的 redis 操作,ServiceStack 封裝的太厲害,而且有過收費的“前科”。

Install-Package StackExchange.Redis
using (ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379")) {

IDatabase db = redis.GetDatabase();//預設是訪問 db0 資料庫,可以通過方法參數指定數 字訪問不同的資料庫

db.StringSet("Name", "abc");

}

支持設置過期時間:db.StringSet("name", "rupeng.com", TimeSpan.FromSeconds(10)) 獲取數據:string s = db.StringGet("Name")如果查不到則返回 null

Redis 里所有方法幾乎都支持非同步,比如 StringGetAsync()、StringSetAsync(),儘量用非同步方法。

      註意看到訪問的參數、返回值是 RedisKey、RedisValue 類型,進行了運算符重載,可以和 string、 byte[]之間進行隱式轉換。

11、Key 操作
       Key 操作:因為 Redis 里所有數據類型都是用 KeyValue 保存,因此 Key 操作針對所有數據類型, KeyDelete(RedisKey key):根據 Key 刪除;KeyExists(RedisKey key)

      判斷 Key 是否存在,儘量不要用, 因為會有併發問題;KeyExpire(RedisKey key, TimeSpan?  expiry)、KeyExpire(RedisKey key, DateTime? expiry)設置過期時間;
12、數據類型

       Redis 支持的數據結構:string、list、set、sortedset、hash、geo(redis 3.2 以上版本)。對應 的 Redis 客戶端里的方法都是 StringXXX、HashXXX、GeoXXX 等方法。

      不同數據類型的操作方 法不能混用,比如不能用 ListXXX 寫入的值用 StringXXX 去讀取或者寫 入等操作。
13、String 類型

      可以用 StringGet、StringSet 來讀寫鍵值對,是基礎操作StringAppend(RedisKey key, RedisValue value):向 Key 的 Value 中附加內容,不存在則新建; 可以用作計數器:db.StringIncrement("count", 2.5);

      給 count 這個計數器增加一個值,如果不存在則從 0 開始加;db.StringDecrement("count",1)計數器減值;獲取還是用 StringGet()獲取字元串類型的 值。比如可以用這個來計算新聞點擊量、點贊量,效率非常高。     

private static string XinWen_Prefix = "WWW_XinWen_";

public async Task<ActionResult> Index(int id)

{
using (ConnectionMultiplexer redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379")) {

IDatabase db = redis.GetDatabase();//預設是訪問 db0 資料庫,可以通過方法參數指定數字訪 問不同的資料庫

//以 ip 地址和文章 id 為 key
string hasClickKey = XinWen_Prefix + Request.UserHostAddress + "_" + id;

//如果之前這個 ip 給這個文章貢獻過點擊量,則不重覆計算點擊量 if(await db.KeyExistsAsync(hasClickKey)==false)
{

await db.StringIncrementAsync(XinWen_Prefix + "XWClickCount" + id, 1); //記錄一下這個 ip 給這個文章貢獻過點擊量,有效期一天 db.StringSet(hasClickKey, "a", TimeSpan.FromDays(1));

}

RedisValue clickCount = await db.StringGetAsync(XinWen_Prefix + "XWClickCount" + id); XinWenModel model = new XinWenModel();
model.ClickCount = Convert.ToInt32(clickCount);
return View(model);

}

return View(); }

14、list 類型

      Redis 中用 List 保存字元串集合。 比如可以把聊天記錄保存到 List 中;商品的物流信息記錄。也  可以當成雙向隊列或者雙向棧用,list 長度是無限。

      ListLeftPush(RedisKey key, RedisValue value)從左側壓棧;RedisValue ListLeftPop(RedisKey key) 從左側彈出;

      ListRightPush(RedisKey key, RedisValue value ) 從右側壓棧;RedisValue ListRightPop(RedisKey key) 從右側彈出;

      RedisValue ListGetByIndex(RedisKey key, long index)獲取 Key 為 key 的 List 中第 index 個元素的值; long ListLength(RedisKey key) 獲取 Key 為 key 的 List 中元素個數;儘量不要用 ListGetByIndex、 ListLength 因為會有併發問題;。

     如果是讀取而不 Pop,則使用 ListRange:RedisValue[] ListRange(RedisKey key, long start = 0, long stop = -1)。不傳 start、end 表示獲取所有數據。指定之後則獲取某個範圍。

      可以把 Redis 的 list 當成消息隊列使用,比如向註冊用戶發送歡迎郵件的工作,可以在註冊的流 程中把要發送郵件的郵箱放到 list 中,另一個程式從 list 中 pop 獲取郵件來發送。

      生產者、消費者模式。把生產過程和消費過程隔離。

15、set 類型
      如大家所知,set 是一種元素不重覆的集合。 SetAdd(RedisKey key, RedisValue value)向 set 中增加元素

      bool SetContains(RedisKey key, RedisValue value) 判斷 set 中是否存在某個元素; long SetLength(RedisKey key) 獲得 set 中元素的個數;

      SetRemove(RedisKey key, RedisValue value)從 set 中刪除元素;

      RedisValue[] SetMembers(RedisKey key)獲取集合中的元素;

      如果使用 set 保存封禁用 id 等,就不用做重覆性判斷了。

      註意 set 不是按照插入順序遍歷的,而是按照自己的一個存儲方式來遍歷,因為沒有保存插入的 順序。

16、sortedset
     如果對於數據遍歷順序有要求,可以使用 sortedset,他會按照打分來進行遍歷。 SortedSetAdd(RedisKey key, RedisValue member, double score) 在 key 這個 sortedset 中增加member,並且給這個 member 打分,如果 member 已經存在,則覆蓋之前的打分;       doubleSortedSetIncrement(RedisKeykey,RedisValuemember,doublevalue) 給key中member這一項增加 value 分;

     double SortedSetDecrement(RedisKey key, RedisValue member, double value):給 key 中 member 這一項減 value 分; 

     SortedSetEntry[] SortedSetRangeByRankWithScores(RedisKey key, long start = 0, long stop = -1,Orderorder=Order.Ascending) 根據排序返回sortedset中的元素以及元素的打分,start、stop用來分頁 查詢、order 用來指定排序規則。

     測試:

db.SortedSetIncrement("Hotwords", "test", 1);

db.SortedSetIncrement("Hotwords", "test", 1); db.SortedSetIncrement("Hotwords", "test", 1); db.SortedSetIncrement("Hotwords", "楊中科", 1); db.SortedSetIncrement("Hotwords", "侯寶林", 1); db.SortedSetIncrement("Hotwords", "侯寶林", 1);
SortedSetEntry[] items = db.SortedSetRangeByRankWithScores("Hotwords"); foreach(var item in items)

{
Console.WriteLine(item.Element+"="+item.Score);

}

 RedisValue[] SortedSetRangeByRank(RedisKey key, long start = 0, long stop = -1, Order order =Order.Ascending) 根據打分排序返回值,可以根據序號查詢其中一部分;

   RedisValue[] SortedSetRangeByScore(RedisKey key, double start = double.NegativeInfinity, doublestop = double.PositiveInfinity, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1)

    根據打分排序返回值,可以只返回 start- stop 這個範圍的打分;

    sortedset 應用場景:

      1) 用戶每搜一次一個關鍵詞,就給這個關鍵詞加一分;展示熱搜的時候就把前 N 個獲取出來就行了;

      2) 高積分用戶排行榜;

      3) 熱門商品;

       4) 給寶寶投票;

17、Hash

      相當於 value 又是一個“鍵值對集合”或者值是另外一個 Dictionary。 沒想到有什麼應用場景。

18、Geo 類型

Geo 是 Redis 3.2 版本後新增的數據類型,用來保存興趣點(POI,point of interest)的坐標信息。

可以實現計算兩 POI 之間的距離、獲取一個點周邊指定距離的 POI。 下麵添加興趣點數據,”1”、”2”是點的主鍵,點的名稱、地址、電話等存到其他表中。

db.GeoAdd("ShopsGeo", new GeoEntry(116.34039, 39.94218,"1"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340934, 39.942221, "2"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.341082, 39.941025, "3"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340848, 39.937758, "4"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.342982, 39.937325, "5"));

db.GeoAdd("ShopsGeo", new GeoEntry(116.340866, 39.936827, "6"));

GeoRemove(RedisKey key, RedisValue member)刪除一個點

查詢兩個 POI 之間的舉例:double? dist = db.GeoDistance("ShopsGeo", "1", "5", GeoUnit.Meters);// 最後一個參數為距離單位根據點的主鍵獲取坐標:GeoPosition? pos = db.GeoPosition("ShopsGeo", "1")

獲取一個 POI 周邊的 POI:

GeoRadiusResult[] results = db.GeoRadius("ShopsGeo", "2", 200, GeoUnit.Meters);//獲取”2”這個周邊 200 米範圍內的 POI
foreach(GeoRadiusResult result in results)
{

Console.WriteLine("Id="+result.Member+",位置"+result.Position+",距離"+result.Distance); }

  獲取一個坐標(這個坐標不一定是 POI)周邊的 POI:

GeoRadiusResult[] results = db.GeoRadius("ShopsGeo", 116.34092, 39.94223, 200, GeoUnit.Meters);// 獲 取(116.34092, 39.94223)這個周邊 200 米範圍內的 POI
foreach(GeoRadiusResult result in results)
{

Console.WriteLine("Id="+result.Member+",位置"+result.Position+",距離"+result.Distance);

}

     Geo Hash 原理:http://www.cnblogs.com/LBSer/p/3310455.html

19、Redis 的批量操作

如果一次性操作很多,會很慢,那麼可以使用批量操作,兩種方式: 1)幾乎所有的操作都支持數組類型,這樣就可以一次性操作多條數據:比如

GeoAdd(RedisKey key, GeoEntry[] values)、SortedSetAdd(RedisKey key, SortedSetEntry[] values) 2) 如果一次性的操作不是簡單的同類型操作,那麼就要使用批量模式:
IBatch batch = db.CreateBatch();
db.GeoAdd("ShopsGeo1", new GeoEntry(116.34039, 39.94218, "1"));

db.StringSet("abc", "123"); batch.Execute();

會把當前連接的 CreateBatch()、Execute()之間的操作一次性提交給伺服器。

20、redis 分散式鎖

     多線程中的 lock 等的作用範圍是當前的程式範圍內的,如果想跨多台伺服器的鎖(盡量避免這樣搞),就要使用分散式鎖。

      

RedisValue token = Environment.MachineName;

//實際項目秒殺此處可換成商品 ID

if (db.LockTake("mylock", token, TimeSpan.FromSeconds(10)))//第三個參數為鎖超時時間,鎖占 用最多 10 秒鐘,超過 10 秒鐘如果還沒有 LockRelease,則也自動釋放鎖,避免了死鎖
{

try {

} finally {

db.LockRelease("mylock", token); }

} else {

Console.WriteLine("獲得鎖失敗"); 
}

  

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下麵是一些ssh agent的資料簡要摘錄,網路上的相關的文章已經很多了: ssh 推薦的登錄方式是使用私鑰登錄。但是如果生成私鑰的時候,設置了口令(passphrase),每次登錄時需要輸入口令也很麻煩。可以通過 ssh-agent 來管理私鑰,把私鑰載入進記憶體,之後便不用再輸入私鑰。 ssh-a ...
  • 一、基礎知識 1、cortex-m3支持256個中斷,其中包含了16個內核中斷,240個外部中斷 2、STM32只有84個中斷,包括16個內核中斷和68個可屏蔽中斷 3、STM32F103上只有60個可屏蔽中斷(本文重點講解F103) 4、先占優先順序和次占優先順序 先占優先順序(搶占優先順序):搶占優先順序 ...
  • 此題的題意很清晰: 日期相差一天(使用 ); 今天的溫度大於昨天。 ...
  • sql語句如下: SELECT * from A LEFT JOIN B ON A.aID = B.bID ...
  • 一、事務和隔離級別 事務的概念:事務是把對資料庫的一系列操作都看做一個整體,要麼全部成功,要麼全部失敗,利用事務我們可以保證資料庫的完整性,事務具有原子性。 隔離級別:隔離級別定義了事務與事務之間的隔離距離。 臟讀(dirty read):當一個事務讀取另一個事務未提交的修改時,產生臟讀。 不可重覆 ...
  • 一.mysql事件隔離級別 1未提交讀(READUNCOMMITTED) 另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據(臟讀)( 隔離級別最低,併發性能高 ) 2..提交讀(READCOMMITTED) 本事務讀取到的是最新的數據(其他事務提交後的)。問題是,在 ...
  • 前言 鏈表提供了高效的節點重排能力, 以及順序性的節點訪問方式, 並且可以通過增刪節點來靈活地調整鏈表的長度。 作為一種常用數據結構, 鏈表內置在很多高級的編程語言裡面, 因為 Redis 使用的 C 語言並沒有內置這種數據結構, 所以 Redis 構建了自己的鏈表實現。 大家可以把Redis的鏈表 ...
  • 1 Kylin是什麼 今天,隨著移動互聯網、物聯網、AI等技術的快速興起,數據成為了所有這些技術背後最重要,也是最有價值的“資產”。如何從數據中獲得有價值的信息?這個問題驅動了相關技術的發展,從最初的基於文件的檢索、分析程式,到數據倉庫理念的誕生,再到基於資料庫的商業智能分析。而現在,這一問題已經變 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...