V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  soundbbg  ›  全部回复第 2 页 / 共 5 页
回复总数  86
1  2  3  4  5  
2014-05-30 00:56:11 +08:00
回复了 karlxu 创建的主题 程序员 求教:计算代码复杂度的算法是什么?
@lijinma 你理解错了,我没有藐视算法。
2014-05-29 21:42:13 +08:00
回复了 karlxu 创建的主题 程序员 求教:计算代码复杂度的算法是什么?
一开始不需要过度优化,后面针对具体的瓶颈优化就好了。

拿循环做复杂度其实也挺逗的,谁知道函数嵌套了多少个函数,更不要说大部分不间断的程序都是死循环,你没看到只是因为别人都封装好了。

代码里不推荐多个嵌套循环这是必然的,但纯拿循环来说性能就和拿代码行数算KPI一个道理,况且计算机就是一个大循环。
popclip啊。
2014-05-19 11:17:21 +08:00
回复了 yudun1989 创建的主题 酷工作 [北京]下厨房招聘:移动开发,前后端等多个职位
@yudun1989 好的呐,嘻嘻。
2014-05-19 11:12:08 +08:00
回复了 yudun1989 创建的主题 酷工作 [北京]下厨房招聘:移动开发,前后端等多个职位
云顿求带。
2014-05-15 09:08:33 +08:00
回复了 qingfeng 创建的主题 程序员 刚收到小米的短信,让我尽快改密码
@qingfeng so easy了不是。
2014-05-14 18:22:15 +08:00
回复了 qingfeng 创建的主题 程序员 刚收到小米的短信,让我尽快改密码
你既然是程序员,就知道网络里面哪有安全的,太保密的东西还是放保险柜为好。
这个真的没有太大的必要,况且psn会员已经相当诱人了,换来换去挺麻烦还得等,有时候太好玩了想自己留住这个是没办法控制的。

其实有点钱买正版游戏还是很值得的,我正版游戏已经一大柜子了。
2014-05-14 10:52:01 +08:00
回复了 kafkakevin 创建的主题 Python 最近总是无心学习,怎么破?
那就不学习了呗。
2014-05-13 16:02:29 +08:00
回复了 tamamaxox 创建的主题 Linux 如何通过一个耳机线控操作执行程序?
为硬件写一个简单的驱动程序?
2014-05-12 16:41:58 +08:00
回复了 xiaomajia008 创建的主题 程序员 吐槽:jquery 真是给了一些人乱搞的机会~
和jquery没有关系,开发本身不太给力。
纯前端。。
2014-05-05 18:07:17 +08:00
回复了 kurtis 创建的主题 程序员 个人对“情商高”的理解,仅是个人意见
你在说什么读了很多遍我没懂,大概是我智商低,但怎么说,人是复杂的,不是轻易就能定义的,严格要求自己宽容对待别人生活会好过很多。
2014-05-05 13:53:40 +08:00
回复了 hyspace 创建的主题 分享创造 Gitblog.io - 简洁的 Github Pages 博客编辑器
这个项目不错,支持一下。
这设计又让我想到了苹果。。。
2014-05-05 01:13:52 +08:00
回复了 sanddudu 创建的主题 程序员 你愿意为你的博客付多少钱?
github or gitcafe for free.
domain 19$ per year.
2014-04-26 11:10:26 +08:00
回复了 scarlex 创建的主题 程序员 web 后端项目开源的话会有哪些不利的影响?
没什么影响,除了被别人发现你太垃圾。
2014-04-25 15:43:39 +08:00
回复了 selectSum 创建的主题 程序员 360 贴个那么大的东西 员工晒不到太阳啊!摔!
给的钱那么多,晒不到也无所谓了。
2014-04-25 15:42:36 +08:00
回复了 88250 创建的主题 Java Java 开源博客——B3log Solo 0.6.6 正式版发布了!
这个博客略有一些复杂。。。
2014-04-25 10:46:53 +08:00
回复了 gaicitadie 创建的主题 程序员 当前用户信息该不该缓存?
需要缓存。这是结论。

如果你的网站用户量小的可怜,倒是不必,但加了还是比不加好。

这里要理解缓存和数据库的作用是同等重要的,也是需要强调的。

首先需要理解缓存,缓存你可以简单的理解成一个哈希表,通过key就可以取得值。而这个key-value对在内存中,内存的访问极快。如果数据库有索引,那也是相当的快,但索引需要生成文件,如果对大量的key进行索引会导致索引文件数据膨胀,甚至有可能会超过数据文件本身。查询虽然性能消耗的小,但大量的查询性能还是会消耗,相比之下,能节约数据库性能就节约,因为我们程序员是干嘛的?就是为了不必重复劳动。

既然lz对缓存作用有怀疑,觉得sql的查询性能已经很高了,那么我们可以仔细分析,有这么一种情况:

1个用户被100个用户关注。

OK,这样我们如果不使用缓存,加载一个用户的粉丝页面。

1. 首先通过数据库查询到用户,例如from user where id=xxx。
2. 然后通过数据库查到粉丝列表,例如from fans where follow_id=xxx。
3. 显示用户的页面,这里有101个用户。循环查询了from user where id=xxx 101次。

这个时候你会发现,即便是同一个用户,那么访问一次页面需要101个查询,虽然粉丝已经很少了。即便性能很快,还是需要消耗sql资源。如果一个页面每天被访问1000万次,你就自己能够得到结论。

如果使用缓存,会有下面的情况:

1. 首先通过数据库查询到用户,from user where id=xxx,放入缓存。
2. 通过数据库查询到粉丝列表,from fans where follow_id=xxx列表可以放入缓存。
3. 显示用户的页面,假设没有任何缓存的情况下,依旧循环查询了from user where id=xxx 100次。

