发掘数据库内存表的用处
内存表(或称内存数据库中的表),是数据库把表中的数据完全放在内存,重启数据库后,内存表中的不会有任何数据,但内存表的表结构还存在。首先需要明确一个观念,使用内存表和程序直接在内存操作理论速度是一样。以下为内存表的power功能描述。
一、内存表的优点:
(一)、速度很快
没有最快,只有更快。内存的速度是除了cpu cache外最快的存储设备,所以不要怀疑内存表的速度。理论上内存表的速度和最快通信方式速度是一样,因为都在内存中操作。缺点在于不能持久存储,只有扬长避短,才能发挥内存表的优势。内存速度可达6G/S以上,而硬盘速度不稳定算为0.2G/S,相差30倍以上,有的系统甚至相差100倍以上.
(二)、标准sql操作
两个应用程序的通信,是多么让人痛苦,什么文件记录锁、管道、队列、消息队列、信号灯、共享内存、com组件、soap、xml、soa、json/bson等等,全是奔通信而来,让人眼花缭乱。巨大的复杂且不说,关是n个操作系统的兼容性就够头痛的。而基于sql的内存表跨语言,跨平台,跨虚拟机、跨数据库、跨老菜鸟。说来说去,还是sql标准带来的好处。
(三)、支持事务
以上通信不支持事务,是很多高性能通信都不能解决的问题,更别说自定义的socket协议。支持事务在通信可能不是必要,但有了更安全的选择。
二、内存表缺点:
(一)、不能持久化
不能存入硬盘,因为硬盘的速度太慢,所以出现了内存表。持久化,只要做到服务正常停止时,把内存表数据保存到普通数据表就可以了,比队列之类的持久化容易得多。
(二)、占用内存过大
现在服务器内存已经很大了,很多内存浪费掉了。用内存表,你的内存使用量完全可以控制。
三、内存表可发掘功能:
(一)、用于进程通信
不同程序的进程通信、汲及各大操作系统内部知识,实现难度大。完全可以内存表来交换数据,解决了硬盘数据表交换数据慢的问题,解决了进程通信不标准化问题,解决多个操作系统进程通信的困难。另外本机通信可以不通过tcp/ip协议,使用相关数据库的管道通信,进一步提高通信效率。
(二)、用于业务系统缓存
一个数据库支持的系统,都有很多表。为了追求速度,我们经常把不需要频繁更新的表缓存在应用程序中,但这种缓存不能多个程序共享,对缓存的控制也需要相当的技巧。其实可以保持原有框架不动,建立内存表,表结构和 “需缓存表” 一样。在应用程序启动后把 “需缓存表” 数据插入内存表中。当有“需缓存表”有数据更新时,只要再插一份到内存表。解决了自行控制缓存的风险,通过内存表的参数设置解决了内存的使用量问题。
(三)、代替网络通信
特别对于局域网应用,很多时候需要通信网络通信来解决服务器和客户端的数据同步问题。网络通信的本质是进程通信的延伸,但又有自已特点。如会话控制,通信协议控制。而基于内存表的通信建立在坚实的c/s数据库服务器上。在更高层解决了很多网络通信问,你只要关注于通信协议的业务逻辑。当需要传输二进制大数据时,其实我们可以在基于内存表的通信基础上,让服务器再通过scoket把二进制传入。在局域网c/s框架下,你可以通过权限控制,动态建立内存表,来完成用户交互。
(四)、构建分布式系统
当你的系统遇到高并发,高流量时,你需要构建分布式,可水平扩展的业务系统。而你的多个业务系统如果共享数据是一大难题.内存表可以解决这个问题,速度是建立在内存中,通信是建立高性能数据库c/s模式上,你只要专注于业务逻辑。
(五)、构建跨语言跨平台通信
通用数据库系统,在各大流行语言中都可以访问。通过数据库表通信,以前遇到的问题是通信速度太慢,而基于内存模式,解决了通信慢的问题,好处在于使各种语言通过标准sql访问通信内容。可以基于这种方式,实现c#和java在局域网通信,解决通信协议问题。通过orm方式,完全实现对象和list<t>在不同系统的穿梭,避免重复发明轮子。对于小并发量局域网通信完全够用。对于大并发,见问答。
内存表在上面系统中,类似于设计模式中的中介者模式。中介者模式的特点是,用一个中介对象封闭一系列的对象交互,各个对象不需要相互作用,使其耦合松散,从而独立改变它们之间的交互。
四、内存表问答:
(一)、如何做到数据库的全内存操作,不要经过老牛般的硬盘?
你可以把数据库安装在“内存硬盘”中,“内存硬盘”是用内存虚拟硬盘,这样数据库在读取诸如用户权限、配置信息时,也是从内存加载,有效克服最后的瓶颈。至于“内存硬盘”如果和硬盘同步,也有解决方案。
(二)、基于内存表通信的速度有我自行开发的socket快吗?
如果两台电脑通过socket对连,内存表通信肯定没有socket快,但也慢不到那里去,因为都在内存操作。内存表只是一个中介者,有了这个中介者会带来很多好处,如访问容易,就像在不同电脑之间加入路由器一样。
(三)、基于内存表的缓存系统怎么在现有系统上集成?
你可以把“需要缓存”、不常执行新增删除修改的表,改为内存表。把原来的数据表,改个名字,系统启动时,用程序把数据表插入内存表。这样代码和sql做到最少改动。原数据表的新增删除修改部分代码,增加"改名后的数据表"操作部分。
极少更新的表,可以不修改现有任何代码,建立一个伺服程序,过段时间把数据表同步到内存表中(操作最好带事务,不然读”内存表“程序可能出现数据出错),当然时间间隔你可以根据情况自行调整。
(四)、大家都知道数据库连接数是有限的,如果用内存表通信支持高并发?
对于高并发,内存数据库的并发量高于基于硬盘的并发量。这时任何基于传统数据库驱动的程序会感到更吃力,因为传统数据库有i/o的瓶颈。这时你只要使用传统分流数据库并发方式来操作就可以了,如物理分库, 数据库集群、负载均衡、路由选择库表散列。另外你可以使用高效率c/c++来接收通信,把收到内容放入队列,队列程序再放入内存表,使用java/c#擅长逻辑处理的程序从内存表中取出做业务逻辑处理,处理完后的结果放在内存表,队列程序从内存表中取出到发送队列,c/c++从发送队列发送给客户端。
五、测试图
下图为使用内存表测试结果,其中testGetEntitiesByArray(),测试了一万条数据库事务处理。不处理数据库时测试平均为2s,使用数据库为5s,内存表用了3s。
下图为使用基于硬盘数据库表测试结果,其中testGetEntitiesByArray(),测试了一万条数据库事务处理。不处理数据库时测试平均为2s,使用数据库为50s,硬盘数据库表用了48s。两者相差48/3=16倍。