网站改版常见问题答疑

最近常有厦门的客户通过网站上的联系我,询问网站改版的情况。几乎每日都要针对客户网站存在的问题做一番分析,然后客户以价格等其他因素结束对话,如此反复,实在烦人。

  为此做一个内容整理,希望很多只是想了解或者参考资料而不准备花钱改版的客户也不枉此行吧。言归正传。

  一般客户要求对网站改版,无非存在以下原因:

  对网站美工不满意;

  对网站框架(栏目)结构不满意;

  对网站在搜索引擎的排名不满意,希望做一些优化;

  网站年久失修,没人回复,需要彻底重做。。。

  大凡有此需求的客户,都应该值得赞许,至少他们已经认可了网络可以为他们带来一定的信息帮助。同时他们应该也从网络中反馈到很多信息,因此才希望对自身网站进行升级改版。


  根据与客户的沟通得出,一般网站改版包含四个部分:

  网站整体风格改版(美工);

  网站内部代码程序重写(程序);

  以上二者兼顾;

  网站优化,包括搜索引擎优化及网站内部优化更易浏览。要做到这些,所以都必须以用户体验为最终目标。网站不是我们的客户说怎么样就怎么样的,而应该是给最终浏览者去体验的,也就是说改版过的网站应该更容易被搜索到,更容易访问,更容易使用(访客使用和网站管理员使用)。

  那么首先{dy}步,应该询问我们的客户对目前网站不满意的地方,成都网络推广以及他们的客户反馈过来的信息;然后,我们对客户的网站进行剖析,将存在的问题以图表的形式罗列出来;提出我们的解决方案,与客户探讨。然后就是报价。

  至于第二、第三步,很多客户都会要求你越详细越好。而{dy}步呢,客户有时候不愿意说出来或者他根本说不出来。因此需要我们去引导客户。然而到了第四步,就很xx,很多客户,他们更关心价格,或者说他们最希望的价格越低越好,然后才是效果问题。所以,现在都不是很愿意去回答第二、第三个问题了。可能这个也是个人业务能力的问题吧。总之很多客户会说,

  “你的见解很好,我们会很中肯的去接受,但是你的价格我们没办法接受,还是很感谢你的!”


这两天发现我运营的一个门户网站出现了数据无法写入的问题,新会员不能注册,信息不能发布,不能正常登陆会员系统,实在找不到原因,觉定还原备份数据库,但在恢复mssql数据库过程过程中,提示数据库日志满已满,请清空数据库日志后,还原。我想可能就是这个原因导致数据不能正常的写入,然后就baidu搜索了相关的信息,终于找到了原因,程序运行完,修复成功,今天把源代码公布出来,希望对大家有所帮助,大家以后出现相似问题不防也采有清空数据库日志的方法,可以也会解决相似问题,清空数据库日志不会对服务器数据有所损害,能解决数据库不能写入的原因,代码如下:  

'sql数据库连接参数:数据库名(SqlDatabaseName)、用户密码(SqlPassword)、用户名(SqlUsername)、

  '连接名(SqlLocalName)(本地用local,外地用IP)

  Const SqlDatabaseName = "数据库名称"

  Const SqlPassword = "数据库用户密码"

  Const SqlUsername = "数据库用户名"

  Const SqlLocalName = "数据库服务器" '如果服务器是本机,可以设置为:(local),如果是远程要设置数据库ip地址

  '以下内容请不要修改

  Dim ConnStr

  ConnStr = "Provider = Sqloledb; User ID = " & SqlUsername & "; Password = " & SqlPassword & "; Initial Catalog = " &

  SqlDatabaseName & "; Data Source = " & SqlLocalName & ";"

  Set conn = Server.CreateObject("ADODB.Connection")

  conn.open ConnStr

  conn.execute("DUMP TRANSACTION " & SqlDatabaseName & " WITH NO_LOG")

  conn.execute("DBCC SHRINKDATABASE(" & SqlDatabaseName & ")")

  conn.close

  set conn=nothing

  Response.Write "您的mssql数据库日志已清空。"

  %>

        以上代码针对与mssql数据库,支持asp的空间而定,把以上代码保存为某某名字.asp,然后在在输入保存的网页地址,程序运行自动清空数据库日志,xx解决数据库无法写入的问题,希望以上代码对seo站长们有所帮助,谢谢。


