Share
Embed
Transcript
41 slides
-
3FEJTʹ͍ͭͯ 4FU )BTIׂͱߴڃͳσʔλܕΛඋ͑ͨΠϯϝϞϦ,74 8FCαʔϏεͷߴԽͱ͔ͰΑ͘ΘΕΔ 4PSUFE4FU 3FEJT͕ఏڙ͢ΔσʔλܕͷҰͭ
είΞ͖ͷཁૉͷू߹ʢείΞͰιʔτ͞Ε͍ͯΔʣ ϥϯΩϯάʹ͑Δ ू߹ʹରͯ͠ू߹ੵू߹ͱݴͬͨԋࢉ༻ҙ͞Ε͍ͯΔ είΞσϑΥϧτͰ͠߹Θ͞ΕΔ ਪનɾݕࡧͳͲԿ͔Λ୳͢Ұཡը໘ͷ࣮ʹ͑Δ -
4PSUFE4FUͷ༻ྫ 4UBSͰιʔτ͞ΕͨϦϙδτϦ ݴޠ͕3VCZ·ͨ1ZUIPOͰॻ͔ΕͨϦϙδτϦ ࠓिͷτϨϯυʹࡌ͍ͬͯΔϦϙδτϦ ࠓिͷτϨϯυʹࡌ͍ͬͯͯɺ͔ͭݴޠ͕3VCZ·ͨ1ZUIPOͰॻ͔ΕͨϦϙδτϦ
ݴޠ͕3VCZͰॻ͔Ε͍ͯͯɺ͔ͭYNMΛΩʔϫʔυͱؚͯ͠ΉϦϙδτϦ [શͯͷϦϙδτϦ(Star ΛείΞʹ࣋ͭ)] [ݴޠ͕ Ruby ͷϦϙδτϦ] ∪ [ݴޠ͕ Python ͷϦϙδτϦ] [ࠓिͷτϨϯυʹؚ·ΕΔϦϙδτϦ] [ࠓिͷτϨϯυʹؚ·ΕΔϦϙδτϦ] ∩ ([ݴޠ͕ Ruby ͷϦϙδτϦ] ∪ [ݴޠ͕ Python ͷϦϙδτϦ]) [ݴޠ͕ Ruby ͷϦϙδτϦ] ∪ [จষதʹ “xml” ΛؚΉϦϙδτϦ(ݕࡧΤϯδϯͷධՁΛείΞʹ࣋ͭ)] -
ͱ͜ΖͰɿͲͷٕज़ʹدͤΔ͔ Ϛελʔσʔλతͳͷ%#ʹೖΕΒΕ͍ͯΔ͜ͱ͕ଟ͍ 㲈"DUJWF3FDPSE͍ͬͯ͏࠷ߴͷ03.BQQFS͕͋Δ3VCZΛ͍͍ͨʁ FHϦϙδτϦͷ࡞࣌ɺ4UBS શจݕࡧΛ͍ͨ͠ͷͰݕࡧΤϯδϯ͕͍͍ͨ FHYNMΛΩʔϫʔυͱؚͯ͠Ή
ػցֶशΛऔΓೖΕ͍ͨͷͰ1ZUIPOͰαʔόʔॻ͖͍ͨ FHਪનΛ͍ͨ͠ͷͰॱҐ͚ܭࢉ͍ͨ͠ -
ೋͭͷू߹ͷੵΛऔͬͯ݅औಘ͢Δ 3FEJTΫϥΠΞϯτΛ͏ͱͻͨ͢Βखଓ͖తʹͳΔ ؔʹ·ͱΊΔ͜ͱͰ͖Δ͕ɺେ͖͘վળ͠ͳ͍ c = Redis.new if c.ttl(“src1”)
< 0 c.zadd("src1", [[32.0, "a"], [64.0, “b”]]) c.expire("src1", 60) end if c.ttl(“src2”) < 0 c.zadd("src2", [[44.0, "a"], [21.0, "c"]]) c.expire("src2", 60) end c.zinterstore("dest", ["src1", "src2"]) c.expire("dest", 10) c.zrevrange("dest", 0, 5) #=> [“a"] dest = src1 ∩ src2 -
͍·ΘͤΔΑ͏ʹΩʔΛఆٛ͢Δ ͜͏͍͏ΩʔੜΛΑ͘Δʢ͏͔ͬΓΩʔ͕িಥͨ͠Γ͠ͳ͍ʁʣ lࠓिͷτϨϯυʹࡌ͍ͬͯͯɺ͔ͭݴޠ͕3VCZ·ͨ1ZUIPO Ͱॻ͔ΕͨϦϙδτϦz <ࠓिͷτϨϯυ>㱯 <ݴޠ͕3VCZ>㱮<ݴޠ͕1ZUIPO> ɾɾɾΈ͍ͨͳෳࡶͳू߹ͷΩʔͲ͏ܾͬͯΊΑ͏ʁ
def user_repository_key(user_id) "user_repositories:#{user_id}" end c.zadd( user_repository_key(user_id), get_user_repositories(user_id) ) -
جఈΫϥεɿ3FE#MPDLT4FU SFRVJSFEkey_suffix, get PQUJPOBMcache_time class RepositorySearchService::LanguageSet < RedBlocks::Set
def initialize(language) raise ArgumentError unless Repository::LANGS.include?(language) @language = language end def key_suffix @language.to_s end def get Repository.where(language: @language).pluck(:id) end def cache_time 60.minutes end end -
جຊతͳ͍ํ set = RepositorySearchService::LanduageSet.new(:Ruby) # ઌ಄5݅Λऔಘ set.ids #=> [341, 325,
932, 421, 523] # 10ϖʔδΛऔಘ set.ids(paginator: RedBlocks::Paginator.new(per: 10, page: 10)) # શମͷ݅Λऔಘ set.size #=> 2314 # Redis ͷΩʔΛ֬ೝ set.key #=> “RB:RepositorySearchService::LanguageSet:Ruby” # ໌ࣔతʹ Redis ্ͷσʔλΛ࠷৽ʹ͢Δ set.update! -
3FE#MPDLT4FUHFUείΞͳ͠ͱείΞ͋Γ ཁૉʢJEʣͷϦετɺ·ͨཁૉͱείΞͷϖΞͷϦετΛฦͤΔ ཁૉͷϦετΛฦͨ͠߹ɺείΞશͯʹͳΔ ू߹ಉ࢜ͷԋࢉͷࡍɺείΞσϑΥϧτͰ͞ΕΔͷͰɺͦશମͷείΞʢॱংʣʹӨڹΛ༩͑ͳ͍ ॱংʹڵຯ͕ͳ͘ɺ͍ΘΏΔֶతͳҙຯͰͷू߹Λఆ͍ٛͨ͠߹ɺγϯϓϧʹཁૉ͚ͩΛฦͤྑ͍ def
get Repository.where(language: @language).pluck(:id) end def get Repository.all.pluck(:id, :star_count) end ಛఆͷݴޠͷϦϙδτϦͷू߹ɿ શͯͷϦϙδτϦͷू߹ʢελʔΛείΞʹ࣋ͭʣɿ -
3FE#MPDLT4FUJETۭू߹ͷදݱ 3FEJTͷ4PSUFE4FUͷ༷Ͱɺแ͢Δཁૉ͕݅Ͱ͋Δͱ͍͏ঢ়ଶͱɺ 4PSUFE4FUࣗମ͕ଘࡏ͠ͳ͍ͱ͍͏ঢ়ଶΛ۠ผͰ͖ͳ͍ ͔͠͠ɺʮۭͷू߹Ͱ͋Δʯͱ͍͏ঢ়ଶΩϟογϡ͍ͨ͠ʢྫ͑ɺಛఆͷΩʔ ϫʔυʹΑΔશจݕࡧͷ݁Ռ͕݅Ͱ͋Δͱ͍͏͜ͱࣗମΛΩϟογϡ͍ͨ͠ʣ ࣮ࡏ͢Δཁૉ͕ͱͯ͠औΓಘͳ͍ͷʢA3FE#MPDLTDPOpHCMBOL@JEAʣΛɺ શͯͷ4PSUFE4FUʹඞؚͣΊΔΑ͏ʹ͍ͯ͠Δ
def ids(paginator: Paginator.new) update! if disabled? RedBlocks.client.zrevrange(key, paginator.head, paginator.tail ).reject { |id| id == RedBlocks.config.blank_id } end -
3FE#MPDLT4FULFZ@TV⒏YΩʔͷମܥԽ શମͷ໊લۭؒ3FE#MPDLT͕ར༻͢ΔϕʔεͱͳΔ໊લۭؒ ΫϥεϨϕϧͷࣝผࢠLFZ@QSFpYΫϥε໊Λࣗಈతʹ࠾༻ ΠϯελϯεϨϕϧͷࣝผࢠLFZ@TV⒏YϢʔβʔ͕ఆٛ͢Δ ௨ৗɺΦϒδΣΫτͷଐੑΛҰҙͳจࣈྻදݱʹ͢Εྑ͍ <શମͷ໊લۭؒ>:<ΫϥεϨϕϧͷࣝผࢠ>:<ΠϯελϯεϨϕϧͷࣝผࢠ>
set = RepositorySearchService::LanguageSet.new(:Ruby) set.key #=> “RB:RepositorySearchService::LanguageSet:Ruby” -
3FE#MPDLT4FUVQEBUFσʔλͷࠩߋ৽ ҰશͯΛআ͔ͯ͠Β৽͘͠σʔλΛೖΕΔͱ͍͏ํ๏ͩͱɺ σʔλ͕ͳ͘ͳͬͯ͠·͏ॠ͕ؒ͋Δ ΞοϓσʔτલͱޙͰൺֱ͠ɺফ͑ͨཁૉͷΈΛআ͢Δ είΞશͯߋ৽͢Δ def update!
entries = normalize_entries(validate_entries!(self.get)) removed_ids = self.ids(paginator: Paginator.all, update_if_disabled: false) - entries.map(&:last) RedBlocks.client.pipelined do RedBlocks.client.zrem(key, removed_ids) if removed_ids.size > 0 RedBlocks.client.zadd(key, all_entries) RedBlocks.client.expire(key, expiration_time) end end -
3FE#MPDLT6OJPO4FU3FE#MPDLT*OUFSTFDUJPO4FU HFU3FEJTʹͬͯͳ͍શͯͷแ͢Δू߹ʹରͯ͠AVQEBUFAΛൃߦͨ͠ ޙɺA[VOJPOTUPSF EFTU TSD TSD AͰԋࢉ݁ՌΛ֨ೲ
LFZ@TV⒏YΠϯελϯεϨϕϧͷࣝผࢠʹશͯͷแ͢Δू߹ͷΩʔͷλϓϧ ”[#{ruby_set.key}|#{python_set.key}]"Έ͍ͨͳΠϝʔδ set1 = RedBlocks::UnionSet.new([ruby_set, python_set]) # ܭࢉ݁ՌΛΩϟογϡ͢Δ͜ͱՄೳ set1 = RedBlocks::UnionSet.new([ruby_set, python_set], cache_time: 3.minutes ) # ෳࡶͳωετͪΖΜՄೳ set2 = RedBlocks::IntersectionSet.new(starred_count_set, set1) ˞HFU LFZ@TV⒏YϥΠϒϥϦଆͰ࣮͍ͯ͠ΔͷͰɺΫϥεఆٛͳ͠Ͱར༻Մೳ -
3FEJT্ͷσʔλͷੜଘظؒ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ " 1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ $͔ΒσʔλΛҾ͘ U ෦ͰߦΘΕΔॲཧͷྲྀΕ
3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET -
3FEJT্ͷσʔλͷੜଘظؒ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ " 1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ ྫ͑ɺ͜͜ʹདྷΔ·Ͱʹ"͕FYQJSF ͪ͠ΌͬͨΒɾɾɾ $͔ΒσʔλΛҾ͘
U ෦ͰߦΘΕΔॲཧͷྲྀΕ 3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET -
3FEJT্ͷσʔλͷੜଘظؒ શͯͷू߹ͷϛχϚϜ ͷੜଘظؒΛΩϟογϡ ظؒͱผʹઃఆ͢Δ ͦͷؒʹશͯͷॲཧ ͕ऴΘΔඞཁ͕͋Δ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ "
1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ ྫ͑ɺ͜͜ʹདྷΔ·Ͱʹ"͕FYQJSF ͪ͠ΌͬͨΒɾɾɾ $͔ΒσʔλΛҾ͘ U ෦ͰߦΘΕΔॲཧͷྲྀΕ 3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET -
3FEJT্ͷσʔλͷੜଘظؒ શͯͷू߹ͷϛχϚϜ ͷੜଘظؒΛΩϟογϡ ظؒͱผʹઃఆ͢Δ ͦͷؒʹશͯͷॲཧ ͕ऴΘΔඞཁ͕͋Δ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ "
1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ ྫ͑ɺ͜͜ʹདྷΔ·Ͱʹ"͕FYQJSF ͪ͠ΌͬͨΒɾɾɾ $͔ΒσʔλΛҾ͘ U ෦ͰߦΘΕΔॲཧͷྲྀΕ 3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET def expiration_time RedBlocks.config.min_ttl + self.cache_time end -
3FEJT্ͷσʔλͷੜଘظؒ શͯͷू߹ͷϛχϚϜ ͷੜଘظؒΛΩϟογϡ ظؒͱผʹઃఆ͢Δ ͦͷؒʹશͯͷॲཧ ͕ऴΘΔඞཁ͕͋Δ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ "
1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ ྫ͑ɺ͜͜ʹདྷΔ·Ͱʹ"͕FYQJSF ͪ͠ΌͬͨΒɾɾɾ $͔ΒσʔλΛҾ͘ U ෦ͰߦΘΕΔॲཧͷྲྀΕ 3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET def expiration_time RedBlocks.config.min_ttl + self.cache_time end -
3FEJT্ͷσʔλͷੜଘظؒ શͯͷू߹ͷϛχϚϜ ͷੜଘظؒΛΩϟογϡ ظؒͱผʹઃఆ͢Δ ͦͷؒʹશͯͷॲཧ ͕ऴΘΔඞཁ͕͋Δ 3VCZͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ "
1ZUIPOͷू߹Λ%#͔ΒҾ͍ͯ3FEJTʹอଘ # 3FEJT্Ͱ"ͱ#ͷू߹Λܭࢉ͠อଘ $ ྫ͑ɺ͜͜ʹདྷΔ·Ͱʹ"͕FYQJSF ͪ͠ΌͬͨΒɾɾɾ $͔ΒσʔλΛҾ͘ U ෦ͰߦΘΕΔॲཧͷྲྀΕ 3FE#MPDLT6OJPO4FUOFX <SVCZ@TFU QZUIPO@TFU> JET def expiration_time RedBlocks.config.min_ttl + self.cache_time end RedBlocks.config.min_tll ʼ -
3FE#MPDLT6OJPO4FU3FE#MPDLT*OUFSTFDUJPO4FU class RepositorySearchService def initialize(params); @params = params end def
fetch(per: nil, page: nil) case format when :ids set.ids(paginator: RedBlocks::Paginator.new(per || 10, page || 1)) when :count set.size end end def set @set ||= build_set(@params) end def build_set(params) sets = [PublicSet.new] sets += params.map { |key, value| case key.to_sym when :languages RedBlocks::UnionSet.new(value.map { |v| LanguageSet.new(v) }) when :tags RedBlocks::UnionSet.new(value.map { |v| TagSet.new(v) }) when :keywords RedBlocks::UnionSet.new(value.map { |v| KeywordSet.new(v) }) when :order case value.to_sym when :starred StarredSet.new when :recent RecentSet.new end end }.compact RedBlocks::IntersectionSet.new(sets, cache_time: 5.minutes).unset end end -
ݕ౼ɿ3FE#MPDLTͰͲ͏มΘ͔ͬͨ ಉ༷ͷϩδοΫΛ࣋ͭू߹ΛΫϥε୯ҐͰ·ͱΊΒΕΔ ྫɿݴޠʢʹ֘͢ΔϦϙδτϦͷू߹ʣΫϥε3VCZʢʹ֘͢ΔϦϙδτ Ϧͷू߹ʣΠϯελϯε ݸผͷσʔλΛҾ͘෦Λ4FUΫϥεɺ౷߹Λ4FSWJDFͰߦ ͏ͱ͍͏͕Ͱ͖Δ
ྫɿ֤αϒγεςϜͷΞΫηε4FUΫϥεͷHFUϝιουʹہॴԽ͞ΕΔ 3FEJTʹؔ͢Δ༷ʑͳৄࡉ࣮Λߟྀ͢Δඞཁ͕ͳ͍ ྫɿू߹ͷΩʔΛߟ͑Δඞཁ͕ͳ͍ -
ݕ౼ɿ3FE#MPDLTͰͲ͏มΘ͔ͬͨ ಉ༷ͷϩδοΫΛ࣋ͭू߹ΛΫϥε୯ҐͰ·ͱΊΒΕΔ ྫɿݴޠʢʹ֘͢ΔϦϙδτϦͷू߹ʣΫϥε3VCZʢʹ֘͢ΔϦϙδτ Ϧͷू߹ʣΠϯελϯε ݸผͷσʔλΛҾ͘෦Λ4FUΫϥεɺ౷߹Λ4FSWJDFͰߦ ͏ͱ͍͏͕Ͱ͖Δ
ྫɿ֤αϒγεςϜͷΞΫηε4FUΫϥεͷHFUϝιουʹہॴԽ͞ΕΔ 3FEJTʹؔ͢Δ༷ʑͳৄࡉ࣮Λߟྀ͢Δඞཁ͕ͳ͍ ྫɿू߹ͷΩʔΛߟ͑Δඞཁ͕ͳ͍ ͷΑ͏ͳͷ؆୯ʹͭ͘ΕΔ -
·ͱΊ 3FEJTͷ4PSUFE4FUΛ3VCZͰ4FUΫϥεͱͯ͠ఏڙ 3FEJTʹରͯ͠దͳநԽΛߦ͏͜ͱͰɺෳࡶͳॲཧ͕ 3VCZͰهड़Մೳʹͳͬͨ ͦΕʹΑΓɺ3VCZͰਪનγεςϜͷ౷߹ॲཧͷΑ͏ͳͷ Λ࡞Δ͜ͱ͕Ͱ͖Δ
ϝΠϯͷॲཧ$Ͱॻ͔Εͨ3FEJTͰߦ͏͜ͱͰɺ 3VCZͱ͍͏ݴޠͷԸܙʢߴੜ࢈ੑɾΤίγεςϜʣΛ ੑೳͱཱ྆͠ͳ͕ΒڗडͰ͖Δ ࠓޙɿ4PSUFE4FUҎ֎ͷσʔλܕʹ͍ͭͯͷݕ౼ɺ