C# 讀寫redis C#讀寫實時資料庫
本文將使用一個gitHub開源的元件技術來讀寫redis資料,使用的是基於乙太網的TCP/IP實現,不需要額外的元件,讀取操作只要放到後臺執行緒就不會卡死執行緒,本元件支援超級方便的高效能讀寫操作
github地址:https://github.com/dathlin/HslCommunication 如果喜歡可以star或是fork,還可以打賞支援。
官網地址:http://www.hslcommunication.cn/ 打賞請認準官網
技術支援QQ群(主要面向工業軟體及HSL元件的):592132877 (元件的版本更新細節也將第一時間在群裡釋出)最後編輯日期:2018年11月21日 19:05:49
裡面各種小夥伴,為您解答資料互動,程式設計技巧,如果對本介面提供的API有任何疑問,都可以加群諮詢,如果有更好的建議,歡迎提出。
Redis是什麼?
這個是一個實時的資料庫技術,主要採用鍵值操作來儲存資料的。官網是 https://redis.io/ ,官方的解釋為(摘自百度百科):
redis是一個key-value 儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list( 連結串列)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。這些 資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,為了保證效率,資料都是快取在記憶體中。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。 Redis 是一個高效能的key-value資料庫。 redis的出現,很大程度補償了
安裝redis伺服器
我們在使用前需要安裝伺服器,一般的windows的伺服器來自於微軟的專案:
https://github.com/MicrosoftArchive/redis/releases
雖然微軟的專案只更新到了 redis3.2 版本。但是已經足夠我們日常的使用了。
安裝完成後,會自動的啟動伺服器。我們可以開啟cmd來測試
伺服器搭好後就可以使用C#來操作了。
再次隨便聊聊,C#有個還可以的redis類庫叫StackExchange.Redis
https://github.com/StackExchange/StackExchange.Redis
但是這個類庫呢,總有些莫名其妙的問題,尤其是超時問題,始終沒有得到很好的解決,所以我整合實現了redis的基本操作,給大家一個更多的選擇。支援.net framework和.net standard
當你的程式實現了redis之後,程式架構變成了:
此處的redis相當於高速的資料快取,可以部署在伺服器的電腦上,可以部署在雲端等等,任意其他的電腦上面。
接下來演示使用HSL來進行操作
從NUGET安裝
Install-Package HslCommunication
關於兩種模式
在PLC端,包括三菱,西門子,歐姆龍,AB以及Modbus Tcp客戶端的訪問器上,都支援兩種模式,短連線模式和長連線模式,現在就來解釋下什麼原理。
短連線:每次讀寫都是一個單獨的請求,請求完畢也就關閉了,如果伺服器的埠僅僅支援單連線,那麼關閉後這個埠可以被其他連線複用,但是在頻繁的網路請求下,容易發生異常,會有其他的請求不成功,尤其是多執行緒的情況下。
長連線:建立一個公用的連線通道,所有的讀寫請求都利用這個通道來完成,這樣的話,讀寫效能更快速,即時多執行緒呼叫也不會影響,內部有同步機制。如果伺服器的埠僅僅支援單連線,那麼這個埠就被佔用了,比如三菱的埠機制,西門子的Modbus tcp埠機制也是這樣的。以下程式碼預設使用長連線,效能更高,還支援多執行緒同步。
在短連線的模式下,每次請求都是單獨的訪問,所以沒有重連的困擾,在長連線的模式下,如果本次請求失敗了,在下次請求的時候,會自動重新連線伺服器,直到請求成功為止。另外,儘量所有的讀寫都對結果的成功進行判斷。
DEMO示例:
下面的一個專案是這個元件的訪問測試專案,您可以進行初步的訪問的測試,免去了您寫測試程式的麻煩,三菱的介面和西門子的介面幾乎是一致的。可以同時參考。該專案位於本篇文章開始處的Gitbub原始碼裡面的
下載地址為:HslCommunicationDemo.zip
可以用來瀏覽你的redis到底有什麼資料,以及這個資料是什麼,初步支援了 string,list,hash 資料型別。
當你寫入的key名字帶有:(英文狀態)時。這個瀏覽器還會對資料進行分類整理、
關於redis指令
http://doc.redisfans.com/index.html
原生的指令有很多,這個庫裡也是支援了大部分的操作,如果你需要的功能還沒有支援,比如 獲取一個鍵的資料資訊, 將指令引數按照空格輸入進去就行
private void button16_Click( object sender, EventArgs e ) { OperateResult<string> read = redisClient.ReadCustomer("GET A" ); if (read.IsSuccess) { // read.Content 就是從伺服器返回的資料 例如為 $2\r\n11\r\n 需要自己提煉真實的資料 MessageBox.Show( read.Content ); } else { MessageBox.Show( read.Message ); } }
下面列舉一些示例
簡單使用
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using HslCommunication.Enthernet.Redis; using HslCommunication; namespace WindowsFormsApp3 { public partial class Form1 : Form { public Form1( ) { InitializeComponent( ); } private RedisClient redisClient = new RedisClient( "127.0.0.1", 6379, "" ); private void button1_Click( object sender, EventArgs e ) { OperateResult<string> read = redisClient.ReadKey( "a" ); if (read.IsSuccess) { MessageBox.Show( read.Content ); } else { MessageBox.Show( read.Message ); } } } }
結果如下:
顯示的值就是我們之前寫入的操作,主要,redis區分大小寫,你讀 A 和讀 a 是不一樣的。
上述的程式碼已經進行了嚴格的驗證,上面情況會讀取失敗呢?網路異常或是 a 不存在
我們來看看寫入鍵值:
private void button2_Click( object sender, EventArgs e ) { OperateResult write = redisClient.WriteKey( "a", "abcde" ); }
上述就沒有對寫入成功與否進行驗證,只要是網路正常基本都是成功的。
寫完後我們再讀取一次:
如果想寫入一個有生命週期的key,比如100s後自動消失的key
private void button3_Click( object sender, EventArgs e ) { OperateResult write = redisClient.WriteExpireKey( "b", "abcde", 100 ); }
這樣就寫入了一個帶生命週期的key了。
批量讀寫
如果想要一次性寫入或是讀取很多鍵值:
private void button4_Click( object sender, EventArgs e ) { OperateResult<string[]> read = redisClient.ReadKey( new string[] { "a", "b" } ); if (read.IsSuccess) { string[] result = read.Content; } else { MessageBox.Show( read.Message ); } }
寫入的操作如下:
private void button5_Click( object sender, EventArgs e ) { redisClient.WriteKey( new string[] { "a", "b" }, new string[] { "abcde", "ihsdasd" } ); }
此處省略了對寫入結果的驗證,為了安全起見,你應該新增。
獲取舊值,並設定一個新的值進去
private void button6_Click( object sender, EventArgs e ) { OperateResult<string> read = redisClient.ReadAndWriteKey( "a", "aaaaaa" ); if (read.IsSuccess) { MessageBox.Show( read.Content ); } else { MessageBox.Show( read.Message ); } }
遞增遞減操作。
這個基本功能也是很常見的、
我們先寫 BB 為 0
然後我們再給這個值加1,並返回1的操作。
private void button7_Click( object sender, EventArgs e ) { OperateResult<int> read = redisClient.IncrementKey( "BB" ); if (read.IsSuccess) { MessageBox.Show( "Value:" + read.Content ); } else { MessageBox.Show( read.Message ); } }
同理也支援減一操作,增加指定的資料操作,減去指定的資料操作。
列表操作
redis也支援儲存陣列資料資訊
我們建立一個數組,並往裡面塞東西,當然支援從陣列的左側塞,也支援從右側塞,下面就是左側的例子
private void button8_Click( object sender, EventArgs e ) { redisClient.ListLeftPush( "C", "123" ); }
這樣就建立了一個數組,陣列資料的讀取,並不是get了,而是變成了 LRANGE 0 -1 代表讀取整個的陣列
用程式碼來讀取就是
private void button9_Click( object sender, EventArgs e ) { OperateResult<string[]> read = redisClient.ListRange( "C", 0, -1 ); if (read.IsSuccess) { // 列表變成了一個數組資訊 string[] result = read.Content; } else { MessageBox.Show( read.Message ); } }
當然,當你的陣列很大時。比如1000個長度時,你可以讀取中間任意個數組。
獲取陣列長度
當你不知道一個數組的長度,不想在讀取所有的陣列資訊的情況下,讀取到長度
private void button10_Click( object sender, EventArgs e ) { int length = redisClient.GetListLength( "C" ).Content; // 此處就是1 }
獲取指定索引的資料
private void button11_Click( object sender, EventArgs e ) { string read = redisClient.ReadListByIndex( "C", 0 ).Content; }
注意,當C不是list時,會引發錯誤。
修剪列表資訊
當陣列過長時,我們可以修剪陣列來達到收縮的目的
private void button12_Click( object sender, EventArgs e ) { redisClient.ListTrim( "C", 0, 9 );// 10個長度,保留0-9索引的資料 }
返回並移除開始處的列表
private void button13_Click( object sender, EventArgs e ) { OperateResult<string> read = redisClient.ListLeftPop( "C" ); if (read.IsSuccess) { MessageBox.Show( read.Content ); } else { MessageBox.Show( read.Message ); } }
移除並返回測試的也是可以的。
雜湊值讀寫
雜湊值的意思是一個鍵的值是由多個鍵值組成的
private void button14_Click( object sender, EventArgs e ) { redisClient.WriteHashKey( "D", "A", "1" ); redisClient.WriteHashKey( "D", "B", "2" ); redisClient.WriteHashKey( "D", "C", "3" ); }
相當於是鍵 D 的域 A 寫入1, B寫入2,C寫入3
你一次可以讀取所有的C的域集合,或是值集合,或是域+值集合,下面演示了一個示例,讀取域+值集合
private void button15_Click( object sender, EventArgs e ) { OperateResult<string[]> read = redisClient.ReadHashKeyAll( "C" ); if (read.IsSuccess) { // 列表變成了一個域+值資訊 // A // 1 // B // 2 // C // 3 string[] result = read.Content; } else { MessageBox.Show( read.Message ); } }