Redis学习笔记
启动Redis服务
redis-server.exe闪退解决方案
运行redis-server.exe闪退,运行redis-cli.exe被拒绝连接,解决方案:
在redis目录下进入控制台,输入"redis-server.exe redis.windows.conf"后界面如下:
此处使用了默认的redis.windows-service.conf,IP地址为127.0.0.1,端口号为6379;如需修改可修改该配置文件的57行和80行,或直接更换配置文件。
此时再运行redis-cli.exe输入ping,如回应PONG则连接成功。
通过操作系统服务管理启动Redis服务
将Redis配置为Windows服务,可以通过系统服务管理器启动、停止、重启服务,也可以设置其随系统启动而自动运行。可参考Windows Service Documentation.docx。
配置为Windows服务
- 使用快捷键Win+R打开“运行”对话框,输入“powershell“。
3.进入Redis所在目录,假设Redis位处D:\Redis-x64-3.2.100
4.输入 “.\redis-server --service-install --service-name ChargingGPT与redis.windows-service.conf” 即可将redis配置为Windows服务。
卸载/开始/停止方法
可通过系统服务管理器操作,也可通过PowerShell操作。
开始
输入”.\redis-server --service-start --service-name AnyServiceName“ 。
停止
输入“.\redis-server --service-stop --service-name AnyServiceName“。
卸载
输入” .\redis-server --service-uninstall --service-name AnyServiceName“。(需要先暂停,否则不起作用)
通过bat脚本配置
创建文件RedisPowerShellDescript.ps1,文件内容:
新建bat脚本,增加语句“PowerShell.exe -ExecutionPolicy Bypass -File "%~dp0RedisPowerShellDescript.ps1"”。(-ExecutionPolicy Bypass为改动PowerShell的执行策略为ByPass,否则执行不了ps1脚本。)
运行
服务不存在下执行时,暂停服务时会报错,后继可查看是否有判断方式进行优化。
如服务存在下执行。
发布与订阅
Redis具有5种数据结构,分别为字符串、字符串列表、字符串集合、哈希。订阅与发布只能以字符串形式,所以需要进行数据转换,实验通过将数据转换为JSON格式进行传输。
实验条件
创建两个控制台应用程序和一个动态链接库;控制台应用程序一个用于发布,一个用于订阅;动态链接库用于实现发布与订阅,数据转换。
都安装nuge包:
动态链接库额外安装nuge包:
动态链接库
代码
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;namespace NsRedisTool
{public class ClsRedisTool{public delegate void DelegateReceiveMessage(string type,string key,object value);public delegate void DelegateUpdateString(string key);public delegate void DelegateUpdateList(string key);public delegate void DelegateUpdateSet(string key);public delegate void DelegateUpdateSortedSet(string key);public delegate void DelegateUpdateHash(string key);public DelegateReceiveMessage receivemessage;public DelegateUpdateString updateString;public DelegateUpdateList updateList;public DelegateUpdateSet updateSet;public DelegateUpdateSortedSet updateSortedSet;public DelegateUpdateHash updateHash;private static ClsRedisTool instance;private static object objLock = new object();private static ConfigurationOptions options = new ConfigurationOptions{EndPoints = { { "localhost", 6379 } },Password = "RedisPasswordOfChargingGPT"};private ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options);public IDatabase GetDatabase(){return redis.GetDatabase();}private ClsRedisTool() { }~ClsRedisTool(){redis.Close();redis.Dispose();}public static ClsRedisTool GetInstance(){if (instance == null){lock (objLock){if (instance == null){instance = new ClsRedisTool();}}}return instance;}public void OpenListening(string channel){ISubscriber subscriber = redis.GetSubscriber();subscriber.Subscribe(channel, OnMessageReceived);}private void OnMessageReceived(RedisChannel channel, RedisValue message){dynamic jsonObject = JsonConvert.DeserializeObject(message);string type = (string)jsonObject.Type;string key = (string)jsonObject.Key;object value = jsonObject.Value;receivemessage?.Invoke(type,key,value);switch (type){case "String":updateString?.Invoke(key);break;case "Set":updateSet?.Invoke(key);break;case "List":updateList?.Invoke(key);break;case "Hash":updateHash?.Invoke(key);break;case "SortedSet":updateSortedSet?.Invoke(key);break;}}private void Send(string channel,string value){ISubscriber subscriber = redis.GetSubscriber();subscriber.Publish(channel, value);}public void SendString(string channel,string key,RedisValue value){Send(channel,JsonConvert.SerializeObject(new { Type = "String",Key=key, Value = value }));}public void SendSet(string channel, string key, RedisValue[] value){Send(channel, JsonConvert.SerializeObject(new { Type = "Set", Key = key, Value = value }));}public void SendList(string channel, string key, RedisValue[] value){Send(channel, JsonConvert.SerializeObject(new { Type = "List", Key = key, Value = value }));}public void SendSortedSet(string channel, string key, RedisValue[] value){Send(channel, JsonConvert.SerializeObject(new { Type = "SortedSet", Key = key, Value = value }));}public void SendHash(string channel, string key, RedisValue value){Send(channel, JsonConvert.SerializeObject(new { Type = "Hash", Key = key, Value = value }));}}
}
发布
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;namespace SendConsole
{internal class Program{static NsRedisTool.ClsRedisTool redis =NsRedisTool.ClsRedisTool.GetInstance();static string channel = "channel";static void Main(string[] args){Console.ReadKey();SendString();Console.ReadKey();SendSet();Console.ReadKey();SendList();Console.ReadKey();SendSortedSet();Console.ReadKey();SendHash();Console.ReadKey();}private static void SendString(){string key = "stringKey";string value = "stringValue";IDatabase database = redis.GetDatabase();database.StringSet(key, value);Console.WriteLine("SendString");redis.SendString(channel, key, database.StringGet(key));}private static void SendSet(){string key="setKey";IDatabase database = redis.GetDatabase();database.SetAdd(key, "setValue1");database.SetAdd(key, "setValue2");Console.WriteLine("SendSet");redis.SendSet(channel, key, database.SetMembers(key));}private static void SendList(){string key = "listKey";IDatabase database = redis.GetDatabase();database.ListLeftPush(key, "listValue1");database.ListRightPush(key, "listValue2");Console.WriteLine("SendList");redis.SendList(channel, key, database.ListRange(key));}private static void SendSortedSet(){string key = "sortedSetKey";IDatabase database = redis.GetDatabase();database.SortedSetAdd(key, "sortedSetValue1", 1);database.SortedSetAdd(key, "sortedSetValue2", 2);Console.WriteLine("SendSortedSet");redis.SendSortedSet(channel, key, database.SortedSetRangeByRank(key,0,-1));}private static void SendHash(){string key = "hashKey";IDatabase database = redis.GetDatabase();database.HashSet(key, "hashField1", "hashValue1");database.HashSet(key, "hashField2", "hashValue2");Console.WriteLine("SendHash");redis.SendSortedSet(channel, key,database.HashKeys(key));}}
}
订阅
代码
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ReceiveConsole
{internal class Program{static NsRedisTool.ClsRedisTool redis = NsRedisTool.ClsRedisTool.GetInstance();static void Main(string[] args){redis.receivemessage += Receivemessage;redis.OpenListening("channel");Console.WriteLine("OpenListening");Console.ReadKey();}private static void Receivemessage(string type,string key,object value){Console.WriteLine($"Receive message from channel [\"channelName\"],type[{type}],key[{key}]");switch(type){case "String":Console.WriteLine(value);break;case "Set":case "List":case "SortedSet":Console.Write(string.Join(",", value));break;}}}
}
执行
发布
订阅
窗体应用程序实验
创建两个窗体应用程序(此处使用C# .NetFramework WinForm),一个用于发布,一个用于订阅。
都安装nuge包:
发布
用于发布的应用程序添加一个按键,通过按键按下事件发布消息。
界面
代码
using StackExchange.Redis;
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;namespace NsSend
{public partial class Send : Form{ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379");//6379在运行redis-server.exe时有显示在界面上。public Send(){InitializeComponent();}private void SendFunction(){ISubscriber subscriber = redis.GetSubscriber();subscriber.Publish("messageChannel", "Hello");//messageChannel为通道名称,在接收端需要使用;Hello为信息。}private void Form1_FormClosing(object sender, FormClosingEventArgs e){redis.CloseAsync().Wait();//确保应用程序安全退出时关闭连接。}private void button1_Click(object sender, EventArgs e){SendFunction();}}
}
接收
用于接受的应用程序添加一个文本框,接收到消息时更新文本框。
界面
代码
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows.Forms;namespace NsReceive
{public partial class Receive : Form{private delegate void DelegateSetTextBox(string text);private DelegateSetTextBox setTextBox;ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379");public Receive(){setTextBox = SetTextBox;InitializeComponent();ReceiveFunction();}private void ReceiveFunction(){ISubscriber subscriber = redis.GetSubscriber();subscriber.Subscribe("messageChannel", OnMessageReceived);//当有消息通过Publish方法发送到这个通道时,订阅者会调用回调方法。}private void OnMessageReceived(RedisChannel channel, RedisValue message){if (this.InvokeRequired)//判断调用方在对控件操作时是否必须调用Invoke方法(因为调用方在创建控件的线程以外的线程)。{this.Invoke(setTextBox, $"{channel}: {message}");}else{setTextBox($"{channel}: {message}");}}private void SetTextBox(string message){textBox1.Text = message;}private void Form1_FormClosing(object sender, FormClosingEventArgs e){redis.CloseAsync().Wait();}}
}
运行
安全性
密码
可通过密码增加安全性。
增加方式
修改配置文件,此处仍用redis.windows-service.conf做演示;第445行为新增内容,其上为描述。(如已将Redis配置为Windows服务,需卸载服务重新配置)
使用redis-cli.exe通信
增加密码后,运行redis-cli.exe,输入ping后结果如下:
需先使用auth指令输入密码后才可通信:
使用C#通信
增加密码后,运行此前”发布与订阅“编写的字符串例子,语句报错:
改为如下代码可恢复使用:
static ConfigurationOptions options = new ConfigurationOptions{EndPoints = { { "localhost", 6379 } },Password = "RedisPasswordOfChargingGPT"};ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options);