Redis 消息队列中的异步场景封装
场景样式:
积分服务和短信服务订阅消息队列,消息队列推送消息到积分服务,短信服务,这样创建订完单响应给客户端只需要花费1s,但是又不会影响订单服务的并发量。
准备工作:
安装windows下的redis.
在项目中添加引用服务:ServiceStack.Redis
1.创建一个项目:MyRedis
1.1创建一个异步的类:RmOrder来进行订单积分和短信发送
```csharp
using MyRedis.MQ;
using System;
using System.Collections.Generic;
using System.Data.Odbc;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyRedis.Async
{
class RmOrder
{
public string CreateOrder()
{
//统计时间
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//1.订单生成
string order_sn = this.OrderGenrator();
//1.1存储到数据库
Thread.Sleep(1000);
Console.WriteLine($"订单:{order_sn}保存成功");
2.添加积分
//Console.WriteLine($"*********************开始调用积分服务*********************");
//RmOrderPoints rmOrderPoints = new RmOrderPoints();
//rmOrderPoints.AddPoints(order_sn);
//Console.WriteLine($"*********************积分服务调用完成*********************");
3.发送短信
//Console.WriteLine($"*********************开始调用短信服务*********************");
//RmOrderSms rmOrderSms = new RmOrderSms();
//rmOrderSms.SendSms(order_sn);
//Console.WriteLine($"*********************短信服务调用完成*********************");
//redis 优化
using (var messageQueue = new RedisMessageQueue("localhost:6379"))
{
//1.发送积分消息
messageQueue.EnQueue("rm_points",order_sn);
//2.发送短信信息
messageQueue.EnQueue("rm_sms", order_sn);
}
stopwatch.Stop();
Console.WriteLine($"订单完成耗时:{stopwatch.ElapsedMilliseconds} ms");
return order_sn;
}
/// <summary>
/// 订单生成器
/// </summary>
/// <returns></returns>
private string OrderGenrator()
{
Random random = new Random();
return "R" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + random.Next(1000,9999).ToString();
}
}
}
1.2创建一个类:RedisMessageQueue来封装Redis的消息队列,继承IDisposable
```csharp
using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyRedis.MQ
{
class RedisMessageQueue : IDisposable
{
/// <summary>
/// redis客户端
/// </summary>
public RedisClient redisClient { get; }
public RedisMessageQueue(string redisHost)
{
redisClient = new RedisClient(redisHost);
}
/// <summary>
/// 入队
/// </summary>
/// <param name="QKey">入队Key</param>
/// <param name="QMessage">入队消息</param>
/// <returns></returns>
public long EnQueue(string QKey, string QMessage)
{
//1.编码字符
byte[] bytes = Encoding.UTF8.GetBytes(QMessage);
//2.redis消息队列入队
long count = redisClient.LPush(QKey, bytes);
return count;
}
/// <summary>
/// 出队(非阻塞)==拉
/// </summary>
/// <param name="QKey">入队Key</param>
/// <returns></returns>
public string DeQueue(string QKey)
{
//1.redis 消息出队
byte[] bytes = redisClient.RPop(QKey);
string Qmessage = null;
//2.字节转string
if (bytes == null)
{
Console.WriteLine("队列中数据为空");
}
else {
Qmessage = Encoding.UTF8.GetString(bytes);
}
return Qmessage;
}
/// <summary>
/// 出队(阻塞)==推,数据实时性高
/// </summary>
/// <param name="QKey">入队Key</param>
/// <param name="timespan">阻塞超时时间</param>
/// <returns></returns>
public string BDeQueue(string QKey,TimeSpan? timespan)
{
//1.redis 消息出队
string Qmessage = redisClient.BlockingDequeueItemFromList(QKey, timespan);
return Qmessage;
}
/// <summary>
/// 获取队列数量
/// </summary>
/// <param name="QKey">队列Key</param>
/// <returns></returns>
public long GetQueueCount(string QKey)
{
return redisClient.GetListCount(QKey);
}
public void Dispose()
{
//1.关闭redis
redisClient.Dispose();
}
}
}
2.添加一个新建项:MyRedisRmPoints 根据订单增加积分以及反馈积分消息
2.1.添加类 RmOrderPoints
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyRedisRmPoints.Async
{
class RmOrderPoints
{
/// <summary>
/// 根据订单增加积分
/// </summary>
/// <param name="order_sn"></param>
public void AddPoints(string order_sn)
{
//1.调用积分服务
Thread.Sleep(1000);
//2.发送积分成功
Console.WriteLine($"增加积分:order_sn:{order_sn} 成功");
}
}
}
2.1.在program里面进行积分消息的优化
using MyRedisRmPoints.Async;
using MyRedisRmPoints.MQ;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyRedisRmPoints
{
class Program
{
static void Main(string[] args)
{
//redis 优化
using (var messageQueue = new RedisMessageQueue("localhost:6379"))
{
Console.WriteLine("积分消息......");
//1.获取积分消息
while (true)
{
string rm_points = messageQueue.BDeQueue("rm_points", TimeSpan.FromSeconds(60));
//2.消费积分消息
RmOrderPoints rmOrderPoints = new RmOrderPoints();
rmOrderPoints.AddPoints(rm_points);
}
}
}
}
}
3.添加一个新建项:MyRedisRmSms 根据订单发送短信以及反馈短信发送状态
2.1.添加类 RmOrderSms
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyRedisRmSms.Async
{
class RmOrderSms
{
/// <summary>
/// 根据订单发送短信
/// </summary>
/// <param name="order_sn"></param>
public void SendSms(string order_sn)
{
//1.调用第三方短信接口
Thread.Sleep(1000);
//2.发送短信成功
Console.WriteLine($"发送短信:order_sn:{order_sn} 成功");
}
}
}
2.2.在program里面进行发送短信的优化
using MyRedisRmSms.Async;
using MyRedisRmSms.MQ;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyRedisRmSms
{
class Program
{
static void Main(string[] args)
{
//redis 优化
using (var messageQueue = new RedisMessageQueue("localhost:6379"))
{
Console.WriteLine("短信消息......");
//1.获取短信消息
while (true)
{
string rm_sms = messageQueue.BDeQueue("rm_sms", TimeSpan.FromSeconds(60));
//2.消费短信消息
RmOrderSms rmOrderSms = new RmOrderSms();
rmOrderSms.SendSms(rm_sms);
}
}
}
}
}
4.在MyRedis项目里的program中完成对订单的异步调用服务、
RmOrder rmOrder = new RmOrder();
rmOrder.CreateOrder();
5.重新生成各个项目,在资源文件夹之中找到对应的Dubug目录,进行服务调用