惊现支撑1亿pv/天的超级数据库解决方案

舍得网支撑1亿pv/天构架,开源了
说是支持1亿pv/天,也许有点夸张,也是为了吸引您能点进来,如果您能认真看完相信也不会让您失望,当然,肯定有很多“高手”会对此会嗤之以鼻,没关系,有很多眼高手低的人总喜欢评论别人却从不会看清自己。

如果大家真想支持我、支持中国人开源项目,请把该文贴到自己的博客中或者收藏本文,记得包含文档的下载地址!!!!!!!谢谢。

我说的系统主要是构建在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里即可。

那么最后的缓存结构应该是下面这个样子:

缓存A是:
Key键(long型) Value值(类型T)
11 Id=11的T对象
22 Id=22的T对象
133 Id=133的T对象
……

列表缓存B是:
Key键(String型)                             Value值(ArrayList型)
from T order by createTime desc limit 0,50 ArrayList,对应取出来的所有id
from T order by createTime desc limit 50,50 ArrayList,对应取出来的所有id
from T order by createTime desc limit 100,50 ArrayList,对应取出来的所有id
……

散列缓存C是:
Key键(String型) Value值(HashMap)
userId=2046 Key键(String型) Value值(ArrayList)
userId=2046#0,5 id组成的List
userId=2046#5,5 id组成的List
userId=2046#15,5 id组成的List
……

userId=2047 Key键(String型) Value值(ArrayList)
userId=2047#0,5 id组成的List
userId=2047#5,5 id组成的List
userId=2047#15,5 id组成的List
……

userId=2048 Key键(String型) Value值(ArrayList)
userId=2048#topicId=2008#0,5 id组成的List
userId=2048#5,5 id组成的List
userId=2048#15,5 id组成的List
……

……

总结:这种缓存思路可以存储大规模的列表,缓存命中率极高,因此可以承受超大规模的应用,但是需要技术人员根据自身业务逻辑来配置需要做散列的字段,一般用一个表的索引键做散列(注意顺序,最散的字段放前面),假设以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。

配置说明文件在docs/开始配置.txt里有说明。

最后啰嗦一句,如果大家真想支持我、支持中国人开源项目,请把该文贴到自己的博客中或者收藏本文,记得包含文档的下载地址!!!!!!!谢谢。thank you and Good luck。

QQ群:24561583

复制过来格式有点乱了,还是自己下载一个下来看看吧,里面有个word文档,写得比较清晰。

(0)

