用序列化的方式保存简单的数据类型之积分查询系统的建设
2014-03-15 00:00
288 查看
摘要: 一个简单的会员卡积分查询接口,由于数据量达到了50多万条,且无法用数据库间的数据交换进行数据同步,导致作者走了不少弯路,并最终抛弃了数据库。
最近有个小活,是做一个积分查询接口,由于积分系统是内部系统且无法连接外网,所以数据只能通过导出-导入的方式加入到积分查询接口的小系统中。
看到这里,你肯定认为这没什么呀,但我把以下条件列出后,你的想法可能会改变一些:
1、数据一共有50万条左右;
2、数据的导出只能用文本文件;
3、积分接口的数据库是mysql;
4、原卡库的数据库是mssqlsser2008;
5、要保证查询速度;
6、每日更新的数据大概有20000条左右;
7、积分接口所在服务器不允许远程连接数据库和远程登录,只能通过积分接口系统完成数据的导入;
8、服务器配置不高。
以上就是要求,根据需求,我先测试如何将这几十万条数据导入到数据库;首先存放数据的文本文件有10MB大小,初步我想的是如何将这个文件中的KV键值对转换成数据库能识别的sql语句,于是,我用了一下午的时间完成文件内容的转换... ... 或许你会问,怎么会用了一下午呢?应该很快吧?我要说编码的时间确实没用多少,但转换可就费时了,整个转换过程整整用了一整个下午!!!
试过才知道该方法不可行,那就分割数据文件吧,然后用多线程同时执行。我先把数据文件分割成没20000条一个文件,然后用线程分别转换,这次转换效果较第一次有很大改善,但依然用了将近一个小时。莫非java对字符串的处理这么费时?于是百度、google,没有找到有用的解释,好吧,那继续吧。
转换完成的sql文件有24MB大小,当我看到这个文件时,我预料到数据导入的速度也不会快。不过我还是执行了数据导入,结果我不想多说,总之,很惨。
惨归惨,不过数据好在都有了,那就做查询接口吧。轻车熟路,很快,一个带传输参数加密(其实就是编码)、验证身份和数据缓存的接口完成了,本地部署测试,一切正常,然后上传到服务器,当天一切正常。到第二天早上,我把新导出的文本文件(19000多条数据)上传到服务器并执行数据的转换和导入操作,通过日志查询页面,感觉系统响应速度奇慢,大约运行了两个小时后,页面停止响应,查看服务器状态,提示内存溢出,服务器配置本身就不高,我还在一个tomcat下部署了N个应用,看来撑不住了。
这个时候我有点心虚了,怎么办?不能每天搞这么个东西呀?在这后面我想了很多办法,如把文件2sql转换的工作放在前台用JS来实现,结果浏览器挂了;用lucene生成索引吧,无法完成有效的查询;... ...
最终,我想不行就试试serizable接口吧,把数据导入到继承了serizable接口的对象中,然后序列化到磁盘中,用的时候缓存到内存中,查询也快;经过将近一个小时的改造,除了最初的文件上传还保留外,其他的都改造了。改造完成的系统,文件上传到服务器端后,不再保存为文件,而是通过stream的方式读取数据并进行KV键值对的分离,然后存入MAP对象中。KV分离完成后,先将Map对象赋值给缓存供接口查询用,然后将map保存到磁盘,以便容器重启后可以重新导入数据,也相当于做了数据的持久化。
由于每天都有更新的数据,而这些数据中可能有需要将map中已有Key的value更新的,也可能有新加入的,这也正好是map的特性。
到目前为止,系统运行稳定,查询直接从内存中完成,且能经受住高强度负载,基本满意,但数据的转换速度还是有点慢,虽然已经使用了线程。
总结:做应用的一个习惯,就是挂载数据库,其实在做一些不复杂的且数据量不大的应用时,完全可以考虑序列化。不过序列化也有一些局限性,如某些数据对象是无法做序列化的。
最近有个小活,是做一个积分查询接口,由于积分系统是内部系统且无法连接外网,所以数据只能通过导出-导入的方式加入到积分查询接口的小系统中。
看到这里,你肯定认为这没什么呀,但我把以下条件列出后,你的想法可能会改变一些:
1、数据一共有50万条左右;
2、数据的导出只能用文本文件;
3、积分接口的数据库是mysql;
4、原卡库的数据库是mssqlsser2008;
5、要保证查询速度;
6、每日更新的数据大概有20000条左右;
7、积分接口所在服务器不允许远程连接数据库和远程登录,只能通过积分接口系统完成数据的导入;
8、服务器配置不高。
以上就是要求,根据需求,我先测试如何将这几十万条数据导入到数据库;首先存放数据的文本文件有10MB大小,初步我想的是如何将这个文件中的KV键值对转换成数据库能识别的sql语句,于是,我用了一下午的时间完成文件内容的转换... ... 或许你会问,怎么会用了一下午呢?应该很快吧?我要说编码的时间确实没用多少,但转换可就费时了,整个转换过程整整用了一整个下午!!!
试过才知道该方法不可行,那就分割数据文件吧,然后用多线程同时执行。我先把数据文件分割成没20000条一个文件,然后用线程分别转换,这次转换效果较第一次有很大改善,但依然用了将近一个小时。莫非java对字符串的处理这么费时?于是百度、google,没有找到有用的解释,好吧,那继续吧。
转换完成的sql文件有24MB大小,当我看到这个文件时,我预料到数据导入的速度也不会快。不过我还是执行了数据导入,结果我不想多说,总之,很惨。
惨归惨,不过数据好在都有了,那就做查询接口吧。轻车熟路,很快,一个带传输参数加密(其实就是编码)、验证身份和数据缓存的接口完成了,本地部署测试,一切正常,然后上传到服务器,当天一切正常。到第二天早上,我把新导出的文本文件(19000多条数据)上传到服务器并执行数据的转换和导入操作,通过日志查询页面,感觉系统响应速度奇慢,大约运行了两个小时后,页面停止响应,查看服务器状态,提示内存溢出,服务器配置本身就不高,我还在一个tomcat下部署了N个应用,看来撑不住了。
这个时候我有点心虚了,怎么办?不能每天搞这么个东西呀?在这后面我想了很多办法,如把文件2sql转换的工作放在前台用JS来实现,结果浏览器挂了;用lucene生成索引吧,无法完成有效的查询;... ...
最终,我想不行就试试serizable接口吧,把数据导入到继承了serizable接口的对象中,然后序列化到磁盘中,用的时候缓存到内存中,查询也快;经过将近一个小时的改造,除了最初的文件上传还保留外,其他的都改造了。改造完成的系统,文件上传到服务器端后,不再保存为文件,而是通过stream的方式读取数据并进行KV键值对的分离,然后存入MAP对象中。KV分离完成后,先将Map对象赋值给缓存供接口查询用,然后将map保存到磁盘,以便容器重启后可以重新导入数据,也相当于做了数据的持久化。
由于每天都有更新的数据,而这些数据中可能有需要将map中已有Key的value更新的,也可能有新加入的,这也正好是map的特性。
到目前为止,系统运行稳定,查询直接从内存中完成,且能经受住高强度负载,基本满意,但数据的转换速度还是有点慢,虽然已经使用了线程。
总结:做应用的一个习惯,就是挂载数据库,其实在做一些不复杂的且数据量不大的应用时,完全可以考虑序列化。不过序列化也有一些局限性,如某些数据对象是无法做序列化的。
相关文章推荐
- MySQL登陆方式、数据类型、数据引擎及SQL查询语句,注意的问题.
- 看你的linux编译系统是32位还是64位最简单的方法以及不同数据类型占用字节个数
- C#中,当从数据库中查询到数据,以DataTable类型返回后,如果需要对DataTable中的数据进行筛选,可以选择下面的方式
- SharedPerferences 保存数据,android提供用于保存简单配置信息,标记,用户数据的一种方式
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(10):服务器端和客户端数据类型的自动转换:以XML方式序列化数据、小结
- 简单类型的数据查询
- 通过ajax GET方式查询数据,Django序列化objects
- Parcelable 与Serializable(两种序列化方式用于传输非基本类型的数据)
- MySQL查询中使用Concat关键字来拼接中文字符乱码(不同的数据类型拼接)解决方式
- 数据推荐系统系列 8种方法之零 简单方式 SlopeOne 方式 (补充简单的方式)
- eclipse中保存数据到数据库中乱码简单处理方式
- 数据类型简单总结及学生信息管理系统的调试
- 学生管理系统----文件和数据库(oracle)两种保存数据方式
- 给定数据类型的补码表示,不能简单的用取反加一的方法来求反码的,介绍下2的补码系统
- OC基础-NSNumber类簇-将简单数据类型保存为对象
- Hadoop第7周练习—MapReduce进行数据查询和实现推简单荐系统
- 服务器端和客户端数据类型的自动转换:以XML方式序列化数据
- 新打开窗口,MD5加密,实体类方式保存在Session中,获得系统根路径,分页,动态获取XML数据到页面
- Hadoop—MapReduce进行数据查询和实现推简单荐系统---练习7
- 通过loadrunner 11常规通用的C语言API类型的Vuser 方式,测试验证MySQL数据库插入、查询、修改、删除数据性能脚本实例