经常听到你们说的"消息队列",这到底是啥东西?怎么用?

by_封爱 版主 2018-06-06 07:59:38
加精
没用过.不过听你们说 好像是一个集合.来防止"并发"的..

一个一个进 一个一个出...FIFO吗?

看一下代码..

static readonly ILog infoLogger = LogManager.GetLogger("Logger");
void xxx()
{
infoLogger.Info("日志");
}

没啥含量,,就是单纯的使用log4记录日志..

就这个代码来看.如果在"高并发"使用的情况下.会不会产生异常?

听说 公司在业务繁忙期间(并发多),这种代码出险了问题."前人"说是因为并发引起的..

可能说是N个人并发写日志..导致异常.

这种情况可能发生吗?而且 这么有名气的类库,人家不会不考虑吧..

所以如果这个问题真实存在.. 我如何用"队列"的代码方式来解决?
...全文
4598 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
家有琦琦果 2019-04-30
  • 打赏
  • 举报
回复
过来学习,慢慢研究中
mk_lucifer 2019-04-30
  • 打赏
  • 举报
回复
消息队列是操作系统常见的一种内核对象,也叫消息邮箱,当然这种技术不是只有操作系统采用,自己也可以用队列实现同样的手段,最常见的消息队列就是,窗口消息,windows下所有的窗口行为都是消息驱动的,所有UI线程都有一个消息队列,这个消息队列是系统级的,直接用它也没啥毛病,但是适合C/C++等支持指针的非托管语言,因为这个消息的定义经常要用指针携带消息内容,所以C#不是很适合。。 消息队列就是一种技术而已,即使不用线程消息队列,也可以自己创建队列实现相同的功能。基本原理就是委托者将自己要委托的事情写到一个特殊结构体里(消息),然后推入一个队列中。。被委托者空闲时从队列取消息,并按照消息描述做被委托的事情。。最好理解的就是饭馆吃饭,你先点菜,然后服务员以纸质单据等形式给后厨,厨师会累计一摞单据,然后一个个的做,吃饭的等着吃就行了。。。也可以啥也不关心发出消息就算任务结束(这种方式,更像快递)。。
baidu_27549073 2018-08-17
  • 打赏
  • 举报
回复
引用 52 楼 weixin_40068689 的回复:
请教一下,为什么说静态的就不会有问题呢,小白不懂

我的意思是如果只有一个静态类调同一个文件,不存在多个对象抢同一个资源(日志文件)的情况。只有多个地方要打开同一个文件才会有这种情况,后面的那个请求会因为不能打开文件而报错。
但是还是会有调用频率太快写不进去(非常极端的情况了)的问题。
闭包客 2018-08-16
  • 打赏
  • 举报
回复
本身这种写日志的代码就是一个队列串行写入的。

一个队列、一个硬盘、一台主机的 IO,都有其极限,当业务超过了这个极限的时候,就只有分布式能解决问题的。
BXS_null 2018-08-15
  • 打赏
  • 举报
回复
引用 46 楼 baidu_27549073 的回复:
以前用过,讲道理,静态了是不会有问题的。
之前碰到一个情况,有两个UI层,发布到一个项目中。当做同一个网站运行,两个网站的Dll抢同一个文件,然后出错了。
还有种可能就是有几个类都引用了log4net。然后相互抢资源
请教一下,为什么说静态的就不会有问题呢,小白不懂
flybirding10011 2018-08-15
  • 打赏
  • 举报
回复
flybirding10011 2018-08-15
  • 打赏
  • 举报
回复
flybirding10011 2018-08-15
  • 打赏
  • 举报
回复
baidu_27549073 2018-07-09
  • 打赏
  • 举报
回复
以前用过,讲道理,静态了是不会有问题的。
之前碰到一个情况,有两个UI层,发布到一个项目中。当做同一个网站运行,两个网站的Dll抢同一个文件,然后出错了。
还有种可能就是有几个类都引用了log4net。然后相互抢资源
chenzhe014 2018-07-09
  • 打赏
  • 举报
回复
引用 24 楼 wanghui0380 的回复:
[quote=引用 21 楼 qq_17486399 的回复:]
[quote=引用 20 楼 wanghui0380 的回复:]
[quote=引用 19 楼 qq_17486399 的回复:]
[quote=引用 12 楼 wanghui0380 的回复:]
消息队列是用来解耦的,不是用来解决并发的。

至于你的问题,就像sp说的,一个lock就可以了,因为本质上他是资源共享问题。

现在的消息队列指的是MQ等,不是用来解决高并发?可以说它是解决高并发的一种解决方法吧[/quote]
他首先是用来解耦的,你只有是这种态度才能用好他。否则就会像楼上sp说的,你会用错方向。
另外:请分清楚什么什么并发,什么是并行。并发是多任务片段执行,并行是同时执行。MQ更多情况是并行,而非并发。我们只是把后续处理解耦出来,并行交给其他的系统去后续执行[/quote]
如果一次有1万个请求写日志,我们电脑是8核,并行处理最多为8,那怎么说MQ是为了处理并行呢?小弟有点不解,求多多指教。我对这个确实有点迷糊了[/quote]