相关推荐

  • 惊现支撑1亿pv/天的超级数据库解决方案

    舍得网支撑1亿pv/天构架,开源了 说是支持1亿pv/天,也许有点夸张,也是为了吸引您能点进来,如果您能认真看完相信也不会让您失望,当然,肯定有很多"高手"会对此会嗤之以鼻,没关系,有很多眼高手低的人总喜欢评论别人却从不会看清自己. 如果大家真想支持我.支持中国人开源项目,请把该文贴到自己的博客中或者收藏本文,记得包含文档的下载地址!!!!!!!谢谢. 我说的系统主要是构建在hibernate之上的高效数据库缓存系统,其中包含了分布式解决方案,该系统已经应用在舍得网上了,没有发现大问题

  • MySQL如何支撑起亿级流量

    目录 1 主从读写分离 1.1 core 2 主从复制 2.1 主从复制的过程 2.2 主从复制的副作用 2.3 避免主从复制的延迟 2.3.1 数据冗余 2.3.2 使用Cache 2.3.3 查询主库 3 如何访问DB 3.1 应用程序内部 优点 缺点 3.2 独立部署的代理层方案 优点 缺点 4 总结 FAQ 1 主从读写分离 大部分互联网业务都是读多写少,因此优先考虑DB如何支撑更高查询数,首先就需要区分读.写流量,这才方便针对读流量单独扩展,即主从读写分离. 若前端流量突增导致从库负载

  • 惊现学习CSS应该注意的方法

    学习任何东西都是一样,从小学.中学.大学,除了学习知识外就是去学习方法! 要想掌握CSS, 首先要学会HTML,我刚开始是从零开始学习的,花了一个月时间学习HTML,没有老师,书就是我唯一的老师,也没有上网的条件!一个月过后,我就开始学习CSS,刚开始看的第一本CSS书是<CSS网页样式设计>看了几天后发现根本看不懂!,之后换了一本<HTML参考大全>,这本书是网页制作师的案头常备之书!之所以更换这本书来学习CSS,是因为这里面有一部分是CSS,就成了我的CSS启蒙书.看了几段后,

  • 惊现瑞星升级原理详解,其实早就有人破解了

    中天.比特均通过修改 Hosts 文件实现瑞星升级, 剑盟则是通过设置代理服务器实现. 大概的过程就是让瑞星的智能升级程序连接到非官 方服务器.正如比特网 abcbit 所言:"虽然修改hosts仅仅是一小步,但是幕后的工作确是一大步." 有很多网友问关于瑞星升级的原理, 网上也出现了许多解释, 我写本文的目的只是为了把这个过程说得更具体.仅属个人意见, 供大家参 考, 可能会有些错误. 瑞星智能升级程序 (Smartup.exe) 启动的时候, 首先连接以下地址检测最新版本: htt

  • phpBB 2.0.13惊现漏洞的解决

    一.Path Disclosure 漏洞文件:/db/oracle.php 漏洞描叙:直接访问oracle.php,导致暴露web路径 涉及版本:phpbb <=2.013 测试:ie提交http://127.0.0.1/phpBB2/db/oracle.php 返回错误: Fatal error: Cannot redeclare sql_nextid() in f:\easyphp1-7\www\phpbb2\db\oracle.php on line 405 解决办法 如果你不是采用的or

  • 落伍惊现GG判断作弊的一些绝对机密标准

    今天有机会和好久没有见面的中国GG的一个朋友聚在一起了!我便和他闲谈中得知了一些关于GGAD的一些机密标准!呵呵大家不要见笑哈!我今天说这些的目的不是在于帮助你们去作弊!而是让大家清楚不要做违反GG条款的一些事情!我大致总结了一下!大家可以参考一下!    在喝茶的时候我就问我朋友!  我说为什么你们在封人家的号的时候能够知道那些在作弊呢?因为是铁哥们.而且我也在做这个的推荐所以嘿嘿!我朋友就给我透了点风.  他说!其实我们主要是通过IP来判断的.因为做点击广告判断的主要就是IP地址.把这些IP

  • 惊现索引擎如何索引收录网页的方法

    highdiy 发表在 五月 9, 2007  对SEO(搜索引擎优化)而言,让网站内的页面能够及时.全面地被搜索引擎索引.收录应该说是首要的任务,这是实施其他SEO策略的最基本保证.--不过,这也是往往易被高估的一个环节,比如说我们时常可以看到某些人宣称自己的网站被Google收录了多少页面如几K甚至几十K等以证明SEO工作的成功.但客观地说,网页仅仅被搜索引擎索引.收录是没有太大的实际意义,往往只能沦为浩如烟海的Internet世界中的殉葬品,更重要的是如何让网页出现在针对特定搜索项的SER

  • 惊现统计站背后隐藏的巨大黑幕 怕怕第1/2页

    这样一个黑幕揭露出来可能会招来很多人的攻击,因为其中的利益实在是太大了,甚至可以决定到一个庞大的搜索引擎帝国的生死存亡.也许这样说没有几个人会信,但是你看完我的分析你就会有一种如芒在背的感觉,因为你所视为珍宝的一些秘密从此不再安全,你的经验从此就变成了某个帝国扩张的工具. 说了这些玄乎的东西,有点烦了吧,现在转入正题.我迟迟不愿意转入正题是因为我不能确定这样的想法会不会是另一个疯狂的杞人忧天的故事. 今天,就在今天.我作为一个普通的站长,在打开雅虎统计(tongji.cn.yahoo.com)之

  • 1亿条记录的MongoDB数据库随机查询性能测试

    mongdb性能压力测试,随机查询,数据量1亿条记录 操作系统centos6.4x64位 从测试结果看,当mongodb将数据全部载入到内存后,查询速度根据文档的大小,性能瓶颈通常会是在网络流量和CPU的处理性能(该次测试中当数据全部在内存后,纯粹的查询速度可以稳定在10W/S左右,系统load可以维持在1以下,由于此时CPU已经被使用到极限了,当并发再大时load值会直线飙升,性能急剧下降). 压力生成服务器与Mongodb服务器基本配置 cpu型号:Intel(R) Xeon(R) CPU

  • jquery实现瀑布流效果 jquery下拉加载新数据

    瀑布流效果在很多网站还是有的,这种错落有致的排布看着还是很不错的呢.今天我就来记录一下关于用jquery实现瀑布流效果的代码: 一.页面基本排版 1. items盒子主要用来存放我们需要摆放的数据item: 2. tips是页面加载数据的时候用来提示用户的文本: <div class="wrapper"> <div class="items"> <div class="item"></div> &l

随机推荐