您的位置:首页 > 数据库 > Redis

NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

2017-11-06 17:00 836 查看

http://www.cnblogs.com/edisonchou/p/3825682.html

一、消息队列场景简介

  “消息”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器

View Code
  (4)走到这里,生产者消费者模式中生产者的任务已经完成了,接下来消费者就需要开始消费了。也就是说,消息队列已经建好了,我们什么时候从队列中去任务,在哪里执行?怎么样执行?通过上面的介绍,我们知道,在专门的消息队列服务器中有一个进程在始终不停地监视消息队列,如果有需要待办的任务信息,则会立即从队列中取出来执行相应的操作,直到队列为空为止。于是,思路有了,我们马上来实现以下。这个消息监视的操作也是一个全局操作,在系统启动时就会一直运行,于是它也应该写在Application_Start这个全局起始事件里边,于是按照标准的配置写法,我们在Application_Start中添加了如下代码:MessageQueueConfig.RegisterExceptionLogQueue();

View Code

PS:Log4Net是用来记录日志的一个常用组件(Log4J的移植版本),可以将程序运行过程中的信息输出到一些地方(文件、数据库、EventLog等)。由于Log4Net不是本篇博文介绍的重点,所以对Log4Net不熟悉的朋友,请在博客园首页搜索:Log4Net,浏览其详细的介绍。


  其次,在App_Start文件夹中添加一个类,取名为LogConfig,定义一个静态方法:RegisterLog4NetConfigure,具体代码只有一行,实现了Log4Net配置的初始化操作。

public class LogConfig
{
public static void RegisterLog4NetConfigure()
{
//获取Log4Net配置信息(配置信息定义在Web.config文件中)
log4net.Config.XmlConfigurator.Configure();
}
}


  最后,在Global.asax中的Application_Start方法中添加一行代码,注册Log4Net的配置:

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

//自定义事件注册
MessageQueueConfig.RegisterExceptionLogQueue();
LogConfig.RegisterLog4NetConfigure();
}


  (5)第五步,改写MessageQueueConfig中的RegisterExceptionLogQueue方法。这里就不再需要从预置类型Queue中取任务了,而是Redis中取出任务出队进行相应处理。这里,我们使用了Log4Net进行异常日志的记录工作。PS:注意在代码顶部添加对log4net的引用:using log4net;

  public static void RegisterExceptionLogQueue()
{
//通过线程池开启线程,不停地从队列中获取异常信息并将其写入日志文件
ThreadPool.QueueUserWorkItem(o =>
{
while (true)
{
try
{
if (MyExceptionFilterAttribute.redisClient.GetListCount("ExceptionLog") > 0)
{
//从队列中出队,获取异常对象
string errorMsg = MyExceptionFilterAttribute.redisClient.DequeueItemFromList("ExceptionLog");
if (!string.IsNullOrEmpty(errorMsg))
{
//使用Log4Net写入异常日志
ILog logger = LogManager.GetLogger("Log");
logger.Error(errorMsg);
}
}
else
{
Thread.Sleep(1000); //为避免CPU空转,在队列为空时休息1秒
}
}
catch (Exception ex)
{
MyExceptionFilterAttribute.redisClient.EnqueueItemOnList("ExceptionLog", ex.ToString());
}
}
});
}


  (6)最后一步,调试验证是否能正常写入App_Data文件的日志中,发现写入的异常日志如下,格式好看,信息详细,圆满完成了我们的目的。



四、小结

  使用消息队列将调用异步化,可以改善网站系统的性能:消息队列具有很好的削峰作用,即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。在电商网站的促销活动中,合理使用消息队列,可以有效地抵御促销活动刚开始大量涌入的订单对系统造成的冲击。本文使用消息队列的思想,借助Redis+Log4Net完成了一个超简单的异常日志队列的应用案例,可以有效地解决在多线程操作中对日志文件的并发操作带来的一些问题。同样地,借助消息队列的思想,我们也可以完成对数据库的高并发的消息队列方案。所以,麻雀虽小五脏俱全,理解好了这个案例,相信对我们这些菜鸟码农是有所裨益的。同样,也请大牛们一笑而过,多多指教菜鸟们一步一步地提高,谢谢了!后边,我们会探索一下Redis的集群、主从复制,以及在VMWare中建立几台虚拟机来构建主从结构,并使用Redis记录网站中重要的Session会话对象,或者是电商项目中常见的商品类目信息等。但是,本人资质尚浅,并且都是一些初探性质的学习,如有错误和不当,还请各位园友多多指教!

参考文献

(1)传智播客.Net学院王承伟,数据优化技术之Redis公开课,http://bbs.itcast.cn/thread-26525-1-1.html

(2)Sanfilippo/贾隆译,《几点建议,让Redis在你的系统中发挥更大作用》,http://database.51cto.com/art/201107/276333.htm

(3)NoSQLFan,《Redis作者谈Redis应用场景》,http://blog.nosqlfan.com/html/2235.html

(4)善心如水,《C#中使用Log4Net记录日志》,http://www.cnblogs.com/wangsaiming/archive/2013/01/11/2856253.html

(5)逆心,《ServiceStack.Redis之IRedisClient》,http://www.cnblogs.com/kissdodog/p/3572084.html

(6)李智慧,《大型网站技术架构-核心原理与案例分析》,http://item.jd.com/11322972.html

附件下载

(1)版本1:使用预置类型的异常日志队列Demo,http://pan.baidu.com/s/1nt5G7Fj

(2)版本2:使用Redis+Log4Net的异常日志队列Demo,http://pan.baidu.com/s/1i3gMnnJ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: