我说的系统主要是构建在hibernate之上的高效数据库缓存系统,其中包含了分布式解决方案,该系统已经应用在舍得网上了,没有发现大问题,本人也相信该系统已经足够强大,应付数百万IP/天的应用都不是问题,我这么说肯定有人会对此表示怀疑,其实系统到底能撑多少IP/天不在于系统本身而是在于使用该系统的人。
代码看上去很简单,其实却是两年经验的总结,整过过程也遇到了很多难点,最后一一解决了,所以也请各位珍惜他人的劳动成果。本系统非常简洁易用,主程序BaseManager.java不到1000行代码,用“精悍”来形容绝对不为过,1000行代码却包含了数据库对象的缓存、列表和长度的缓存、按字段散列缓存、update延时更新、自动清除列表缓存等功能,用它来实现像论坛、博客、校友录、交友社区等绝大部分应用网站都足够了。
我在理想状态下做了压力测试,在没有数据库操作的jsp页面(舍得网新首页)里可以完成2000多requests每秒(正常情况可能有1/1000的request有数据库查询,其余999/1000都是直接从缓存里读取),物品详情页每秒可完成3000多requests,纯静态html页面也只能完成7000多requests/秒,我对首页进行了三个小时的压力测试,完成了24850800个requests,java一点事都没有,内存没有上涨。按照2000个requests/秒算,一天按15小时计算,那么每天能完成3600*15*2000=1亿零8百万requests,当然这是理想状态,实际状态就算打一折,还能完成1000万pv/天,要知道,这只是一个普通1万3千块钱买的服务器,内存4G,CPU2个,LinuxAS4系统,apache2.0.63/resin2.1.17/jdk6.0的环境。
现在进入正题。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
为什么要用缓存?如果问这个问题说明你还是新手,数据库吞吐量毕竟有限,每秒读写5000次了不起了,如果不用缓存,假设一个页面有100个数据库操作,50个用户并发数据库就歇菜,这样最多能支撑的pv也就50*3600*15=270万,而且数据库服务器累得半死,搞不好什么时候就累死了。我的这套缓存系统比单独用memcached做缓存还要强大,相当于在memcached上再做了两级缓存,大家都知道memcached很强了,但是吞吐量还是有限,每秒20000次get和put当遇到超大规模的应用时还是会歇菜,本地HashMap每秒可执行上百万次put和get,在这上面损耗的性能几乎可以忽略不记了。温馨提示:能不用分布式的时候就不要用分布式,非用分布式的时候再考虑用memcached,我的缓存系统在这方面都已经实现了,改个配置就可以了,有兴趣的可以仔细测试测试!
一般数据库缓存在我看来包含四种。第一种:单个对象的缓存(一个对象就是数据库一行记录),对于单个对象的缓存,用HashMap就可以了,稍微复杂一点用LRU算法包装一个HashMap,再复杂一点的分布式用memcached即可,没什么太难的;第二种:列表缓存,就像论坛里帖子的列表;第三种:长度的缓存,比如一个论坛板块里有多少个帖子,这样才方便实现分页。第四种:复杂一点的group,sum,count查询,比如一个论坛里按点击数排名的最HOT的帖子列表。第一种比较好实现,后面三种比较困难,似乎没有通用的解决办法,我暂时以列表缓存(第二种)为例分析。
mysql和hibernate的底层在做通用的列表缓存时都是根据查询条件把列表结果缓存起来,但是只要该表的记录有任何变化(增加/删除/修改),列表缓存要全部清除,这样只要一个表的记录经常变化(通常情况都会这样),列表缓存几乎失效,命中率太低了。
本人想了一个办法改善了列表缓存,当表的记录有改变时,遍历所有列表缓存,只有那些被影响到的列表缓存才会被删除,而不是直接清除所有列表缓存,比如在一个论坛版(id=1)里增加了一个帖子,那么只要清除id=1这个版对应的列表缓存就可以了,版id=2就不用清除了。这样处理有个好处,可以缓存各种查询条件(如等于、大于、不等于、小于)的列表缓存,但也有个潜在的性能问题,由于需要遍历,CPU符合比较大,如果列表缓存最大长度设置成10000,两个4核的CPU每秒也只能遍历完300多次,这样如果每秒有超过300个insert/update/delete,系统就吃不消了。
在前面两种解决办法都不完美的情况下,本人和同事经过几个星期的思索,总算得出了根据表的某几个字段做散列的缓存办法,这种办法无需大规模遍历,所以CPU符合非常小,由于这种列表缓存按照字段做了散列,所以命中率极高。思路如下:每个表有3个缓存Map(key=value键值对),第一个Map是对象缓存A,在A中,key是数据库的id,Value是数据库对象(也就是一行数据);第二个Map是通用列表缓存B,B的最大长度一般1000左右,在B中,key是查询条件拼出来的String(如start=0,length=15#active=0#state=0),Value是该条件查询下的所有id组成的List;第三个Map是散列缓存C,在C中,key是散列的字段(如根据userId散列的话,其中某个key就是userId=109这样的String)组成的String,value是一个和B类似的HashMap。其中只有B这个Map是需要遍历的,不知道说明白了没有,看完小面这个例子应该就明白了,就用论坛的回复表作说明,假设回复表T中假设有字段id,topicId,postUserId等字段(topicId就是帖子的id,postUserId是发布者id)。
第一种情况,也是最常用的情况,就是获取一个帖子对应的回复,sql语句应该是象
select id from T where topicId=2008 order by createTime desc limit 0,5
select id from T where topicId=2008 order by createTime desc limit 5,5
select id from T where topicId=2008 order by createTime desc limit 10,5
的样子,那么这种列表很显然用topicId做散列是最好的,把上面三个列表缓存(可以是N个)都散列到key是topicId=2008这一个Map中,当id是2008的帖子有新的回复时,系统自动把key是topicId=2008的散列Map清除即可。由于这种散列不需要遍历,因此可以设置成很大,例如100000,这样10万个帖子对应的所有回复列表都可以缓存起来,当有一个帖子有新的回复时,其余99999个帖子对应的回复列表都不会动,缓存的命中率极高。
第二种情况,就是后台需要显示最新的回复,sql语句应该是象
select id from T order by createTime desc limit 0,50
的样子,这种情况不需要散列,因为后台不可能有太多人访问,常用列表也不会太多,所以直接放到通用列表缓存B中即可。
第三种情况,获取一个用户的回复,sql语句象
select id from T where userId=2046 order by createTime desc limit 0,15
select id from T where userId=2046 order by createTime desc limit 15,15
select id from T where userId=2046 order by createTime desc limit 30,15
的样子,那么这种列表和第一种情况类似,用userId做散列即可。
第四种情况,获取一个用户对某个帖子的回复,sql语句象
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 0,15
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 15,15
的样子,这种情况比较少见,一般以topicId=2008为准,也放到key是topicId=2008这个散列Map里即可。
总结:这种缓存思路可以存储大规模的列表,缓存命中率极高,因此可以承受超大规模的应用,但是需要技术人员根据自身业务逻辑来配置需要做散列的字段,一般用一个表的索引键做散列(注意顺序,最散的字段放前面),假设以userId为例,可以存储N个用户的M种列表,如果某个用户的相关数据发生变化,其余N-1个用户的列表缓存纹丝不动。以上说明的都是如何缓存列表,缓存长度和缓存列表思路完全一样,如缓存象select count(*) from T where topicId=2008这样的长度,也是放到topicId=2008这个散列Map中。如果再配合好使用mysql的内存表和memcached,加上F5设备做分布式负载均衡,该系统对付像1000万IP/天这种规模级的应用都足够了,除搜索引擎外一般的应用网站到不了这种规模。
再次申明:系统到底是不是强大不在系统本身而在于使用该系统的人!!!
这个缓存系统是我和同事几年经验的总结,看似简单,其实也没那么简单,把它作为开源有下面几个目的:第一,真的希望有很多人能用它;第二:希望更多的人能够完善和改进它;第三:希望大家能聚到一起为通用高效数据库缓存构架作出贡献,毕竟,数据库操作是各种应用最常用的操作,也是最容易产生性能瓶颈的地方。
Zip包中包含了配置方法和测试用的jsp,只要把它配置成一个web应用就可以快速调试并看到缓存的力量了,文档和下载地址是http://shedewang.com/akaladocs/api/com/akala/dbcache/core/BaseManager.html。群组的地址是http://groups.csdn.net/shedewang_db_cache
配置说明文件在docs/开始配置.txt里有说明。
分享到:
相关推荐
在这个性能测试中,我们关注的是在MongoDB中存储1亿条记录时的随机查询性能。测试环境是基于CentOS 6.4的64位操作系统,硬件配置包括一颗Intel Xeon E5-2630 2.30GHz处理器、64GB内存和6块10K转速硬盘组成的RAID0...
- `@PageSize`: 每页显示的记录数,默认为10。 - `@PageIndex`: 当前页码,默认为1。 - `@doCount`: 是否计算总记录数,0表示不计算,非0表示计算。 - `@OrderType`: 排序类型,0表示升序,非0表示降序。 - `@...
本文以一个实际案例——将10亿级的Elasticsearch (ES) 数据迁移到MongoDB,探讨了这一迁移过程中的成本和性能变化,以及两种数据库的适用场景。 首先,Elasticsearch通常被用于大数据量的全文搜索、模糊匹配和复杂...
- SQL Server概述:Microsoft SQL Server 2005是一个企业级的关系型数据库管理系统,提供数据存储、处理和分析的能力,适合大型应用程序。 - QT C++ 工具概述:QT是一个跨平台的C++开发框架,用于构建用户界面和应用...
- **定义**:数据库审计系统是一种专门用于监控和记录数据库操作行为的安全工具。它主要用于保护企业关键数据资产的安全,通过对数据库活动进行全面监控和记录,确保数据的安全性和合规性。 - **作用**: - **风险...
在实际业务场景中,经常会遇到需要处理千万甚至亿级别的数据记录的情况。例如,在电子商务平台、社交媒体应用等场景下,每天都会产生大量的交易记录、用户行为数据等。这些数据通常会存储在数据库中,并需要频繁地...
尤其是在处理百万级设备指标时,每天数据增加量可能达到上亿条记录,这对数据库的性能和扩展性提出了极高的要求。 HiTSDB作为一款高性能的时间序列数据库,具备以下核心能力: 1. 每秒可写入2000万数据点,能够支持...
高效的研发运维、每日构建发布能力、低成本交易、实时安全控制、毫秒级风险防护能力、高并发交易、支付笔数 10 亿 +、全球服务用户、高可用容灾 > 99.99% 可用性、资产安全管理、全天候资损防控体系、强一致性、快速...
在本课程“龙果学院亿级流量电商详情页”中,我们主要探讨的是如何构建能够承受巨大流量的电商详情页面。这是一门针对Java开发者的高级课程,旨在帮助他们掌握处理高并发、大数据量场景下的网页设计与实现技巧。虽然...
在2013年的双11购物节,阿里巴巴的数据库达到了惊人的峰值,全天成交额达到了191亿,全天订单数突破了1亿笔。数据库的峰值性能表现为:单机QPS(每秒查询数)达到40000,单机TPS(每秒事务数)达到10000,单机逻辑读...
在当前信息化高度发展的时代,数据库已经成为各种业务系统的核心,尤其在公安、政府等领域的应用中,数据库规模往往达到千万甚至亿级的数据量。面对这样的海量数据,如何高效地进行查询、分析、统计,并实现数据分页...
在IT行业中,"阿里亿级高并发"是一个极具挑战性的技术话题,主要涉及到大型互联网公司如何处理海量用户同时在线访问的场景。阿里巴巴作为全球领先的电子商务平台,其背后的技术架构必须能够支持亿级用户的高并发访问...
【10分钟搞懂亿级用户的分布式数据存储解决方案】 在面对亿级用户的互联网服务中,传统的单体数据库往往无法承受巨大的访问压力和数据量。因此,分布式数据存储成为了解决这一问题的关键。本文将深入探讨分布式...
在MySQL数据库中,面对亿级数据的快速清理是一项挑战性的任务,尤其是在磁盘空间告急的情况下。本篇文章将深入探讨几种高效的数据清理策略,以应对上述问题。 首先,当遇到磁盘空间不足的情况,第一步是定位问题。...
2008年,在面对Oracle系统中遇到的诸如CPU和I/O资源紧张、索引过大(超过100GB)、产品表数据量巨大(上亿条记录)、每秒交易量达到数千乃至上万次等挑战时,Cobar被提出并逐步完善。 - **版本迭代**:从v0.6到1.0....
### 千万级Mysql-MongoDB性能对比报告 #### 测试环境配置 - CPU: i5 3.30GHz - 内存: 8GB - 操作系统: Windows 7 #### 测试工具与语言 - **Python**作为测试语言 - **MySQL**版本: 5.1,连接工具为**PyMySQL** -...
- **实践工具**: 使用SQL Server 2005和Oracle 10g进行实践操作,帮助理解数据库的实际应用场景。 - **练习与实践**: 通过实际操作加深对概念的理解,提升解决问题的能力。 - **广泛获取资料**: 除了教科书外,还...