转自:http://bbs.youkuaiyun.com/topics/390607959/ 中sp大神的回答
收到一个请求,如果需要异步处理,从线程池中分配一个线程就行了。一个线程中处理http请求的操作很快就结束了,例如200毫秒就结束了,然后线程就还给线程池了。根本用不着什么“队列”来把请求再排一次队。
在很早以前我们说“应该给客户排个队”来缓解秒杀的冲突,是指在用户session信息中为客户端分配一个“拿个号”,就好像医院看病之前先要挂号一样。然后当客户点击“提交”页面时
1. 如果线程池使用率很低,当然立刻分配线程开始处理。
2. 而如果线程池不满,但是使用率已经超过了某个临界值,那么就用这个实现拿到的排队号来判断是否应该“插队”处理(也就是说它比”当前已经处理到的排队号“更小),如果不允许插队就给客户端推送“当前刚刚处理到n号,你这个m号请求需要继续等待”的信息。
3. 如果线程池已经满了,那么直接给客户端推送“系统繁忙,请等待”的信息。
可见,在服务器端根本不是什么“http排队”。要么是直接并发处理,要么是直接客户返回脚本请用户在页面上继续等待、过一会儿重试。排队是用户看到的业务逻辑视图,不是真的在服务器端的并发线程之外再来额外地搞排队。排队是垃圾的,她会让系统变慢、而且复杂。
对于你的问题二,我认为你犯了一个“用数据库来取代高层次的应用编程”的错误。数据库只是跟在程序的屁股后头来持久化数据的,你的程序先处理了数据,然后才丢到数据库里。所以你的处理相应数据请求的程序应该来触发所有后续异步请求,甚至分发到其它服务器上去。程序来做这个触发,数据还没有最终可靠地存到数据库表之前,就应早已触发其它任务的。而不是什么数据库来触发外部任务。如果满脑子只知道一点数据库增删改查,做不了高性能的程序设计。
对于你的第三个问题,缓存的核心就是保证极高的命中率。放入缓存的数据,要么是基本上不改变的数据(业务上会使用新的id好的资源来表示数据修改,而不是修改同一个id号记录下面的内容),要么就是有一个缓存依赖机制会自动根据数据库的改变而自动删除缓存单元(这样你下一次访问缓存中的数据时,由于找不到,就会自动重新建立缓存单元)。
缓存不是用来胡乱保存数据的。对于图片、音频等等巨量的静态文件,当然直接用缓存。而对于频繁变化的数据,你要掂量一下你有没有现成的“缓存依赖机制”。如果没有,你就没有金刚钻,不要揽这个瓷器活。实际上大多数都是因为误认为缓存是傻瓜化地”把数据保存在内存中“,以为不需要技术含量,所以才胡乱用缓存。