Jack:那我要写的这个server用Oracle、mysql中的哪个模型比较合适呢?
我:一个都不合适。准确地说,如果你采用了这两种模式中的一种模式,你的16CPU机器马上就会挂。
Jack:那哪一个会先挂呢?
我:应该是Oracle那种模型的数据库会先挂。因为不断的进程fork()与exit()会消耗大量的操作系统资源,而这些进程其实就做了类似于"select a from b where c=10;"这样的操作(如果有合适的索引,这样的操作是非常快的)。
Jack:这有神马问题吗?
我:这样的SQL重复的频率是很高的,也容易引起latch争用的问题,同时,执行时间很短。
Jack:Oracle如何解决这样的问题呢?
我:Oracle主要通过绑定变量来解决这样的问题。
Jack:Oracle解决得好吗?
我:这是一个伪命题。因为这样的应用是典型的key-value场景,关系型数据库本身就不适合。如果你设计一个nosql数据库它的性能就会非常好。
Jack:好吧。回到正题,我们要如何设计这个Cache Server的网络框架呢?
我:所以,根据上边的讨论,我们可以得出一个结论——一定要采用多进程、多线程。
Jack:到底是多进程还是多线程呢?
我:我建议多进程+多线程。因为多进程模型必然采用共享内存,而共享内存使用起来复杂的同时,有一个明显的优点——进程挂掉之后,共享内存数据不会丢失。也就是说,只要把进程restart一下,就可以正常服务,它的可靠性比多线程要高得多。另外,可以在多进程中的每一个进程里采用多线程。
Jack:了解了。那么,采用多进程/多线程就足够了撒?
我:不够。对于关系型数据库来说,采用多进程或者多线程就完全足够了。但是,你这个是cache server,面对着直接的高并发、非事务的疯狂冲击。简单的多进程、多线程必挂。
Jack:为什么关系型数据库采用更多进程多线程就完全足够了?
我:根本的原因是关系型数据库是面向事务的,它的并发量并没有那么大。如果真有那么大,就只有做业务拆分,用更多的db机器去扛。因为它确实需要顶住这么大的业务量。你想一想,一个sql从用户那里发出后,会经历些什么呢?
Jack:比如Oracle,简单地说,首先把SQL传送到server端,然后把SQL语句解析成ASCII,然后再做yacc语法解析,之后再进行复杂的SQL优化(CBO干的就是这事儿),最后再执行这个SQL语句,执行的对象是一个table,而这个table有可能是几十个GB,甚至上T。
我:关键就在这里。一个关系型数据库的请求需要做很多很多的事情。而最耗费时间的,莫过于执行这个SQL语句。所以,一个请求的生命周期是比较长的。短的几分钟,长的几天甚至几十天都可能。所以,它很少面临因为线程、进程本身的创建、释放而把操作系统搞死的情况。但是,你的Cache Server就不同了。
Jack:明白了。那如何解决这个问题呢?
我:采用IO多路复用是必须的。甚至你可以不考虑多进程、多线程,但是IO多路复用一定需要。