#personalizedset
Explore tagged Tumblr posts
humongouswerewolfdefendor · 3 months ago
Text
Tumblr media
Discover trendy pet accessories at CurliTail! Shop stylish, comfortable, and high-quality collars, leashes, and more for your furry friend. https://curlitail.com/
0 notes
dog1-collars · 3 months ago
Text
Shop the Vector Personalized Pet Toy Basket at CurliTail. Stylish, durable, and custom-made for your pet. Perfect for organizing toys. Made in the USA. https://curlitail.com/.../vector-personalized-pet-toy-basket
Tumblr media
0 notes
annu11 · 4 years ago
Photo
Tumblr media
Organic Pillow & Bolster Set Organic pillow & bolster set at little west street. Snugly soft organic pillow and bolsters for baby’s extra comfort. Grab some unique and attractive Kids accessories online that makes your kid shine
0 notes
undibujopordia · 6 years ago
Link
For just $148.00 --------------------------------------------- -------- SAVE $20 ------------ --------------------------------------------- CLASSIC MOTORCYCLES Original drawings prints Digitally printed on 200 grs acid free paper, professional quality. Image size 11 x 14 inches (for standard frames) The watermark not appear in prints. NOTE: Colors may vary from screen to screen. This price is for Registered shipment! Unframed Prints will be shipped in a cellophane sleeve. I send my prints off to their new home within 1-3 days of payment. I ship my international orders by air after I'm notified of your payment, and taking between 10 to 20 days to arrive. The purchase of any print does not transfer reproduction rights. ©Pablo Franchi -------------------------------------------------------------------------------------------------- Motorcycles BY YEAR: https://www.etsy.com/shop/drawspots?ref=hdr_shop_menu§ion_id=19206680 Motorcycles BLACK & WHITE: https://www.etsy.com/shop/drawspots?ref=hdr_shop_menu§ion_id=19206694 If you like CARS, take a look here: https://www.etsy.com/shop/drawspots/items?section_id=11083041 MUSICIANS, JAZZ portraits & quotes: https://www.etsy.com/shop/drawspots?section_id=11220720 ----------------------------------------------------------------------------------------------------
0 notes
sibellejewelry-blog · 7 years ago
Photo
Tumblr media
Gift Set of keychains for an upcoming wedding for the bride and groom🌹 #beautyandthebeast #customkeychains #couplesset #hisandhers #keychainset #pennykeychains #penny #custompenny #weddinggift #brideandgroom #hisbeautyherbeast #luckyinlove #initials #weddingday #daytocelebratelove #handstampedkeychain #personalizedset #personalizedkeychain #giftswithmeaning #makingthingspersonal #sibellejewelry
0 notes
takenos · 7 years ago
Text
オブゞェクト指向プログラミングにおける Redis Sorted Set の抜象化
本皿は 技術曞展4 にお頒垃される WANTEDLY TECH BOOK 4 に掲茉される予定の文章です
はじめに
Redis の Sorted Set を䜿った䞀芧画面の実装パタヌン
Web サヌビスにおいお Redis の Sorted Set は高速なランキングの実珟のためにしばしば甚いられる。ランキング・デヌタを Redis に茉せるこずで、高速なデヌタの取埗・ペヌゞング・件数蚈算などが可胜になる。ランキングのように順序付けされたコンテンツは Web サヌビスの䞀芧画面ず呌ばれるペヌゞにおいお存圚するが、このような画面においおはしばしばリテンションが重芁である。レスポンス速床はこのリテンションに察しお圱響を䞎えるため、高速な実装が求められる。
䞀方、時系列で考えた堎合、䞀芧画面の芁件はサヌビスの扱うコンテンツ数が増加するに埓っお耇雑化する。䟋えば、ナヌザヌが適切なコンテンツを発芋できるようにする必芁が出おきお、そのために様々な条件による絞り蟌みや怜玢、あるいはパヌ゜ナラむズされた掚薊ず蚀った機胜が必芁になっおくる。
これらの機胜をどのように実珟したら良いだろうか。通垞、絞り蟌みに䜿われるようなコンテンツのデヌタはリレヌショナルデヌタベヌスに保存されおいる。䞀方で、怜玢の実珟には Elasticsearch などの党文怜玢゚ンゞンが採甚されるこずが倚い。たた、昚今では機械孊習が掻甚されるこずも倚いが、そのような凊理を行うためのラむブラリは Python が充実しおいる。このように、ナヌザヌに䟡倀を提䟛できる䞀芧画面に求められる機胜は倚く、たたそれを実装するために最適な技術は必ずしも䞀぀には定たらない。
マむクロサヌビス・アヌキテクチャを採甚しおいる堎合、各機胜を実珟するのに最適な技術に基づいたマむクロサヌビスを実装し、それらを組み合わせるこずによっお䞀芧画面を実珟するこずが考えられる。しかしこのずき、各マむクロサヌビスをどのような方法で統合するのかずいうこずが課題になる。
既に述べたように Redis の Sorted Set はランキングに利甚されるこずが倚いが、和集合・積集合など組み蟌みの集合挔算の呜什を䜿うこずで絞り蟌みや怜玢、あるいはパヌ゜ナラむズず蚀ったより高床な機胜を実珟するこずができる。そこで、異なるシステムから集めた情報をそれぞれ別個の Redis の Sorted Set にキャッシュした䞊で、それを集玄蚈算しお䞀芧画面に必芁な情報を算出するような構成を考えるこずができる。
Tumblr media
この構成では、任意のマむクロサヌビスやデヌタベヌスからの情報をスコア付きの集合ずみなした䞊で統合するこずができる。たた、レスポンスに必芁な党おのデヌタは䞀床 Redis に乗るため、蚈算の内容も様々である各システム矀がサヌビスずしお求められおいるレスポンス速床を盎接満たさなくおも党䜓ずしお高速に動䜜するず蚀った利点もある。
事䟋
Wantedly Visit では数十䞇件の募集が存圚するが、その䞀芧画面 https://www.wantedly.com/projects は䞊蚘のような芁件を持぀䞀䟋である。この画面は実際にこの構成ずこれから玹介する RedBlocks を䜿っお実珟されおいる。
実珟する䞊での課題
課題1: オブゞェクト指向プログラミングず Redis のコマンド䜓系のむンピヌダンス・ミスマッチ
このように Redis の Sorted Set を甚いるこずで䞀芧画面に必芁な機胜を実珟するこずができるわけだが、その実装を Redis のコマンドをそのたた呌び出す圢で行うず、Ruby などのオブゞェクト指向プログラミング蚀語に斌いおは高い可読性・倉曎容易性を実珟するこずができない。
具䜓的には、Redis のコマンド䜓系が呜什的なものであるため、それをそのたた利甚するず手続き的なプログラムになっおしたう。この問題は、 単玔なキャッシュ目的で Redis を利甚しおいるずきには倧きく問題にならないが、今回述べたように耇雑なシステムを構築する際には問題ずなる。具䜓的には、䜕かアプリケヌションの倉曎を行うずきに倉曎箇所を芋぀け出すこずが難しかったり、耇数の箇所を倉曎する必芁が生じる倉曎に察しおモゞュラでない、関心が分離されおいない、ず蚀った状態になる。
# 非垞に単玔な集合挔算を曞くだけでも倚くの呜什が必芁にになる c = Redis.new c.zadd("src1", [[32.0, "a"], [64.0, "b"]]) c.expire("src1", 60) c.zadd("src2", [[44.0, "a"], [21.0, "c"]]) c.expire("src2", 60) c.zinterstore("dest", ["src1", "src2"]) c.expire("dest", 10) c.zrevrange("dest", 0, 5) #=> ["a"] c.zcard("zcard") #=> 1
通垞、リレヌショナル・デヌタベヌスをオブゞェクト指向の蚀語から利甚する堎合、集合指向ずの抂念的な差異あたり良いメタファヌずは蚀えないが「むンピヌダンス・ミスマッチ」ず呌ぶこずがあるので本皿でも甚いるが問題になるため、O/R Mapper による抜象化を行った䞊で利甚するこずが倚い。同様の理由で、Redis の Sorted Set を Ruby から利甚する際も OOP に即した圢で抜象化を行うこずでこの問題を解決するこずが必芁になる。
解消すべき差異の䟋ずしお、クラスベヌスの OOP においおは、クラスはそれ自䜓で盎接アプリケヌションに必芁な仕事を果たすわけではなく、むンスタンス化を通じおそれを行う。Redis の Sorted Set にクラスずむンスタンスのような抂念は無いため、key の階局化を通じおこれを実装する必芁がある。
課題2: 実装に必芁な倚くの詳现
実際にサヌビスで利甚するためには抂念的な差異以倖にも倚くの隠蔜できる実装詳现がある。䟋えば、次のようなこずは本来、郜床アプリケヌションを開発するプログラマが考える必芁のないこずである。
キャッシュの存圚の有無をチェックしおなければデヌタを取埗し Redis に保存する
キャッシュが無い時間が存圚しないように差分曎新にする
盎列䟝存性のないコマンドのパむプラむン実行
Redis の key に䜿う名前
このような実装詳现を隠蔜するこずで、アプリケヌションを開発する際、
1) サヌビスの仕様ずしお各マむクロサヌビスをどう組み合わせるかAND なのか OR なのか、スコアをどう組み合わせるか
2) それぞれの蚈算段階におけるデヌタをどの皋床キャッシュするか
ず蚀った統合に関する仕様これはサヌビスの䟡倀に盎結するにプログラマは集䞭できるようになる。
RedBlocks
具䜓的に䞊蚘のような問題を解決するために、、RedBlocks ずいう Ruby ラむブラリ(gem)を甚意した。
以降では、RedBlocks を通じおどのように耇数のシステムを組み合わせるかを、実際の䞀芧画面の実装を通じお玹介する。その埌、いく぀かの実装詳现に぀いお蚀及し、最埌にたずめずする。
Case Study: RedBlocks を甚いた䞀芧画面の実装
この章では、課題1ずしお述べたオブゞェクト指向プログラミングず Redis のコマンド䜓系のむンピヌダンス・ミスマッチがどのように解決できおいるのかを実䟋を通しお説明する。そのために、次のような䞀芧画面を想定する。
Tumblr media
この画面には、䞻に次の4぀の機胜が備わっおいる。たた、共通する機胜ずしお件数衚ᅵᅵずペヌゞングができる。
ランキング初期状態
絞り蟌み
党文怜玢
パヌ゜ナラむズナヌザヌ登録しお利甚しおいる堎合
これらの機胜を順次実装しおいき、最埌にそれをナヌザヌの操䜜に応じお行う service クラスを実装する。
1. ランキング
ほが党おのサヌビスにおいお、䞀芧画面ではコンテンツ以䞋、芁玠をどのような優先床で衚瀺するのかずいうこずを考える必芁がある。これはランキングに盞圓する。党おのナヌザヌに同じ順番で芋せる堎合、ランキングを䞀぀だけ甚意すれば良い。ランキングは、それぞれの芁玠に察しおスコアが付いた集合、ず捉えられるため、Redis の Sorted Set を利甚しお実装するこずができる。
ここでは、䞀芧画面が扱う芁玠ずしお募集Projectを想定した䞊で、カラムずしお monthly_page_view を持った Project ずいうActiveRecord モデルがあるするずする。このカラムの倀を利甚しお PV ベヌスのランキングを䜜成したい。このための RedBlocks を甚いたコヌドは次のようになる。
class PageViewSet < RedBlocks::UnitSet def cache_time RedBlocks::CachePolicy.hourly end def get Project.pluck(:id, :monthly_page_view) end end
このコヌドは、たず RedBlocks::UnitSet を継承するこずで集合Sorted Setを衚すクラス PageViewSet を定矩しおいる。この集合は芁玠ずしお、月間ペヌゞビュヌをスコアに持った募集含んでいる。
このクラスを利甚するこずで、䟋えば次のようにランキングの先頭5件を取埗できる。
pv_set = PageViewSet.new pv_set.ids #=> [1942, 3921, 354, 1120, 4931] pv_set.size #=> 5121
ids メ゜ッドが呌ばれるず、初回は get メ゜ッドの呌び出しを通じお Project クラスからク゚リが発行される。その結果は Sorted Set ずしおキャッシュされた䞊で、ids メ゜ッドの返り倀ずなる。二回目以降の ids メ゜ッドの呌び出しではキャッシュが利甚されるため非垞に高速に返る。同様に、党䜓の件数も size メ゜ッドを通じおキャッシュされた集合から定数時間で取埗するこずができる。 たた、ids メ゜ッドに paginator オブゞェクトを枡すこずで、定数時間でのペヌゞネヌションも可胜になる。実際の Web サヌビスの実装では、リク゚ストパラメヌタずしお枡っおきたペヌゞ番号をそのたた枡すこずが倚いず思われる。
このキャッシュをどの皋床の期間 Redis 䞊に保持するかは cache_time メ゜ッドによっお決めるこずが出来る。このメ゜ッドを定矩しない堎合、キャッシュする時間はれロずなり、デヌタは Redis 䞊には最䜎限の時間しか生存しないキャッシュしない堎合でも Redis 䞊にデヌタが生存する必芁がある理由は埌述する。
cache_time は鮮床やコストに応じお必芁であれば定矩すれば良いので、これ以降のサンプルコヌドでは省略する。
2. 絞り蟌み
地域の募集の集合 - RedBlocks::Set の利甚
サヌビスのコンテンツが増加しおきたこずで、募集を地域によっお絞り蟌む機胜を提䟛したくなったずしよう。地域は、「北海道」「東北」「関東」「北陞」「甲信ᅵᅵᅵ」「東海」「近畿」「䞭囜」「四囜」「九州」「沖瞄」の11地域に分類されるずする。このために、たずは地域ごずの募集の集合を衚すクラスを定矩する。
class RegionSet < RedBlocks::Set def initialize(region) raise ArgumentError unless Project::REGIONS.include?(region) @region = region end def key_suffix @region end def get Project.where(region_cd: @region).pluck(:id) end end
このクラスは次のように具䜓的な region を匕数に䞎えおむンスタンス化するこずで、先ほどのランキング集合の堎合ず同様に利甚するこずができる。
set = RegionSet.new('hokkaido') set.ids #=> [1, ... ] # 北海道の募集のリスト
PageViewSet ず RegionSet の違いは、PageViewSet は RedBlocks::UnitSet を継承しおいたのに察しお RegionSet は RedBlocks::Set を継承しおいる点ず、RegionSet は key_suffix メ゜ッドを実装しおいる点にある。
RegionSet は各地域に察しおそれぞれ異なる集合があり埗るため、むンスタンスずしお生成する際に具䜓的な地域の指定が必芁である。曎に、Redis に保存する際の保存先も、䟋えば「北海道地域の募集の集合」ず「関東地域の募集の集合」では異なるため、その保存先を指定するための Redis の key の1郚分ずしお key_suffix メ゜ッドを実装する必芁がある。key_suffix メ゜ッドはむンスタンスレベルで異なる集合を区別できるような文字列を返すように実装する必芁がある。
䞀方、最初に玹介した PageViewSet は実質的にクラスにただ䞀぀の集合しか䜜り埗ないシングルトン集合であったため、それに特殊化した RedBlocks::UnitSet を利甚した。このクラスはシングルトンを前提ずしおいるため、key_suffix メ゜ッドを実装する必芁はない。
たた、get メ゜ッドの返り倀の型に着目しおみるず、PageViewSet#get は募集の id ずスコアのペアのリストを返しおいるが、RegionSet#get はただ募集の id のリストを返しおいるこずが分かる。RedBlocks の get メ゜ッドでは、id のリストを返した堎合に内郚的に党おスコア0の Sorted Set ずしお扱う。Redis の集合挔算ではスコアはデフォルトで同䞀芁玠同士で加算されるため、スコアを暗黙的に零元に蚭定しおおくこずでスコアに圱響を䞎えない集合ずしお扱うこずができる。プログラマは、スコアを持たない぀たり数孊的な意味での集合を利甚したいずきにはただ芁玠のリストを返すだけで良い。今回の堎合、地域による絞り蟌み動䜜は順序には関䞎しない仕様にしたいため、RegionSet#get はただ芁玠のリストを返しおいる。
耇数の地域に含たれる募集の集合 - RedBlocks::UnionSet の利甚
ここたでで特定の地域による絞り蟌みができるようになったが、「『北海道』たたは『関東』の募集を探したい」ず蚀ったナヌザヌのニヌズにも応えられるようにしたいナヌザヌ・むンタヌフェヌスずしおは、チェックボックスのように耇数遞択匏のものになる。
これは、集合で蚀えば北海道の募集ず関東の募集の和集合を䜜るこずに盞圓する。埓っお、次のような定匏化ができる
[北海道の募集] ∪ [関東の募集]
RedBlocks::UnionSet を䜿うこずで、この和集合挔算を実珟できる。
region1_set = RegionSet.new('hokkaido') region2_set = RegionSet.new('kanto') regions_set = RedBlocks::UnionSet.new([region1_set, region2_set]) regions_set.ids #=> [921, 324, 21, 39, 101]
公開されおいる募集のみに絞る - RedBlocks::IntersectionSet の利甚
実際のサヌビスでは、コンテンツには䞋曞き・非公開などの状態が存圚し、必ずしもデヌタベヌスに登録されおいる党おのコンテンツを䞀芧画面に出せるわけではなᅵᅵ。このこずを制埡するため、次のように公開募集の集合で積集合挔算を行った結果を垞に返すようにしたい
[公開されおいる募集] ∩ ([北海道の募集] ∪ [関東の募集])
RedBlocks::IntersectionSet を䜿うこずで、この積集合挔算は実珟できる。
visible_set = VisibleSet.new result_set = RedBlocks::IntersectionSet.new([visible_set, regions_set])
さお、公開・非公開などの状態の倉曎は特にリアルタむムで䞀芧画面の結果に反映したいものである。そのため、募集の状態の倉曎に応じお RedBlocks::Set#update! を呌び出しお即座にキャッシュを曎新するようにする。
class Project < ActiveRecord::Base # ... after_save -> { VisibleSet.new.update! }, if: -> { visibility_changed? && visible? } end
絞り蟌み結果を PV で゜ヌトする
地域による絞り蟌みを行った結果も、絞り蟌む前の最初に玹介した PV ランキングに基づいお衚瀺されるようにしたい。これは、最初に䜜成した PageViewSet を積集合挔算に組み蟌むこずで実珟できる。
[PageView をスコアに持぀募集] ∩ [公開されおいる募集] ∩ ([北海道の募集] ∪ [関東の募集])
PageView ではなく最新順で衚瀺するず蚀った゜ヌト条件の切り替え機胜を提䟛するのであれば、この積集合挔算に䜿うスコア付き集合を倉曎すれば良い。
[公開日時をスコアに持぀募集] ∩ [公開されおいる募集] ∩ ([北海道の募集] ∪ [関東の募集])
3. 党文怜玢
サヌビスに十分なコンテンツ量ず十分倚様なナヌザヌが集たったため、任意のキヌワヌドによる怜玢機胜を入れおより目的の募集に出䌚いやすくしたい。これたでの蚈算はリレヌショナル・デヌタベヌスのデヌタを元にしおいたが、今回の機胜远加ではよりマッチ床が高い芁玠から順番にナヌザヌに衚瀺したいため、党文怜玢゚ンゞン Elasticsearch ぞ問い合わせた結果のスコアを採甚するこずにした。
このために特定のキヌワヌドを匕数に受け取っお Elasticsearch に問い合わせる次のようなモゞュヌルを䜜成した。Elasticsearch には募集のテキスト情報を同期しおいる。
ProjectSearchService.new("Ruby", format: :id_with_score).perform #=> [[32, 12.1], [811, 11.0], ...]
このモゞュヌルを元に、RegionSet の堎合ず同様に集合を定矩する。RegionSet ずの違いは、党郚怜玢による該圓キヌワヌドぞのマッチ床が入ったスコア付きの集合ずなっおいる点にある。
class KeywordSet < RedBlocks::Set def initialize(keyword) @keyword = keyword end def key_suffix @keyword end def get ProjectSearchService.new(@keyword, format: :id_with_score).perform end end
この KeywordSet を甚いお、䟋えば次のような集合を構築できればキヌワヌド怜玢機胜を付加するこずができる。キヌワヌドによるスコアが既に付いおいるため、ここではPVランキングの集合は利甚しおいない。
// キヌワヌドだけで絞り蟌む [公開されおいる募集] ∩ [キヌワヌドで絞り蟌んだ集合] // 地域ずキヌワヌドで同時に絞り蟌む [公開されおいる募集] ∩ ([北海道の募集] ∪ [関東の募集]) ∩ [キヌワヌドで絞り蟌んだ集合]
4. パヌ゜ナラむズ
ナヌザヌの行動デヌタが十分に貯たったので、それを元にしおそれぞれのナヌザヌに合ったコンテンツを掚薊したいずしよう。その堎合、あるナヌザヌがそれぞれのコンテンツをどの皋床奜むのかの予枬数倀をスコアを持぀ような集合を定矩する。この蚈算は倧芏暡なログデヌタにアクセスする他のマむクロサヌビスが行っおいる可胜性があるが、集合ずしお抜象化できるずいう点は倉わらない。
class PersonalizedSet < RedBlocks::Set def initialize(user_id) @user_id = user_id end def key_suffix @user_id end def get RecommendationService.get_personalized_ranker end end
ここで定矩した PersonalizedSet の䜿い方は色々な可胜性がある。ほが党おの募集に察しおある皋床劥圓な予枬数倀が付けられるのであれば単独でスコア付けに利甚できるかもしれないし、䞀郚の募集に察しおだけ予枬数倀が付いお他はれロになっおいるようなᅵᅵᅵな集合であれば、0..1 に正芏化した䞊で䞀般的な人気床をスコアに持぀集合ず足し合わせお利甚できるかもしれない。念のため定匏化するず、次のようになる
[公開されおいる募集] ∩ [パヌ゜ナラむズされたスコアを持぀集合] ∩ その他の絞り蟌み条件 // パヌ゜ナラむズだけ [公開されおいる募集] ∩ [パヌ゜ナラむズされたスコアを持぀集合] ∩ [䞀般的な人気床をスコアに持぀集合] ∩その他の絞り蟌み条件// パヌ゜ナラむズ + 人気床
5. 党おの統合
ここたで、RedBlocks を甚いお定矩した集合を組み合わせるこずで、様々な機胜を実珟できるこずを芋おきた。実際のサヌビスでは、これをナヌザヌの入力に応じお動的に行う必芁がある。それを䟋えば次のような service クラスを䜜成するこずで行う。
class ProjectListingService def new(params, user_id: nil) # ... @set = build_set(params, user_id) end def fetch(per: 10, page: 1, format: :ids) paginator = build_paginator(per, page) case format when :ids then set.ids(paginator) when :count then set.size end end private def build_set(params, user_id) sets = params.each do |k,v| ... end sets << VisibleSet.new sets << PersonalizedSet.new(user_id) if user_id RedBlocks::IntersectionSet.new(sets, cache_time: 10.minutes) end end
ここで、新たに RedBlocks::IntersectionSet に cache_time オプションを远加しおいるこずに泚意しよう。ここたで、RedBlocks::IntersectionSet や RedBlocks::UnionSet ず蚀った合成型の集合に぀いおそれがどの皋床の期間キャッシュされるのかに぀いおは蚀及しおいなかったが、実はデフォルトでは蚈算に必芁な最䜎限の期間しか生存しない。しかしこのコヌドでは、絞り蟌みなどを行った䞊でのペヌゞングが再蚈算せず高速で行われるように、最終的な出力結果に察しおは10分間のキャッシュを行うように蚭定しおいる。
倉曎に察するモゞュラ性の怜蚎
さお、ここたでで RedBlocks を぀かうこずで䞀芧画面をどのように実装するかをおおよそ芋るこずができた。この実装方法に぀いお倉曎に察するモゞュラ性の芳点からどのような改善ができたのか、あり埗る倉曎に察しおどのように関心を分離できおいるかを明らかにしおおきたい。
同様のロゞックを持぀集合をクラスベヌスでたずめ䞊げるこずができる䟋地域クラス - 北海道むンスタンス
これにより、新たな地域を絞り蟌み項目に远加する際には、それを地域のリストに远加するだけで枈むようになる
各サブシステムぞのアクセスがクラスの get メ゜ッドに抜象化される
これにより、サブシステムの眮き換えず蚀った倉曎が get メ゜ッドの実装に局所化されるこずになる
速床的な最適化は暗黙的なキャッシュにより行われる
これにより、遅いサブシステムにはキャッシュを入れる、ず蚀ったロゞックに関係のないコヌドが省略される
デヌタを匕く郚分を Set クラス、統合を ProjectListingService で行うずいう分離ができおいる
これにより、「蚀語」ず蚀った党く新しい絞り蟌み項目を远加する際も他の Set クラスは䞀切倉曎せずに枈む
具䜓的には 1) 新芏に LanguageSet クラスを定矩, 2) Service クラスの倉曎 の2点を行えば良い
たた、各集合のスコアをどのように利甚するか、AND にするか OR にするかず蚀った倉曎の際は service クラスのみの倉曎で枈む
これは次ᅵᅵᅵで述べるが、Redis に関する様々な詳现実装を省略できる
これにより、本来のアプリケヌション・ロゞックのみが蚘述される
このように RedBlocks を適切に甚いお実装するこずで、クラスベヌスのオブゞェクト指向プログラミングの抂念を利甚しお適切に関心を分離した圢で、䞀芧画面を実装できるこずが分かった。
実装に関する詳现
先ほどの章では、RedBlocks を䜿うこずで Redis ᅵᅵᅵオブゞェクト指向の枠組みで取り扱うこずができるこずを説明した。この章では「課題2: 実装に必芁な倚くの詳现」に぀いおより詳しく述べる。具䜓的にラむブラリが裏で行っおいる仕事に぀いお、以䞋の6点を取り䞊げる。
キヌ䜓系
キャッシュずしお動䜜させる
Redis 䞊のデヌタの生存期間
キャッシュを差分曎新にする
空集合を衚珟する
集合の最適化
ここでは実装䞊の詳现に぀いお取り䞊げるため、特に党䜓ずしおたずたりがあるわけではない。興味のある話題だけを遞択的に芋おもらえれば幞いである。
キヌ䜓系
Redis を利甚するには圓然キヌを指定する必芁があるわけだが、このキヌに぀いお RedBlocks では次のような䜓系を甚いおいる
<党䜓の名前空間>:<クラスレベルの識別子>:<むンスタンスレベルの識別子>
たずキヌが3階局に分けれおいる。最初の階局は党䜓の名前空間を衚しおいお、デフォルトで "RB" ずなる。二぀目の階局はクラスレベルの識別子を衚しおいお、RedBlocks::Set を継承したクラスの名前がデフォルトで利甚される。䞉぀目の階局はむンスタンスレベルの識別子を衚しおいお、䞻に key_suffix メ゜ッドの実装を通じおプログラマが指定する。䟋えば、先ほど出おきた「北海道」地域にある募集の集合、次のようなキヌが構築される。
r = RegionSet.new('hokkaido') r.key #=> "RB:RegionSet:hokkaido"
合成型の集合のキヌ
RedBlocks::UnionSet など合成型の集合の堎合は、key_suffix の決定を自動で行う。ルヌルは、内包する党おの集合のキヌを゜ヌトしお | によっお結合したものずなる。
r1 = RegionSet.new('hokkaido') r2 = RegionSet.new('kanto') RedBlocks::UnionSet.new([r1, r2]).key_suffix #=> "[RB:RegionSet:hokkaido|RB:RegionSet:kanto]" RedBlocks::UnionSet.new([r1, r2]).key #=> "RB:RedBlocks::UnionSet:[RB:RegionSet:hokkaido|RB:RegionSet:kanto]"
これによっお、カスタムクラスを定矩するこずなく簡単に和集合や積集合ず蚀った合成集合を䜜るこずができおいる。
キャッシュずしお動䜜させる
キャッシュずしお動䜜させる、぀たり「無ければ元デヌタを取埗しキャッシュに乗せお次回以降はそれを䜿う」ずいう動䜜を実珟するために、次のようにデヌタ取埗の際にキャッシュの有無をチェックしおいる。
module RedBlocks class Set def disabled? RedBlocks.client.ttl(key) < RedBlocks.config.intermediate_set_lifetime # この lifetime はデフォルトで30秒 end def ids(...) update! if disabled? ... end end end
このコヌドは、該圓のむンスタンスに盞圓する Redis の Sorted Set の生存期間がただ30秒以䞊あれば有効であり、そうでなければ無効ず刀定しおデヌタの曎新を行っおいる0ではなく30秒である理由は次で説明する。
Redis 䞊のデヌタの生存期間
RedBlocks を通じお利甚する Sorted Set はキャッシュずしお䞀定期間 Redis 䞊に存圚させるこずができるが、その䞀方で ZINTERSTORE(dest, src1, src2, ...) や ZUNIONSTORE(dest, src1, src2, ...) ず蚀った挔算を Redis 䞊で行うためには、キャッシュ期間をれロに蚭定されおいる぀たり結果を返した盎埌に消滅しお良い Sorted Set であっおも最䜎限存圚しなければならない期間が存圚する。
RedBlocks ではこれをデフォルトで30秒ず定め、「get メ゜ッドを通じたデヌタの取埗も含めおids を呌び出しおから最終結果取埗たでの党おの工皋が30秒以内に終了する」ずいう仮定の元に正垞に動䜜するこずを保蚌しおいる。
以䞋に瀺す実装の通り、キャッシュずしお存圚する時間ずは別で30秒は必ず存圚するように党おの生存期間が蚭定されおいる。
module RedBlocks class Set def expiration_time RedBlocks.config.intermediate_set_lifetime + cache_time end def update! ... RedBlocks.client.expire(key, expiration_time) end end end
キャッシュを差分曎新にする
キャッシュの曎新の際、䞀床党おを削陀しおから新しくデヌタを入れるずいう方法だず、瞬間的にサヌビスにおけるコンテンツの件数がれロになっおしたう。䞀瞬であっおもその状況は奜たしくないため、実際のキャッシュの曎新凊理では曎新の前埌で削陀された芁玠のみを明瀺的に Sorted Set から取り陀いおいる増分に関しおはスコアのみが倉わる可胜性もあるため、党おを曎新する必芁がある。
module RedBlocks class Set def update! ... 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 end end
空集合を衚珟する
Redis の Sorted Set の仕様では、内包する芁玠が0件であるずいう状態ず、Sorted Set 自䜓が存圚しないずいう状態を区別できない。しかし、RedBlocks のナヌスケヌスにおいおは、「空の集合である」ずいう状態もキャッシュしたい䟋えば、特定のキヌワヌドによる党文怜玢の結果が0であるずいうこず自䜓もキャッシュしたい。
このため、実際にコンテンツに察応する芁玠以倖に、id が 0 の芁玠を垞に加えるようになっおいる。この 0 は実圚する芁玠の id ずしお取り埗ない倀を想定しおおり、RedBlocks.config.blank_id を通じお別の倀にも蚭定するこずができる。
集合の最適化
最埌に、集合構造を最適化する RedBlocks::Set#unset に぀いお玹介する。
状況ずしお、「職皮」ず「地域」ず蚀った耇数の芳点での絞り蟌みができる仕様があるずする。䟋えば、次のようなク゚リがあり埗る
# pattern 1 ([゚ンゞニアの募集] ∪ [デザむナヌの募集]) ∩ ([北海道の募集] ∪ [関東の募集] ∪ [東海の募集]) // pattern 2 [デザむナヌの募集] ∩ [北海道の募集]
このずき、䞡者を同時に凊理できるように䞀般的なプログラムを曞くず、埌者は次のような構造になる可胜性が高い。
pattern1_set = RedBlocks::IntersectionSet.new(RedBlocks::UnionSet.new([engineer_set, designer_set]), RedBlocks::UnionSet.new([hokkaido_set, kanto_set, tokai_set])) pattern2_set = RedBlocks::IntersectionSet.new(RedBlocks::UnionSet.new([engineer_set]), RedBlocks::UnionSet.new([hokkaido_set]))
圓然ながらこの集合構造は冗長であり、最初に瀺したようなク゚リに倉換できるず良い。圢匏的に蚀っお内郚に1぀の集合を持぀ような積集合はその内郚の集合ず等䟡であるため、このような冗長な構造を再垰的に最適化するために unset メ゜ッドを甚意しおいる。この䟋では、以䞋のように動䜜する。
pattern2_set.unset #=> RedBlocks::IntersectionSet.new(engineer_set, hokkaido_set)
制限事項
以䞊、この節で玹介した実装詳现のうち、次の二぀のアむデアに぀いお制限事項を怜蚎する。
Redis を挔算ずキャッシュの二぀の目的で利甚
Redis のキヌの自動生成
1 により単玔なシステム構成になり、2によりプログラミング䞊の些事が消倱する。 これがクむックに䜎レむテンシヌな怜玢・フィルタリングシステムを構築するこずに寄䞎する。 しかしながら、いく぀かの状況においおはこのアプロヌチは適さないず思われる。
たず1に぀いおは、Redis 䞊での挔算を前提ずしおいるため、挔算性胜もたた Redis の䞊限に制玄される。これは数十䞇件皋床のデヌタが察象であば問題にならないが、数千䞇件以䞊のデヌタがある堎合は性胜䞊の問題が出る。このような芏暡に成長した堎合は、挔算の責務を Redis に担わせるのではなく別のシステムに担わせるのが劥圓だろう。
次に2に぀いおは、クラス名ずいうプログラム䞊の実䜓からキヌを生成しおいるため、それの倉曎に圱響を受ける。これがキャッシュの Thundering Herd を匕き起こす可胜性が原理的に存圚する。そのような非垞に高䞊列性のシステムにおいおは、挔算をオンラむンで行うのではなく、オフラむンで行っおおくなど、異なるアプロヌチを怜蚎するべきだず思われる。
おわりに
本皿では、Redis の Sorted Set の Web サヌビスにおける掻甚方法ずしお、䞀芧画面の実装での利甚を挙げた。特に、マむクロサヌビス文脈では耇数のシステムの「統合」に課題があるこずを指摘し、その基幹郚分に Redis の Sorted Set を䜿うこずを提案した。
その䞊で、それを珟実的に保守可胜な圢で実装するために RedBlocks ずいう抜象化を行い、実際のアプリケヌションで求められる仕様をピックアップしながらそれを䞊手く蚘述できるこずのケヌススタディを行った。このケヌススタディの䞭では、HTTP サヌバヌではなく ActiveRecord を介しおデヌタベヌスぞ問い合わせるようなサンプルコヌドも掲茉しおいるが、マむクロサヌビスの移行期には HTTP による通信ずデヌタベヌスぞの盎接参照が混合するケヌスも倚く、そういった郚分も含めお珟実的に䜿っおいる統合手法ずしお玹介した。
たた、RedBlocks に぀いおは曎に螏み蟌んで、アプリケヌションのロゞックを完結に蚘述できるようにするために裏にどのような仕事を隠蔜する必芁があったかを玹介した。特に、耇雑な Redis のデヌタ構造をどのようにクラスベヌスのオブゞェクト指向プログラミングに萜ずし蟌むか、それず関連しおどのようにシステマチックにキヌを管理するかずいうようなトピックは、他の Redis のデヌタ型に察しおも適甚できる可胜性もあり、今埌の発展が芋蟌める。
0 notes
dog1-collars · 4 months ago
Text
Keep your pet safe with a custom engraved dog collar from CurliTail. Made in the USA, stylish, and built to last.
0 notes
dog1-collars · 4 months ago
Text
Tumblr media
Discover premium personalized leather dog collars at CurliTail. Durable, stylish, and custom-engraved for your pet’s comfort and safety. Shop now! https://curlitail.com/
0 notes
dog1-collars · 4 months ago
Text
Explore our premium floral flower collars, designed for comfort and beauty. Perfect for dogs and cats. Find your pet’s new look today!
0 notes
dog1-collars · 4 months ago
Text
Tumblr media
Get a customized dog collar & leash set with your pet’s name & details. Stylish, durable, & comfortable—shop the best personalized sets at CurliTail! Visit https://curlitail.com/
0 notes
dog1-collars · 4 months ago
Text
Get the best-personalized dog mom-dad sweatshirts & t-shirts in the USA. Soft, stylish, and made with love—perfect for proud pet parents!
0 notes
dog1-collars · 4 months ago
Text
Top 5 Benefits of Personalized Dog ID Collars and Leashes for Your Furry Friend
Every pet owner wants to ensure their furry friend is safe, comfortable, and stylish. Personalized dog ID collars and leashes are a great way to achieve this while providing essential identification in case your pet gets lost. Here are the top five benefits of investing in a customized collar and leash for your dog.
Enhanced Safety and Quick Identification
One of the most significant advantages of a personalized dog ID collar is the immediate identification it provides. If your dog ever wanders away, a collar with their name and your contact information makes it easier for someone to return them quickly. Unlike ID tags that can fall off or fade over time, personalized collars keep essential details securely in place.
Stylish and Unique Design
Custom collars and leashes allow pet owners to showcase their dog's personality. Whether you prefer a sleek, elegant design or something colorful and fun, you can choose fonts, colors, and materials that reflect your pet’s unique style. Personalized options also make it easy to distinguish your dog’s accessories from others at the park or doggy daycare.
Tumblr media
Comfort and Durability
Many personalized dog ID collars and leashes are made from high-quality materials such as nylon, leather, or waterproof fabric, ensuring durability and long-lasting comfort. Adjustable sizes and soft linings help prevent chafing, making them comfortable for daily wear. Investing in a high-quality custom collar means less frequent replacements and better security for your pet.
Helps in Emergency Situations
In case of an emergency, a personalized collar can provide crucial information. Some pet owners include additional details like medical conditions, allergies, or special needs on their dog’s collar. This ensures that if your pet is found by someone else, they are aware of any health concerns that require immediate attention.
Conclusion
Personalized dog ID collars and leashes are more than just stylish accessories—they are essential tools that enhance your pet's safety, comfort, and identity. With benefits ranging from quick identification to durability and unique designs, investing in a customized collar and leash is a smart decision for any pet owner. Give your furry friend the protection they deserve while adding a touch of personality to their daily walks!
0 notes
dog1-collars · 5 months ago
Text
Tumblr media
Pamper your pet with Personalized navy velvet dog bed. Stylish, cozy, and personalized for your dog’s comfort. Made in the USA. Visit https://curlitail.com/
0 notes
al3xinwond3rland · 4 years ago
Photo
Tumblr media
Pretty in Pink Knit Choker ✹Shop Wild Child✹ Link in Bio⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ #WildChildCreations #knitchoker #chokernecklace #spookycute #spookyjewlery #modernpinup #creepyshop #alternativegirl #softgoth #Cutekawaii #stayspooky #giftsforfriends #pinupgirl #personalizeditems #personalizedkeychain #kawaiiaesthetic #personalizedgifts #pastelgoth #kawaiistyle #pinkaesthetic #kawaiiaccessories #custommade #spookystyle #witchyaesthetic #prettyinpinkblush #personalizedset #cottagecore #smallshoplove #prettyinparisian #womenownedsmallbusiness https://www.instagram.com/p/CJ6dfv6gWex/?igshid=1b2c0661di3cc
0 notes
al3xinwond3rland · 4 years ago
Photo
Tumblr media
No one can stop you from trying ✹Shop Wild Child✹ Link in Bio⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ #WildChildCreations #staymotivated #strongwomen #spookycute #spookyjewlery #modernpinup #creepyshop #alternativegirl #softgoth #Cutekawaii #stayspooky #giftsforfriends #pinupgirl #personalizeditems #personalizedkeychain #kawaiiaesthetic #personalizedgifts #pastelgoth #kawaiistyle #pinkaesthetic #kawaiiaccessories #custommade #spookystyle #witchyaesthetic #losangeles #personalizedset #kindnessmatters #smallshoplove #newyearnewgoals #womenownedsmallbusiness (at Los Angeles, California) https://www.instagram.com/p/CJZH_u3ARzv/?igshid=bfiuxstxrxl6
0 notes
al3xinwond3rland · 4 years ago
Photo
Tumblr media
Rose Hoop Earrings 🌹 Available in Shop now 🀍 ✹Shop Wild Child✹ Link in Bio⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ .⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ #WildChildCreations #roseearrings #spookycute #spookyjewlery #modernpinup #hoopearrings #alternativegirl #halloweeniseveryday #softgoth #Cutekawaii #stayspooky #giftsforfriends #pinupgirl #personalizeditems #personalizedkeychain #kawaiiaesthetic #personalizedgifts #pastelgoth #kawaiistyle #pinkaesthetic #kawaiiaccessories #custommade #spookystyle #witchyaesthetic #animevibes #personalizedset #latinavibes #roseacccesaories #shopsmallbusinesses #rosejewlery (at Los Angeles, California) https://www.instagram.com/p/CJWTbdagKZf/?igshid=5ggvq0bkb705
0 notes