这个时候再访问同一个页面的时候,假设访问1000万次。

1. 首先通过缓存看用户是否在缓存里,存在,命中返回。
2. 看用户的粉丝列表是否在缓存里,存在,命中返回。
3. 显示用户的页面,100个粉丝的用户都在缓存里,存在,命中返回。

无需数据库查询。

至于当用户的粉丝变动了,如何更新缓存呢,一个简单的方法就是删除缓存。假设用户的粉丝取消关注了这个用户。

1. 删除用户的粉丝列表的缓存。

那么刷新页面的时候就会下面的情况:

1. 首先通过缓存看用户是否在缓存里,存在,命中返回。
2. 看用户的粉丝列表是否在缓存里,不存在,查询数据库from fans where follow_id=xxx,并放入缓存。
3. 显示用户页面,99个粉丝都在缓存里,存在,命中返回。

即便访问依旧是1000万次,只有取消关注的那第一次返回查询了一个数据库,并且是lz说的高性能查询。那么数据库服务器依旧没有什么压力。

至于缓存性能?相当的快,在内存中,可以忽略不计(当然这里也是根据量级来判断,但即便千万用户也可以忽略不计)。

上面的情况只是一个业务里相当小的情况,有比如你当前打开的v2ex这个页面,加载了多少用户、话题和评论?你可以计算一下缓存的优势。

----

当然,继续深入的话,我们推荐缓存什么最好?(正确的缓存不会造成不一致)首先提出不好的:

1. 不要针对页面缓存,这才会造成什么不一致的情况。
2. 不要针对大块数据进行缓存,下面再说。

(其实有时候是可以针对一些业务页面进行缓存的,例如上个月到几年前的每个月的财务结算报表)

要缓存的,最好是最原始的数据。根据上面的情况,例如:

1. 一个用户的数据库数据的缓存。可以直接映射成一个用户的实例。
2. 一个用户的粉丝列表的id缓存,必须强调,这里不是粉丝列表的实例的缓存。

假设通过mc.get(user_key),那么得到的最好是用户数据库里的原数据。如果mc.get(user_fans_key),那么得到的就是用户粉丝的**id**缓存。这里详细说明一下,不要针对大块数据进行缓存的原因。

假设你缓存了大块数据,即拿到用户粉丝的列表不是缓存id,而是缓存对象,那么如果一个用户更新了自己的信息,这个时候并不会删除掉用户的关注列表缓存,对吧,因为粉丝并没有取消关注用户,那么关注列表拿到的用户数就错误了。

另外一个问题就是如果缓存id,即便有100万个粉丝,内存占用也不大,如果100万个实例呢。。。

所以,只针对粉丝的id进行缓存是很重要的,举例说明:

1. 用户有100个粉丝,并且缓存了。
2. 一个粉丝改了自己的名字,这个时候把粉丝的用户缓存失效。
3. 用户查询自己的粉丝时,发现99个用户缓存命中,1个用户缓存失效,查询并放入缓存。

因为在2里粉丝并没有取消关注用户,不会刷新粉丝缓存,如果这个时候缓存的是用户对象,那就出现了不一致。

----

我们可以再发散,为什么现在redis比memcached更热门,因为redis可以直接在内存里排序。假设我有一个需求是最新关注的粉丝在最上面。那么redis可以直接在缓存列表的最前面插入最新粉丝的id,但memcached不行,按上面的方法就是先删除,然后数据库里查询保持顺序,在插入到缓存中。

redis这样的情况可以让类似twitter、新浪微博这样的业务顺利进行,memcached就用起来别扭了。

----

再回到这个页面,我们看看v2ex当前页面可以怎么缓存。

1. 用户信息。
2. lz发的内容的原数据,文字可以放入key-value持久化数据库。
3. lz发的内容的评论id列表。
4. 每个评论的原数据缓存,内容可以放入key-value持久化数据库。
5. 如果有人添加评论,可以过期lz发的内容的评论id列表。
6. 如果有人更新评论,如果是内容,不需要更新缓存,直接更新持久化数据库。
7. 如果有人更新评论如时间之类的,或者删除评论,过期lz内容评论的id列表。

可以看到数据库查询大大的减少,v2ex这个用户量级和访问,至少毫秒内就能展示。

----

我不太同意『缓存』这是一个过度优化的设计,『缓存』这个概念无论是计算机硬件、软件还是web设计都是很重要的。不仅能提升app的使用体验(载入更快了),还减少了sql服务器的压力。

大部分互联网公司都及其依赖缓存,如果缓存服务器挂了,网站必然挂。但之前我也说了,缓存和数据库都是非常重要的,因为在内存中的数据断电就会消失,还是需要持久化的。另外要知道,内存的速度是硬盘访问的数百倍甚至千倍。

正如 @pubby 说的,网站运行了几年,那积累的缓存要是没了,查询流量瞬间就会击垮服务器。

几年前大家做开发的时候,喜欢把数据写入数据库,然后放入memcached,现在更多的开发更喜欢先放入redis,然后写入数据库持久化,当成是log和恢复时使用。当然我觉得可以根据业务来选择不同的方案,不一定redis是最好的(因为它太消耗内存)。

本来想解答lz的没想到说了这么多,只是觉得能反应架构和思维上的区别,当然我是一个垃圾,如果说的有问题还希望大家轻拍。
1  2  3  4  5  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4281 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 34ms · UTC 05:17 · PVG 13:17 · LAX 22:17 · JFK 01:17
Developed with CodeLauncher
♥ Do have faith in what you're doing.