姑娘是亮点。。
#21 楼 @zhangjinzhu 我刚装了下 qor_cache,看了下源码,确实是读了两次 memcache 换来了不用清除缓存。
我想下吧。没在真实的产品环境实验过,读两次代价也挺高的,毕竟不是单机进程内读数据。 调用 memcache 是有网络开销的。你要一个方法内有 4 次调用数据库,无形中就可能多了 4 次的 memcache 调用。
谢谢啊。这么有耐心的回答。。
你是想告诉我 cacheKey 对应类名,方法名存在 memcache 里面?这得查询多少次,感觉不太划算吧。。。?
#18 楼 @zhangjinzhu 我知道你这个意思。我怀疑是我表述的太不清楚了?
我刚问的意思就是 getCacheKeyFromMemcache() 你这个方法你准备怎么写。
你想想具体实现会很容易么?
问题是你怎么处理这个同享的 cache key?
假设 login_by_email 方法,你两边怎么产生这个一致的 Key?
rails cache_key(123456) -> customer1 java cache_key(123456) -> customer1
rails 中 customer 变了 (你的思路是变 key 这个没错,不清除缓存) rails cache_key(56789) -> customer1_change java cache_key(123456) -> customer1
这个时候 java 得使用 cache_key(56789)?我怎么知道这个新的 key(56789)?
#14 楼 @zhangjinzhu 如果同一个数据库里的同一个 customer(Id;1),你有 rails 程序和 Java 程序,你在 memcached 里面保存几份 customer 对象?
我怀疑多个 Rails 程序集群的时候也可能会有问题。
如果 customer 对象在数据库里被更新了,你怎么保证 Rails 程序和 Java 程序读到的是最新的 Customer 数据?
因为可能是通过 Rails 程序更新的数据库而 Java 程序根本就不知道这个 Customer 被更新了
#12 楼 @zhangjinzhu 你这个是类名 + 方法名 + 随机数,如果我只有 rails 的 app 还行,但是我要在 Java 那边和这个 Key 对起来更麻烦了。我想的是 Java 和 Rails 生成的缓存的 Key 的规则是一致的,就是我 Java 的 lib 可以使用 Rails 程序保存的 memcached 的对象,这样的好处是,内存节约了,更新在一个端更新另外一端使用就行了。
不然的话我就需要处理如果 Rails 这边更新了数据库,Java 那边的缓存怎么办的问题。
#9 楼 @zhangjinzhu 我有很多是类方法,比如 Customer.find_by_email , 这个时候缓存的 Key 是 customer_{#email} => 对应 customer id
比如登录这个场景,这个时候不是一个对象的实例方法,没有 model 的 updatedAt 这个时间戳的
#4 楼 @Rei #6 楼 @zhangjinzhu 想问一下,如果我是两种语言混用的项目,前台用 Rails 后台用 Java, 如何共享缓存,或者怎么使用 memcached.
假设有 Customer 对象在 Rails,Java 中都被缓存了,如果是从 Rails 程序更新了 Customer 对象和缓存,怎么使 Java 缓存失效?
没看到有现成的库两边的 Key 和保存的 Json 都能通用的呢?
一般几个思路?
搜索了一些资料,不知道大家常用的,以及使用的过程中有没有遇到什么比较坑的事情。
1) dalli https://www.digitalocean.com/community/articles/how-to-use-memcached-with-ruby-on-rails-on-ubuntu-12-04-lts https://github.com/mperham/dalli/
2) cache method https://github.com/seamusabshere/cache_method
3) find cache https://github.com/mustafaturan/find_cache
4) second_level_cache (csdn) https://github.com/csdn-dev/second_level_cache https://github.com/hooopo/second_level_cache (支持 Rails 4)
db 如果是 redis 的话,也不需要多大改动,原则就是实体用 hash 结构,关系可以用 set
hash: document user
set public_document user_:id_document admin_user normal_user document_:id_recommend_user user_:id_recommend_document
document id owner_id title content keyword created_at type(private,public) status
user id email password type(teacher,student)
document_recommend id document_id to_user_id document_owner_id
爬虫的速度,一般都有啥办法提升?
还有一种情景,我有大量的 facebook 的 oauth token,需要抓取用户最新的 feed,我一分钟能拿多少个人的数据,有啥办法提高速度?多线程应该算一种吧,有没有其他好的思路?
挺好的。赞一个。
当然找不到,对象嘛,用完都释放了。不释放就内存泄露了。。要死人的。
其实你仔细观察会发现,传入 block 的时候,如果参数是一个 Array,则 Array 里面的参数与 block 的 参数一一对应。我猜测 Array 被当成可变长度参数传递了?分析
test_yield("locale", ["name","desc"], "locale") do |arr,locale|
puts arr.class.to_s
puts arr.to_s
puts locale
end
会发现其实 arr => "name" locale => "desc"
所以 arr.class.to_s 为 String 而不是 Array.
但是根据推断,执行下面的代码结果又会让你大吃一惊
test_yield("locale", ["name","desc"], "locale") do |arr|
puts arr.class.to_s
puts arr.to_s
end
打出的是 Array,"name",
再如
def test_yield (select_locale,value,locale)
if select_locale == locale
yield locale,value
end
end
test_yield("locale", ["name","desc"], "locale") do |arr,aaa,bbb|
puts arr.class.to_s
puts arr.to_s
puts aaa.to_s
puts bbb.to_s
end
再如
def test_yield (select_locale,value,locale)
if select_locale == locale
yield value,locale
end
end
test_yield("locale", ["name","desc"], "locale") do |arr,aaa,bbb|
puts arr.class.to_s
puts arr.to_s
puts aaa.to_s
puts bbb.to_s
end
结合上面的例子,你会发现,当你往 block 传递参数的时候 有且只有一个参数,且参数为数组 a. 如果 block 只有一个参数,则数组会当成一个参数, b. 如果 block 的参数大于传递进来的参数,数据里会当成可变参数
如果有多个参数 a.所有的参数和 block 依次对应
所以我不建议你这么写,你这么写可能不是一个规范的写法
有时间可以查查关于 Block 的资料,我还没来得及看 - - http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_methods.html
执行结果应该是 Array 而不是 Hash, 所以你说的换成 Hash 是对的,是不成立的
arr = [:name=>"name",:desc=>"desc"]
puts arr.class.to_s
puts arr.to_s
改了 yield value,locale
block 是两个参数,你传了一个进去
def test_yield (select_locale,value,locale)
if select_locale == locale
yield value,locale # 需要两个参数?
end
end
test_yield("locale", ["name","desc"], "locale") do |arr,locale|
puts arr.class.to_s
puts arr.to_s
puts locale
end
你有没有觉得你写的代码的本质是类似
def test
i = 1
def test2
puts i
end
test2
end
test()
第一反应是看见这样的代码,就想揍人。
我改了下:
F = {}
def data name = '', &block
F[name] = [] unless F.include? name
F[name] << block
end
def do_data name
i = 2
h = {}
F[name].each do | b |
# 传递参数到 block
h.merge!(b.call(i))
end
h
end
# call data function to generate data
data :a do |i|
{
:a1 => i,
:a2 => 'a2222',
}
end
p do_data(:a)
为什么不直接做缓存
在 2 楼基础上改,既然是在 Module 上定义,应该是想通用吧?
class Module
private
# Generate a string of code to define attr reader methods.
def readonly(*syms)
return if syms.size == 0
code = ""
syms.each do |s|
code << "def #{s}; @#{s}; end\n"
end
# Create instance methods.
class_eval code
end
end
class Test
readonly :x
def x=(value)
@x = value
end
end
test = Test.new
test.x = 'ok'
puts test.x
Chrome 最近是有点差了.. 我的还老崩
这哥们还是挺聪明的,需要有人驾驭,需要经历一些。年少轻狂