我们首先说他为啥是解耦的,拿现在最喜欢折腾的用户操作,用户积分,用户等级,这类玩意来说。不解耦的喜欢这样玩注册用户,送100分,给最低等级。解耦的设计是一个用户动作就好,你注册用户就是注册用户的动作事件,mq发一份过去。谁愿意订阅就订阅去,他订阅了自己处理,比如积分系统订阅了他,那就+100分呗。

[/quote]
请教下,那么积分系统一般是怎么通知注册系统是否成功获取积分?
smileruner 2018-07-03
  • 打赏
  • 举报
回复
微软的产品是biz talker,轻量的有window service bus,云产品有https://docs.azure.cn/zh-cn/service-bus/。
消息队列初衷不是解决并发的,是解耦的。甲需要发送消息,乙要接收消息。甲通过消息队列发送消息就不需要关注消息是否发送成功,做好自己的事情就可以了。
丁劲犇 2018-06-30
  • 打赏
  • 举报
回复
消息队列的主要作用其实是去耦合。如果你愿意一个支持外部触发器的关系数据库也可以作为消息队列。比如postgresql,在表有新东西插入后,可以用c触发器给dbus发消息,通知大伙儿来自己取。
liulilittle 2018-06-07
  • 打赏
  • 举报
回复
引用 37 楼 sp1234 的回复:
[quote=引用 27 楼 liulilittle 的回复:] 但我们把它的请求作为一条消息放入一个消息队列中(当然它也可以被认为叫做“工作队列 或 任务队列”),由队列派发它的请求处理,那么服务器仅仅只是付出了“入队与出队”对buffer的改变重复分配空间拷贝内存的代价,但这个与线程相比极其廉价,而更多的资源都被用于处理请求,而不是用于线程与进程上下文切换降低了CPU的占用,大大减少了内核重复拷贝分配移动释放内存的次数,内核更轻松你的应用程序才会跑的更快。
(例如 asp.net)处理消息内容是同步阻塞的,还是多线程并发的呢?你这个描述的是说异步多线程处理就“CPU疲于切换进程与线程上下文”、所以必须同步阻塞处理,这个跟编程潮流相违背。[/quote] 它并不是说你需要进行同步处理,这样服务器的效率并不能真正的发挥出来,而是说你可以运行多个消息队列 每个消息队列都运行在一个单独的线程实例或者共享的。 另一点现在的开发越来越讲究一个傻瓜式简单,能够同步就同步,而不要去追求异步提高使用者门槛,你可以在框架内部大量应用异步,我们需要考虑现在普遍在职开发人员水平的问题,你很难相信很多人不会在多线程下使用到锁,而且即便用lock锁也能deadlock(无论是因为异常还是超出enter计数),而他们有人还特别的多。 而且要想做好多线程的程序,这要求程序员需要了解各种多线程下的同步机制,无论是互斥体、内核事件对象还是临界区、原子态,即便是内存读写顺序方面也需要对内存屏障与volatile有认识,否则你的应用程序可能会出现很多出乎意料的错误,类似这些问题还有很多很多。 这带来了一个问题,现在的大多数程序员几乎对多线程最多就是有一个概念,有些可能搞过但也就只是一股脑的用lock这类锁,然后什么都不管,我们都知道内核锁是最重的,锁的临界颗粒度划分,而且类似如“Mutex”这类同步锁效率就不会太高,内核的临界区锁竞争过程是比较慢的(内核需要管理的内核资源很多并不只有它自身),相对于自旋锁从挂起到唤醒中间内核经过了多少“离开/进入”临界区的线程上下文的切换? 锁不可以乱用也不能不用,按场景的具体情况而视选取恰当的锁,这样可以提高应用在多线程下并发效能,而这些很多人做不好,虽然可以胡乱套但可能造成程序deadlock,或者效率不高,当然假设不追求效率的确不会有太大的区别。 iis的应用池是基于M/P架构的,而且它们一个P在同一时间段内只能处理一条请求,当你指定了“最大工作进程数”为16时那么系统中至少将运行16个w3wp的进程实例 为了保证在一个进程域不存在并发,而在asp.net中无论你在那条线程中利用“HttpContext.Current”都可以访问到正在“处理请求线程”的当前的HttpContext,并且控制它的一切 包括输出,当然这不止是microsoft家的iis这么干,apache/web服务器也是一样的。
  • 打赏
  • 举报
回复
那标题和帖子内容结合起来说,就是,实际上并发多线程有无数种形式的框架需求,每一种都要具体问题具体分析,看懂其内部机制。 要提高并发程度,对于进程内的多线程编程开发而言,你要用好.net framework 系统提供的线程池、Task、连接池、缓存机制等等框架,以及其它各种框架。在提高并发程度关键就在于并发处理任务的同时要仅仅在必要的那几条代码设计好 lock 同步机制(而不是把所有的任务都整个地进行顺序排队)。
sp1234_maJia 2018-06-07
  • 打赏
  • 举报
