Fluentd Casual Talks LT #fluentd #fluentdcasual

  • 7,015 views
Uploaded on

 

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
7,015
On Slideshare
0
From Embeds
0
Number of Embeds
5

Actions

Shares
Downloads
43
Comments
0
Likes
25

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. FluentdとRedisではじめるカジュアルで リアルタイムなレコメンデーション GMO Media, Inc. Business Promotion Office System Architect Hitoshi Asai
  • 2. WORK ScalaJP backend system data reporting awsFAVORITE PLUGINS TWITTER input: tail Hitoshi ASAI buffer: memory @hito_asa プログラマですよ。 output: exec machida, tokyo, jp #fluentdcasual
  • 3. TODAYS AGENDA自社Webサービスに導入したリアルタイムレコメンデーションシステムのおはなしです。ごめんなさい。サービス名は秘密。内容は画像投稿サービスです。 #fluentdcasual
  • 4. DEMO #fluentdcasual
  • 5. システム構成 #fluentdcasual
  • 6. SYSTEM ARCHITECTURE EXEC LOG FILE FORWARD FLUENTD FLUENTD SCRIPT RUBY FLUENTDPHP WORKER WEB SCALA REDIS API #fluentdcasual
  • 7. スケール #fluentdcasual
  • 8. SYSTEM SCALE scale of service 133 MILLION REQUESTS / DAY 7.6 MILLION PICTURES 6.5 MILLION USERS #fluentdcasual
  • 9. SYSTEM SCALE scale of event log 7GB / DAY 1500 EVENTS / SEC #fluentdcasual
  • 10. SYSTEM SCALE scale of servers WEB 18 WEB SRVS 6 REDIS SRVS WORKER 4 API SRVS 4 WORKER SRVS API REDIS #fluentdcasual
  • 11. レコメンデーションの仕組み #fluentdcasual
  • 12. RECOMMENDATION ALGORITHM画像閲覧時のログを取得 210.153.84.41 - - [10/May/2012:20:52:08 +0900] "GET /JP_r0.prcm.jp/default/pic/index/" 200 57 "-“ "ip_fdop_docomo2 5Cb3mxt" "51402666 14235104" USER ID PIC ID #fluentdcasual
  • 13. RECOMMENDATION ALGORITHM各ユーザーの閲覧履歴を時系列にRedisで保持 LPUSH key value (list) vlist_user1 pic5 pic4 pic3 pic2 pic1 vlist_user2 pic7 pic2 pic4 pic1 pic2 vlist_user3 pic4 pic6 pic2 pic3 pic1 #fluentdcasual
  • 14. RECOMMENDATION ALGORITHMListで近接する画像の関連スコアを加算 LRANGE 3 key value (list) vlist_user1 pic5 pic4 pic3 pic2 pic1 pic4 pic5 pic3 pic5 +2 +1 ※スコアリングルールは随時改善 #fluentdcasual
  • 15. RECOMMENDATION ALGORITHM各画像間のスコアをRedisで保持 key: rel_pic4 (hash) key: rel_pic3 (hash) field value HINCRBY field value HINCRBY pic5 5 3 +2 pic5 2 1 +1 pic6 3 pic2 1 #fluentdcasual
  • 16. 非リアルタイム時代 #fluentdcasual
  • 17. NON-REALTIME GENERATION 1時間に1回のSCP & MapReduce scp map-reduce (houry) (houry) WEB SERVERS Hadoop REDIS #fluentdcasual
  • 18. NON-REALTIME GENERATION 低いヒット率画像:60 - 70%検索語:20 – 30% #fluentdcasual
  • 19. リアルタイム時代 #fluentdcasual
  • 20. REALTIME GENERATION ヒット率の劇的な改善画像:60 - 70% 画像:70 - 90%検索語:20 – 30% 検索語:50 – 70% #fluentdcasual
  • 21. IMPLEMENTATIONrecommendation script (ruby) 43 LINES #!/bin/env ruby require logger require redis require redis/distributed VIEW_PREFIX = r_user_gazo_view_ RELATION_PREFIX = r_gazo_relation_ LOGGER = Logger.new("#{ENV[FLUENTD_HOME]}/logs/gazo_recommend.log", 1, 100 * 1024 * 1024) REDISM = Redis.new(:host => "xxx", :port => 6380) REDISS = Redis::Distributed.new(["redis://xxx:6380", "redis://xxx:6380", "redis://xxx:6380", "redis://xxx:6380", "redis://xxx:6380"]) def calc(time, user_id, gazo_id) time_s = time.strftime(%Y-%m-%d %H:%M:%S) view_key = VIEW_PREFIX + user_id.to_s key_org = RELATION_PREFIX + gazo_id.to_s if REDISS.lrange(view_key, 0, 0) != [gazo_id] then REDISM.lpush(view_key, gazo_id) REDISM.expire(view_key, 7200) REDISM.expire(key_org, 28800) rel = REDISS.lrange(view_key, 0, 3).find_all{|r| r != gazo_id.to_s}.uniq.reverse.take(2).reverse rel.each do |r| key_rel = RELATION_PREFIX + r.to_s score = REDISM.hincrby(key_rel, gazo_id.to_s, 1) REDISM.expire(key_rel, 28800) LOGGER.info("#{time_s} - #{user_id.to_s} : #{r.to_s} => #{gazo_id.to_s} score: #{score}") score = REDISM.hincrby(key_org, r.to_s, 1) LOGGER.info("#{time_s} - #{user_id.to_s} : #{gazo_id.to_s} => #{r.to_s} score: #{score}") end end end while line = gets begin l = line.encode!(UTF-8, UTF-8, :invalid => :replace).split("¥t") if l[1] == default && l[2] == pic && l[3] == index then time = l[0] user_id = l[5] gazo_id = l[6] if user_id && gazo_id then calc Time.at(time.to_i), user_id.to_i, gazo_id.to_i rescue nil end end rescue => ex LOGGER.error("error: #{ex}") end end #fluentdcasual
  • 22. エージェントプロセスの負荷 #fluentdcasual
  • 23. LOAD OF AGENT PROCESS load average リリース時から目立った変化はなし。 #fluentdcasual
  • 24. LOAD OF AGENT PROCESS memory usage (rss) 0.10.15 => 0.10.19 へのバージョンアップで改善。 #fluentdcasual
  • 25. LOAD OF AGENT PROCESS memory usage (rss) - weekly 上昇傾向もありません。 #fluentdcasual
  • 26. トラブル #fluentdcasual
  • 27. TROUBLESin_tailで取り込んだログのパースが稀に失敗する 2012-03-27 03:10:27 +0900: fluent/parser.rb:85:parse: pattern not match: "...(a part of log line)"直りました。https://github.com/fluent/fluentd/pull/44 #fluentdcasual
  • 28. TROUBLES あとは特にないです。 とってもカジュアル。とっても安定。 #fluentdcasual
  • 29. 以上です、ありがとうございました。 #fluentdcasual