技术开发 频道

开发实战:舍得网44587行代码开发经验

  舍得网(shedewang.com)的开发暂时告一段落,一个人用时不到1个月,java底层代码16902行,jsp代码27685行,共计44587行。整个开发过程遇到过许多问题,但最后都解决了。下面把我在开发中遇到的所有问题和解决办法列出,供参考。

  系统构架:

  redhat AS4/apache2.0.59/resin2.1.17/jdk6.0 u2/hibernate3.0/lucene2.2/urlrewrite3.0.4,数据库用得是mysql4.1.15,数据库缓存是构架在hibernate之上的,是一个只有794行的java类,但这个java类却做了数据库对象缓存、列表缓存、update缓冲、自动删除列表缓存,还提供了数据库查询、更新、插入的所有操作,它节省了我一半以上的开发时间。一个获取含有五个查询条件获取列表的方法只用不到10行代码就可以了。【增加:现在我已经把这个数据库操作工具改成分布式了,可以随便增加java应用服务器实现负载均衡,并且各服务器之间可以实现缓存同步,这样,即使每日用户达到百万级别,我的构架也是可以支持的,我将在下面详细说明我的构架,仅供参考。许多人要求我开源,我觉得现在系统还没有经过大规模用户的并发验证,还不是时候,以后我会考虑开源的,我的代码没有太多高深的算法和设计模式,主要用到了模板模式,但全是用心写出来的。

  问题一:

  做数据库缓存时遇到的问题。HashMap在并发遍历时会报ConcurrentModificationException,即使使用Collections.synchronizedList把Map包起来还是会报这个异常,这个问题很简单,解决办法也简单。第一种解决办法是不要用Map的iterator来遍历,而是用Set(Map.keySet方法)的toArray方法来遍历,这种办法虽然会损耗一定的性能和内存,但比在方法前加synchronized好得多;第二种解决办法用jdk5.0以后的ConcurrentHashMap来实现。

  修正:经过测试和验证,第一种方法不行,也就是并发操作MAP而且要求遍历的时候只能用ConcruuentHashMap,在此要感谢写ConcurrentHashMap的专家们。

  增加:数据库的缓存有很多种办法,对于单个对象的缓存比较容易,直接用HashMap都可以,但是对于列表的缓存就比较复杂了,网上说到的memcachedb+memcache_engine或者berkeleydb应该都是做不到列表自动缓存,因为增加一条记录后会影响许多列表的排序,所以什么时候删除列表缓存是个比较头痛的问题,我的解决办法是列表的缓存的key便包含了查询条件信息。如一个表T有字段A,B,C,对应T.java有域A,B,C,那么查询一个A=1 and B=2 and C> 0 的组合条件的列表的key就是A=1#B=2#C> 0,这样,如果增加了一个对象T,其中T.A=1,T.B=3,T.C=0,显然上面列表查询条件包含了条件B=2,而增加的对象B=3,那么无论如何这个新增加的对象T都不可能在这个列表中,也就是说不用删除这个列表,只有增加的对象T满足T.A=1、T.B=2、T.C> 0时该列表才需要重新从数据库中获取,以此可以推出更新、删除一个T对象时什么时候需要删除什么列表。

  增加:至于分布式,我用到了memcached来做远程缓存,利用UDP报文来保持各服务器之间的缓存同步。如获取一个对象:首先在本机缓存中获取,如果没有再去远程memcached server中获取,如果还没有才从数据库中获取并同时放入memcached server 和本机缓存,这样,不管有多少台服务器在做负载均衡,对于一个对象T,只需要在数据库中读取一次,其他所有服务器都可以共享了,数据库查询的压力几乎没有,当然如果插入和修改的次数达到每秒几千次,我可能会用到mysql-proxy,但目前看来,几十万的用户/天的量都用不着,用个好点的数据库服务器即可

  不谦虚的说,我的这套分布式缓存方案是比较强大的,都是用心写出来的,虽然代码只有2874行。实例:如要获取一个id为6789的用户,只要用User u =UserManager.getInstance().getById("6789");一句话即可,所有缓存逻辑都已经包含在里面了。

  问题二:

  jfreecharts在Linux上不能显示中文,这个问题没有费多长时间就解决了,上网一搜就搞定,解决方法如下:

  到网上下载一个linux下的ttf字体,本例用的是zysong.ttf

  1.确认%JavaHome%/jre/lib/fonts目录下存在zysong.ttf

  2.在%JavaHome%/jre/lib/fonts目录下执行"ttmkfdir -o fonts.dir"命令,重新生成fonts.dir文件

  3.确认/usr/share/fonts/zh_CN/TrueType目录存在,如果不存在则mkdir创建

  4.确认/usr/share/fonts/zh_CN/TrueType目录下存在zysong.ttf

  5.在%JavaHome%/jre/lib目录下,执行 cp fontconfig.RedHat.3.properties.src fontconfig.properties

  6.重起resin,OK。

0
相关文章