回复
当集群中的服务器动态地注册到集群、也可能随时有宕机退出的可能性的时候,当许多冗余系统服务动态出现和消失的时候,比如说一个客户端需要将一个 word 文件转换为一个二进制代码,那么它怎么知道用哪一个服务器?它只需要把需求注册,然后等着结果就行了。然后这个服务器消息管理系统会自动查找消息路由,可能把消息从乌鲁木齐路由到天津、然后又路由到拉萨,最后找到一个服务器去执行这个 word 文件转换任务。所谓的“消息队列”是指服务集群常用的的最基础的通用跨语言、跨平台管理系统。 相对于你的进程内的开发和应用来说,它牺牲了几千倍以上的效率,换来的是水平扩展的稳定性。所以你编程设计的时候,应该先搞清楚牺牲了什么。这就好像一个人不会写代码来排序,可能就喜欢用 SQL Server 来排序,这时候就要知道牺牲了什么。
  • 打赏
  • 举报
回复
引用 21 楼 qq_17486399 的回复:
如果一次有1万个请求写日志,我们电脑是8核,并行处理最多为8,那怎么说MQ是为了处理并行呢?小弟有点不解,求多多指教。我对这个确实有点迷糊了
他的意思就是指放到服务器集群、分布式云计算的角度,才能用好这个 MQ。
  • 打赏
  • 举报
回复
引用 19 楼 qq_17486399 的回复:
[quote=引用 12 楼 wanghui0380 的回复:] 消息队列是用来解耦的,不是用来解决并发的。 至于你的问题,就像sp说的,一个lock就可以了,因为本质上他是资源共享问题。
现在的消息队列指的是MQ等,不是用来解决高并发?可以说它是解决高并发的一种解决方法吧[/quote] MQ 等等系统本身适合电信级的、大型服务器集群的底层组件,用类似发电子邮件的方式来简化低速通讯功能,增强其健壮性。因为这类集群系统中经常需要水平扩展,用冗余来保证健壮性,相对来说也就必须支持消息的持久化、流程化、重发消息、服务器监控要求。但是有的人就好像喜欢用 SQL Server 存储过程来给整数排序一样地、用它来模拟一切自己的要做的 c/s 通讯功能,这也是需要指出来,这个时候是严重地牺牲了效率的。 你说的“高并发”类似于这种说法,没有一定的场合就容易误解。当人家说的高并发是每秒几万次、而你说的高并发是每秒十几次的时候,你还觉得这叫做高并发吗?MQ之类的就是集群水平扩展和并发的基础框架,并不是咬文嚼字的“高并发”,而是要首先知道它应用场景才能搞懂高并发的不同概念。
  • 打赏
  • 举报
回复
引用 27 楼 liulilittle 的回复:
但我们把它的请求作为一条消息放入一个消息队列中(当然它也可以被认为叫做“工作队列 或 任务队列”),由队列派发它的请求处理,那么服务器仅仅只是付出了“入队与出队”对buffer的改变重复分配空间拷贝内存的代价,但这个与线程相比极其廉价,而更多的资源都被用于处理请求,而不是用于线程与进程上下文切换降低了CPU的占用,大大减少了内核重复拷贝分配移动释放内存的次数,内核更轻松你的应用程序才会跑的更快。
(例如 asp.net)处理消息内容是同步阻塞的,还是多线程并发的呢?你这个描述的是说异步多线程处理就“CPU疲于切换进程与线程上下文”、所以必须同步阻塞处理,这个跟编程潮流相违背。
SoulRed 2018-06-06
  • 打赏
  • 举报
回复
消息队列的性能很低,但是他确保业务100%可靠性,或者说99.999% 他作为一个功能模块应用于程序中。你可以看看阿里云和腾讯云的消息队列就明白了, 类似于发送一封邮件到客户手中,但比邮件要灵活要快的多。。
大鱼> 2018-06-06
  • 打赏
  • 举报
回复
引用 20 楼 wanghui0380 的回复:
[quote=引用 19 楼 qq_17486399 的回复:] [quote=引用 12 楼 wanghui0380 的回复:] 消息队列是用来解耦的,不是用来解决并发的。 至于你的问题,就像sp说的,一个lock就可以了,因为本质上他是资源共享问题。
现在的消息队列指的是MQ等,不是用来解决高并发?可以说它是解决高并发的一种解决方法吧[/quote] 他首先是用来解耦的,你只有是这种态度才能用好他。否则就会像楼上sp说的,你会用错方向。 另外:请分清楚什么什么并发,什么是并行。并发是多任务片段执行,并行是同时执行。MQ更多情况是并行,而非并发。我们只是把后续处理解耦出来,并行交给其他的系统去后续执行[/quote] 如果一次有1万个请求写日志,我们电脑是8核,并行处理最多为8,那怎么说MQ是为了处理并行呢?小弟有点不解,求多多指教。我对这个确实有点迷糊了
加载更多回复(29)

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