C# redis操作(StackExchange.Redis )
参考:https://www.cnblogs.com/wzh2010/p/17205387.html
参考:https://www.runoob.com/redis/redis-keys.html
测试redis, 使用StackExchange.Redis 的api, 实现发布/订阅, 存放值, 分布式锁, 排序
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using StackExchange.Redis; namespace RedisTest { struct Msg { public string chanel; public byte[] msg; public Msg(string chanel, byte[] msg) { this.chanel = chanel; this.msg = msg; } } public partial class Form1 : Form { ConnectionMultiplexer redisClient = ConnectionMultiplexer.Connect("127.0.0.1:6359,allowadmin=true,password=12345,keepAlive=180"); ISubscriber m_subscriber; IDatabase m_database; Queue<Msg> m_msgQueue = new Queue<Msg>(); bool m_Closed = false; private ManualResetEvent m_ManualResetEvent = new ManualResetEvent(false); public Form1() { InitializeComponent(); } private void DoJob() { while (true) { if (m_msgQueue.Count == 0) { m_ManualResetEvent.WaitOne(); if(m_Closed) { break; } } else { Action action = () => { var msg = m_msgQueue.Dequeue(); string str = UTF8Encoding.UTF8.GetString(msg.msg); this.txtResult.Text += "chanel:" + msg.chanel + "," + str + "\r\n"; }; this.txtResult.Invoke(action); } } } private void Form1_Load(object sender, EventArgs e) { Thread thread = new Thread(DoJob); thread.Start(); //127.0.0.1:6379,allowadmin=true,password=12345,keepAlive=180 // 设置订阅 m_subscriber = redisClient.GetSubscriber(); // 设置数据库 m_database = redisClient.GetDatabase(0); m_subscriber.Subscribe("testchanel", (chanel, message)=>{ m_msgQueue.Enqueue(new Msg(chanel, message)); m_ManualResetEvent.Set(); }); /* m_subscriber.Subscribe("bb", (chanel, message) => { // lamda表达式转delegate Action action = () => { this.txtResult.Text += "chanel:" + chanel + "," + message + "\r\n"; }; this.txtResult.Invoke(action); }); */ } private void button1_Click(object sender, EventArgs e) { string str = this.txtSend.Text + DateTime.Now.Ticks; m_subscriber.Publish("testchanel", str); /* byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(str); m_subscriber.Publish("bb", bytes); */ } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { m_Closed = true; m_ManualResetEvent.Set(); } private void btnSaveLoad_Click(object sender, EventArgs e) { // 参考:https://www.cnblogs.com/wzh2010/p/17205387.html // 参考:https://www.runoob.com/redis/redis-keys.html // 这个可以用来做分布式锁, 设置某个键, 并加超时时间, 并且可以设置只有不存在时才处理 // SETNX 是 set if not exists 的缩写,当且仅当 key 不存在时,则设置 value 给这个key。若给定的 key 已经存在,则 SETNX 不做任何动作。 // 命令的返回值说明:1:说明该进程获得锁,将 key 的值设为 value 0:说明其他进程已经获得了锁,进程不能进入临界区。 // SET lock.user_063105015 1 NX PX 60000 // NX:就是Not Exist,表示只有用户编号为 063105015 不存在的时候才可以 SET 成功,并且只有单个线程可以获取锁; // PX 60000:表示对这个锁设置一个60s的过期时间。 bool ret = m_database.StringSet("mykeystring", 33, new TimeSpan(0, 0, 5), When.NotExists); m_database.SetAdd("myset", "set1"); m_database.SetAdd("myset", "set2"); m_database.ListRightPush("mylist", 1); m_database.ListRightPush("mylist", 2); // 可以使用StringGetSet, 取出旧值, 设置新值 // 对应redis, GetSet命令, 可以使用这个来实现 分布式锁, 返回原来的值, 并且设置新的值 // 下面的例子, 可以在拿的值判断拿到的值是否为1, 如果为1, 则说明被其它人设置了, 如果不是1, 则说明没被其它人操作, // 操作完删除key, 或更新成其它值 var val = m_database.StringGetSet("myGetSetKey", 1); // 这个是给key加个超时, 防止程序异常中断, 死锁 对应redis EXPIRE key seconds, expire key 时间戳 // GETEX命令同样也是Redis 6.2.0中新增的命令,它用于获取指定键值对的值,并设置或移除该键值对的过期时间。 // 这儿测试时用的3.几的reids, 下面执行不了 // //var val2 = m_database.StringGetSetExpiry("myGetSetKey", new TimeSpan(0, 0, 3)); m_database.StringAppend("mystring", "str1"); m_database.StringAppend("mystring", "str2"); var entery1 = new HashEntry("a", 1); var entery2 = new HashEntry("b", 2); m_database.HashSet("myhashkey", new HashEntry[] { entery1, entery2 }); //redis zset排序 m_database.SortedSetAdd("myzset", "一", 8); m_database.SortedSetAdd("myzset", "二", 9); m_database.SortedSetAdd("myzset", "三", 7); long? rank = m_database.SortedSetRank("myzset", "二"); //这儿返回0, 第一名 } } }