系统主要是构建在hibernate之上的高效数据库缓存系统,其中包含了分布式解决方案,该系统已经应用在舍得网上了,没有发现大问题,本人也相信该系统已经足够强大,应付数百万IP/天的应用都不是问题。

  代码看上去很简单,其实却是两年经验的总结,整过过程也遇到了很多难点,{zh1}一一解决了。本系统非常简洁易用,主程序BaseManager.java不到1000行代码,用“精悍”来形容{jd1}不为过,1000行代码却包含了数据库对象的缓存、列表和长度的缓存、按字段散列缓存、update延时更新、自动xx列表缓存等功能,用它来实现像论坛、博客、校友录、交友社区等绝大部分应用网站都足够了。

  现在进入正题。。。。。

  为什么要用缓存?如果问这个问题说明你还是新手,数据库吞吐量毕竟有限,每秒读写5000次了不起了,如果不用缓存,假设一个页面有100个数据库操作,50个用户并发数据库就歇菜,这样最多能支撑的pv也就50*3600*15=270万,而且数据库服务器累得半死,搞不好什么时候就累死了。我的这套缓存系统比单独用memcached做缓存还要强大,相当于在memcached上再做了两级缓存,大家都知道memcached很强了,但是吞吐量还是有限,每秒20000次get和put当遇到超大规模的应用时还是会歇菜,本地HashMap每秒可执行上百万次put和get,在这上面损耗的性能几乎可以忽略不记了。温馨提示:能不用分布式的时候就不要用分布式,非用分布式的时候再考虑用memcached,我的缓存系统在这方面都已经实现了,改个配置就可以了,有兴趣的可以仔细测试测试!

  一般数据库缓存在我看来包含四种。{dy}种:单个对象的缓存(一个对象就是数据库一行记录),对于单个对象的缓存,用HashMap就可以了,稍微复杂一点用LRU算法包装一个HashMap,再复杂一点的分布式用memcached即可,没什么太难的;第二种:列表缓存,就像论坛里帖子的列表;第三种:长度的缓存,比如一个论坛板块里有多少个帖子,这样才方便实现分页。第四种:复杂一点的group,sum,count查询,比如一个论坛里按点击数排名的最HOT的帖子列表。{dy}种比较好实现,后面三种比较困难,似乎没有通用的解决办法,我暂时以列表缓存(第二种)为例分析。

  mysql和hibernate的底层在做通用的列表缓存时都是根据查询条件把列表结果缓存起来,但是只要该表的记录有任何变化(增加/删除/修改),列表缓存要全部xx,这样只要一个表的记录经常变化(通常情况都会这样),列表缓存几乎失效,命中率太低了。

  本人想了一个办法改善了列表缓存,当表的记录有改变时,遍历所有列表缓存,只有那些被影响到的列表缓存才会被删除,而不是直接xx所有列表缓存,比如在一个论坛版(id=1)里增加了一个帖子,那么只要xxid=1这个版对应的列表缓存就可以了,版id=2就不用xx了。这样处理有个好处,可以缓存各种查询条件(如等于、大于、不等于、小于)的列表缓存,但也有个潜在的性能问题,由于需要遍历,CPU符合比较大,如果列表缓存{zd0}长度设置成10000,两个4核的CPU每秒也只能遍历完300多次,这样如果每秒有超过300个insert/update/delete,系统就吃不消了,此路不通。

  在前面两种解决办法都不xx的情况下,本人和同事经过几个星期的思索,总算得出了根据表的某几个字段做散列的缓存办法,这种办法无需大规模遍历,所以CPU符合非常小,由于这种列表缓存按照字段做了散列,所以命中率极高。思路如下:每个表有3个缓存Map(key=value键值对),{dy}个Map是对象缓存A,在A中,key是数据库的id,Value是数据库对象(也就是一行数据);第二个Map是通用列表缓存B,B的{zd0}长度一般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)。

  {dy}种情况,也是最常用的情况,就是获取一个帖子对应的回复,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做散列是{zh0}的,把上面三个列表缓存(可以是N个)都散列到key是topicId=2008这一个Map中,当id是2008的帖子有新的回复时,系统自动把key是topicId=2008的散列Mapxx即可。由于这种散列不需要遍历,因此可以设置成很大,例如100000,这样10万个帖子对应的所有回复列表都可以缓存起来,当有一个帖子有新的回复时,其余99999个帖子对应的回复列表都不会动,缓存的命中率极高。

  第二种情况,就是后台需要显示{zx1}的回复,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

  的样子,那么这种列表和{dy}种情况类似,用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里即可。

  那么{zh1}的缓存结构应该是下面这个样子:

  缓存A是:

  Key键(long型)Value值(类型T)

  11Id=11的T对象

  22Id=22的T对象

  133Id=133的T对象

  ……

  列表缓存B是:

  Key键(String型)Value值(ArrayList型)

  from T order by createTime desc limit 0,50ArrayList,对应取出来的所有id

  from T order by createTime desc limit 50,50ArrayList,对应取出来的所有id

  from T order by createTime desc limit 100,50ArrayList,对应取出来的所有id

  ……

  散列缓存C是:

  Key键(String型)Value值(HashMap)

  userId=2046Key键(String型)Value值(ArrayList)

  userId=2046#0,5id组成的List

  userId=2046#5,5id组成的List

  userId=2046#15,5id组成的List

  ……

  userId=2047Key键(String型)Value值(ArrayList)

  userId=2047#0,5id组成的List

  userId=2047#5,5id组成的List

  userId=2047#15,5id组成的List

  ……

  userId=2048Key键(String型)Value值(ArrayList)

  userId=2048#topicId=2008#0,5id组成的List

  userId=2048#5,5id组成的List

  userId=2048#15,5id组成的List

  ……

  ……

  总结:这种缓存思路可以存储大规模的列表,缓存命中率极高,因此可以承受超大规模的应用,但是需要技术人员根据自身业务逻辑来配置需要做散列的字段,一般用一个表的索引键做散列(注意顺序,最散的字段放前面),假设以userId为例,可以存储N个用户的M种列表,如果某个用户的相关数据发生变化,其余N-1个用户的列表缓存纹丝不动。以上说明的都是如何缓存列表,缓存长度和缓存列表思路xx一样,如缓存象select count(*) from T where topicId=2008这样的长度,也是放到topicId=2008这个散列Map中。如果再配合好使用mysql的拆表和memcached,加上F5设备做分布式负载均衡,该系统对付像1000万IP/天这种规模级的应用都足够了。




郑重声明:资讯 【网站改版常见问题答疑】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——