こんにちは。サービスエンジニアリング本部の寺田と橋野です。 RubyKaigi 2023にenigmoから2名、現地の参加をしました。 今年のRubyKaigi 2023は2023年5月11日〜5月13日に長野県 松本市 の まつもと市民芸術館 で開催されました。 去年と大きく違うところは、公式パー ティー やスポンサー企業によるドリンクアップの企画があったところです。 去年より多くの Rubyist との交流ができるようになりました! 本ブログは、前編と後編に分けてお届けします。 1日目 今年は夜に Official Partyが Hotel Buena Vista で開催されました。 たくさんのドリンクやフードが用意されており、立食形式でおこなわれ、自由に参加者と交流することができました。 参加者の中には知り合いの知り合いに出会えたりして、エンジニアの輪はつながっていることを実感することができました。 Official Party後には、Findyさんによるドリンクアップの企画がありました。 そこでは、去年RubyKaigiで知り合った方達と再開することができ、楽しい時間を過ごすことができました。 また、お店も ドライフラワー がたくさん飾ってあってとてもおしゃれでした! 2日目 2日目にはスタンプラリーがおこなわれていました。 対象の企業ブースを巡り、スタンプを全て集めるとピンバッチをもらえます! ピンバッチは複数種類があり、どれも魅力的でした。 シールだったりスタンプだったり✨ 夜には、スポンサー企業さんがドリンクアップの企画が複数ありました。 橋野はライザップさんのドリンクアップに参加させていただき、馬肉を食べながら、 Rubyist と交流しました。 参加者の中にMatzさんもいて、色々とお話を聞くことができました。 3日目 RubyKaigi終了後には、アフターパー ティー が開催されました。 また、夜にはRubyMusicMixinも開催されていました。 (私たちは不参加だったため、写真や感想はありません!!😭) 今年は色々な企画やイベントがあり、たくさんの Rubyist と交流することができました。 観光 観光名所へ行ったり等はなかったのですが、名物であるそばを食べました! 受付時に貰える3000円分のバウチャーチケットがあるのでそちらを使用しました。 駅周りにはたくさんの飲食店があり、ご飯に困ることはありませんでした。 珈琲屋さんや喫 茶店 などの魅力的なお店がたくさんありました。 しゃぶしゃぶも食べました 感想 私にとっては初めての RubyKaigi でした。技術カンファレンスとして多くの最先端の研究に触れられたことはもちろんのこと、何より Ruby コミュニティのことが大好きになれた3日間だったなあと思います。パー ティー では普段からお世話になっている Ruby や Gem のコミッターと出会い、貴重なお話しを聞くことができました。さらにここで出会ったコミッターの方とその後も一緒に オープンソース のプロジェクトに参加させてもらえるようになったりと、自身と Ruby との関わりを一気に近づけてくれました。スポンサーブースではさまざまな企業の方々とお話しをして、同じく Ruby を使って Web アプリケーションを作る仲間としてさまざまな苦悩を共有したり、これはいいなというア イデア を得たりと多くの学びがありました。名刺も交換させていただき、仕事の面でのつながりも作れました。(寺田) 去年参加したRubyKaigi 2022での反省をいかして、気になる発表の情報を事前に調べるようにしたり、事前イベントに参加したりしました。 その結果、去年より話の内容がわかるところが増えたので、用意をしてから参加をしてよかったです! 今年も同世代のエンジニアの方との交流ができたり、また、女性エンジニアの方と知り合うことができました。同じ悩みを共有したり、キャリアについて色々教えていただいたりして技術以外のことも新たな発見をすることができました。 3日間、発表を聞いたり、コミッターさんたちの話を聞くにつれて、 Ruby のことをもっと知っていきたいという新しい気持ちが芽生えました。 Ruby のしくみを購入したので読み進めたいと思います。 長野県には初めて訪れたのですが、とてもいい場所だったので、次は観光しに行きたいです!(橋野) 後編は印象に残ったセッションの紹介をしていきます! お楽しみに! 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは。 株式会社 エニグモ 新卒 2 年目 エンジニアの橋野です。 先月開催された、 AWS Summit Tokyo 2023 に行ってきました。 今年の AWS Summitはハイブリット開催で、オンライン、オフライン共に参加できるようになっていました。 会場での開催は、2019年以来の4年ぶりということです! 私は、現地で1日目のみ参加させていただきました!会場は、千葉県の 幕張メッセ です。 AWS については初心者ですが、初心者でも楽しめるということで行ってみました! サミットでの過ごし方 時間 行程 10:00~ 受付 朝昼兼用ごはん 11:00~ スポンサーブース 12:00~ これから始める AWS クラウド 、最初の一歩は AWS Cloud Essentials 13:00~ AWSome Day ~踏み出そう、 AWS への最初の一歩~ 16:00~ ニンテンドー アカウント リノベーションプロジェクト 17:00~ AWS AI サービスを使ってあなたのシステムにも 機械学習 を導入しよう! 幕張メッセ の会場について、すぐに受付を行いました。事前に受講票を印刷していたので、スムーズに会場内に入ることができました。 スポンサーブースでは、企業から ノベルティ をもらうと受講票をスキャンするという仕組みは新しくて面白かったです。 また、 AWS 社員から直接話を聞けたり、スポンサーの導入事例やスポンサーのサービスを詳しく聴くこともできました。 午後からは予約していたセッションに参加しました。 わたしは業務で AWS を担当していないので、初心者向けのセッションに参加しました。 私が参加したセッションはほとんどがサイレントセッションでした。発表者のマイクの音を手元のレシーバのチャンネルを設定することによって、聴くことができます。新しい!! この取り組みは、没入感があって受講者としては非常に体験が良かったです。ただ、座席が取れないと立ち見できないので、早めにお席を確保しておきましょう! 今年は、事前にセッション予約をしていても、5分前くらいまでに入場しておかないと、予約していない方でも入場することができるようになるようでした。(私が見た限りでは) ちなみに、椅子はパイプ椅子なので長時間のセッションを受講するとお尻が痛くなるので、 ノベルティ のクッションがあってよかったです。 印象に残ったセッションの感想 AWS Cloud EssentialsとAWSome Day AWS Cloud EssentialsとAWSome Dayは、 AWS クラウド をこれから利用する方にとって非常に役立つプログラムでした。 この2つのプログラムを受講すれば、 AWS に多様なサービスについて、どのようなことが実現できるのかということを理解することができるようになっています。 AWS Cloud Essentialsは、 AWS の基本的なサービスの紹介でした。具体的には、「リージョンとAZ」「EC2」「RDS」「 VPC 」「責任共有モデル」について理解することができます。 話のテンポがゆっくりで聞き取りやすく、集中して受講できるようなセッションでした。 AWSome Dayの方は、 AWS Cloud Essentialsよりもより、多様な AWS の主要なサービスについて、理解することができるプログラムです。 AWS Cloud Essentialsの内容に加えて、「IoTサービス」「 機械学習 」「 ブロックチェーン 」などについての説明を受けることができました。聞いたことがないサービスなどもたくさんあったので、ワクワクしながら受講することができました。 講演後には、 AWS のエキスパートの方と直接話すことができるので、質問や疑問点を解消することができます。現地参加ならではの魅力です! 以上のように、 AWS Cloud EssentialsとAWSome Dayを受講することで、 AWS の主要なサービスについて知ることができました! この2つを受講することによって、より理解が進むことができました。 たとえば、ストレージでは、S3やEFS、EBSという3つのサービスが紹介されていました。私はファイルの管理にはS3を使っていますが、他の2つのサービスについては知りませんでした。 S3は非常に便利ですが、ファイルを直接マウントしたい場合や、より高速な スループット が求められるワークロードでは、EBSやEFSの利用も検討できると思いました。 リレーショナルデータベースでは、 Amazon RDSと、 Amazon Aurora というサービスが紹介されていました。私はアプリケーション開発をしているので、 SQL クエリを通じてデータベースとのやり取りをしますが、そのインフラが AWS やオンプレミスのサーバー上でどのように動作しているのかについてはあまり考えたことがありませんでした。 この講演を聞き、 Amazon Aurora というデータベースを使うことで、高い障害耐性やデータ耐久性を提供していると知りました。 Auroraを利用することでDBの運用が楽になると思いました。 これから AWS を学びたいという方は、来年のSummitで、 AWS をより深く理解するための第一歩として受講することをおすすめします! ニンテンドー アカウン トリノ ベーションプロジェクト 次に受講したセッションは、「 ニンテンドー アカウン トリノ ベーションプロジェクト」という 任天堂 株式会社と株式会社 ディー・エヌ・エー のセッションです。 このセッションでは、 ニンテンドー アカウントという Nintendo Switch などでゲームをする際に利用するユーザーアカウントシステムにおけるリノベーション案件をどう進めたかのセッションでした。 元々はEC2 + Perl で構成されたシステムで、そのリノベーションを実施する理由としては、いくつか挙げられていましたが、さらなる利用者の増加に伴って、現状の技術スタックでのサービスレベルの維持が困難と判断したことと集約できそうでした。 リノベーションは、アプリケーションを全面的に Perl から Java に書き換え、インフラをコンテナに置き換えていき、 アーキテクチャ をマイクロサービスにしていくという内容です。 多くの企業が採用しているモダンな アーキテクチャ や言語の採用というような一般的な内容に見えます。 実際に移行を進める上で、莫大な Perl のコードを全て Java に書き換えるのはかなりの労力です。 そこで、 ニンテンドー では、一時的に人員を増加させるためのリノベーションチームを発足しました。ここが、私がこの登壇で一番興味深いと思った点です。 このチームはリノベーションが完了された段階で、解体されることを目標に作られたチームで、リノベーションプロジェクトを推進する責務を担っています。 サービスレベルについての責務を持っているチームと独立したチームを作ることによって、保守的にならずプロジェクトを進めることができるという側面があると思いました。 もし、同じチームにしてしまったら、目先のサービスレベルの方が重要になるため、なかなか進まなかったのではないかと思います。 普段使っているサービスのシステムについて知ることができて大変興味深かったです。 参加を通して AWS クラウド について初めて学ぶことができ、非常に勉強になりました。 AWS の基礎知識や主要なサービスについての説明や、それらを活用するメリットや具体的な活用例など、わかりやすく解説していただき、初心者でもとても楽しめました! AWS クラウド の無料枠の紹介があったので、個人の開発でも利用してみようと思いました。 セッション登録の際にレベルが記載されているので、自分に合ったレベルのセッションを登録することで、楽しめると思います! また、企業ブースでは、たくさんの展示や AWS の事例紹介があるので、余裕のあるスケジュールを組むとより楽しめそうです。 エニグモ でも AWS を利用しています! 株式会社 エニグモ すべての求人一覧 hrmos.co
エンジニアの竹田です。 BUYMA の検索システムやMLOps基盤の開発・運用を担当しております。 今回はSolr Operatorによる検索システム構築を行いましたので、その実施内容と得られた知見についてご紹介したいと思います。 はじめに 昨期から今期にかけて、オンプレミスのシステムからの脱却、およびマイクロサービス化を目指し、商品検索システムのリプレイスを進めていました。 エニグモ では機能毎に Apache Solrを用いた複数の検索システムを保持しており、 クラウド 移行に伴い、構築面や運用面の負担は大幅に軽減できております。 なお、リプレイスを行った商品検索システムの構成も下記の記事と大きくは変わっていません。 tech.enigmo.co.jp 今回フォーカスする検索システムの課題 検索システムの運用には、開発案件や障害対応、システムのバージョンアップやシステム増強作業などがあります。 中でも開発案件は、本番と同等のデータを利用したシステムにて検索の並び順や検索ヒット内容の検証が必要となる場合があります。 今まではオンプレミス環境にそのシステムを構築していましたが、今回の商品検索の クラウド 移行に合わせ、同環境を クラウド 上に構築することになりました。 システムのライフサイクルが短いため、より簡素に構築・廃棄を行えるようにしたいという課題があり、そこで案として出たのがSolr Operatorの利用です。 結果次第ではサービス運用でも利用できる可能性も考慮してSolr Operatorを利用した構築の検証を行いました。 なお、本記事ではある程度 Kubernetes や Apache Solrのことをご存知の方を対象としている点をご容赦ください。 Solr Operatorについて Welcome - Apache Solr Operator Solr Operatorは Kubernetes のCRD(Custom Resource Definition)として提供されているもので、SolrCloudやZookeeperClusterといったkindによりSolrシステムを一元管理するイメージという理解で良いかと思います。 2023/04/24にv0.7.0がリリースされています。 Solr Operatorの概要や簡素な構築方法については、 Google CloudのShimojo様が非常に分かりやすいブログ記事を公開されていますので是非ご参考にしてみてください。 Solr Operator を利用して SolrCloud クラスタ を GKE Autopilot に構築する (前編) zenn.dev Solr Operator を利用して SolrCloud クラスタ を GKE Autopilot に構築する (後編) zenn.dev 構築時の簡単な構成は、以下のようになっています。 Zookeeper Operatorについては特に触る必要がなかったため、本記事では触れていません。 構成図 Solr Operator CRDの各リソース項目について Solr OperatorはCustom Resource Definition(CRD)として提供されており、項目に合わせて定義を埋めていく形になります。 構成管理を考えた場合、 helm install でSolrCloud クラスタ を構築する際に適宜パラメータとして指定するよりも、 Kubernetes マニフェスト として管理するのが望ましいと思われます。 ※ helm install ではなく、 マニフェスト を作成して kubectl apply -f <作成したマニフェストのyamlファイル> で構築する方式 以下に、 kind: SolrCloud において利用頻度が高いと見込まれるパラメータを列挙してみました。 spec配下の設定項目 内容 備考 solrImage 利用するsolrのコンテナイメージを指定 独自ビルドしたイメージも指定可能 solrOpts solr起動時のパラメータを指定 solrJavaMem java のヒープサイズを指定 solrAddressability solrの解放ポートや外部接続定義を指定 solrGCTune GarbageColleciton用のチューニングパラメータを指定 customSolrKubeOptions solrのカスタム項目を指定 (※1) updateStrategy solrの更新方式をを指定 未指定時のデフォルトがrollingUpdateのため注意 dataStorage solrのデータ格納先ストレージ persistentにして永続ディスクを利用 replicas solr podのレプリカ数 (※1) 以下、customSolrKubeOptions配下の項目 spec.customSolrKubeOptions配下の設定項目 内容 備考 ingressOptions 外部に ingress を利用している場合に利用 annotationsでBackendConfigを指定するなどで利用 configMapOptions providedConfigMapにカスタムConfigMapを指定 solr.xml や log4j2.xml を定義できる podOptions solr podに対するオプション項目 (※2) (※2) 以下、podOptions配下の項目 spec.customSolrKubeOptions.podOptions配下の設定項目 内容 備考 resources CPUやメモリのlimits/requestsを設定 livenessProbe Solrが動作しているかどうか 指定しないとhealthcheckが通らず、podが起動しない readinessProbe Solrが トラフィック を受けられるかどうか 指定しないとhealthcheckが通らず、podが起動しない initContainers Solr PodのinitContainersを定義できる sidecarContainers Solr Podに設置する サイドカー コンテナを定義できる あくまでサンプルですが、以下のような マニフェスト になるかと思います。 apiVersion : solr.apache.org/v1beta1 kind : SolrCloud metadata : name : example namespace : solr spec : replicas : 3 solrImage : tag : 9.2.1 pullPolicy : IfNotPresent solrGCTune : -XX:NewRatio=3 -XX:SurvivorRatio=4 solrJavaMem : -Xms2048M -Xmx2048M solrAddressability : commonServicePort : 8983 updateStrategy : method : StatefulSet dataStorage : persistent : pvcTemplate : spec : resources : requests : storage : 100Gi reclaimPolicy : Retain customSolrKubeOptions : configMapOptions : providedConfigMap : solr-config-map # configMapは先に作成・適用しておく必要がある ingressOptions : annotations : cloud.google.com/backend-config : '{"ports": {"8983":"solrcloud-backend-config"}}' cloud.google.com/neg : '{"ingress": true}' podOptions : resources : limits : cpu : 2 memory : 6Gi requests : cpu : 2 memory : 6Gi livenessProbe : initialDelaySeconds : 30 periodSeconds : 10 httpGet : scheme : HTTP path : /solr/admin/info/health port : 8983 readinessProbe : initialDelaySeconds : 15 periodSeconds : 5 httpGet : scheme : HTTP path : /solr/admin/info/health port : 8983 補足となりますが、Solrが起動しない場合は、概ね以下の方法で原因を特定できます。 Solr Podを kubectl describe で確認 kubectl describe pod example-solrcloud-0 -n solr solr-operator Podを kubectl logs で確認 kubectl logs solr-operator-xxxxxxxxxx-xxxx -n solr マニフェスト 適用後は、solr スキーマ 定義やsolrconfig. xml の配置、コレクションの作成と進めて検索できる状態にします。 こちらの作業についての手順は割愛します。 Solr起動後の管理画面等への接続については、上記で図示した通り ingress 経由としました。 実際に構築してみた所感 まだ検証段階ではありますが、以下の恩恵を得られるものと思います。 Zookeeperを特に意識しなくて良い ディレクト リ構成も基本的には意識しなくて良い SolrCloudを構築する上でのSolrの学習コストが下がる マニフェスト さえ用意しておけばSolrCloudシステムの作成、削除がkubectlコマンド一発で完遂する CRDの項目が充実しており、かなり細かい点まで定義可能 苦労した点としては以下になります。 マニファストの設定誤りや漏れがあると結構ハマる 特にヘルスチェック、リソース定義周りの定義誤りは何が問題なのか分かり辛い CRDはかなり長大な マニフェスト のため読み解くのが大変 Yamlの参考リンク 日本語での参考文献がほとんどない 運用利用に当たっては以下の項目を意識・検討する必要があることも分かりました。 Solr Operatorで構築できるのはSolrのインフラ面のみ Solrの スキーマ 定義や構成ファイルの配置は configsets API や zkCliコマンド を利用する必要がある アクセス周りのセキュリティを気にしておく必要がある 監視関連の定義は別途検討の必要がある エニグモ では検索システムの監視にDatadogを利用しているため、対応方法を調査・検討する必要あり Solr Prometheus Exporterを利用する方法もある 用途の異なる検索システムを1つのSolrCloud kindに集約しない方が良いかもしれない Solr Podの名称がprefix固定の連番suffix(例: xxx-solrcloud-1 、 xxx-solrcloud-2 )での管理となるため、Pod名称から用途が判別し辛い 実サービスでの利用はAutopilot クラスタ よりStandard クラスタ の方が良いかもしれない オートスケールに時間を要するため、ある程度リソースが確保された状態でないと運用は難しそう Solr Operator自体のバージョンアップへの追従 また、合わせてSolr構成も見直した方が良いと感じました。 NRTや全TLOGのレプリカタイプでコレクションを作成した方が良い 1podがダウンしても更新や検索に影響のないシステム構成にする必要あり 必然的にDataImportHandlerのようにデータをpullする方式の採用は難しくなる 検証用途には手順を圧縮できるため便利に感じる一方、サービス運用には検討すべきことが多いという印象でした。 業務等でSolr Operatorの利用を検討されているようでしたら、本記事が一助になれば幸いです。 最後に 弊社では、本記事に記載したような新しい取り組みや、より良いシステムを作りを一緒に進めていくためのメンバーを随時募集しています! 株式会社 エニグモ すべての求人一覧 hrmos.co
BUYMA Globalの事業統括責任者をしているHibaruです。 私はエンジニアではないのですが、プロダクトマネージメント業務にも携わっており、今回は私が BUYMA Globalのプラットフォームに導入したAI企業「 Mad Street Den (以下MSD)」が開催したカンファレンスに招待いただき、たくさんのインスピレーションを得ることができたので、ブログを書かせていただきます。 Montego Bay, Jamaica カンファレンスが行われたのは、なんと カリブ海 にあるジャマ イカ 。 私は普段ロサンゼルス在住なのですが、ジャマ イカ は初上陸でした。 今回は開催企業の取引先で米国企業を中心に世界中からリーダーシップが招待され、 ケーススタディ や新しい技術へのアプローチ方法などをディスカッションする2日間のイベントでした。 DAY 1: Dinner / Meet & Greet 美しい カリブ海 に浮かぶジャマ イカ のMontego Bayにあるリゾートに全員宿泊し、そこからバスで歴史的なハウス ミュージアム であるローズホール・ゲストハウスへ。 Rose Hall Guest House REBUILDと題されたイベントは今回で3回目の開催だそうで、初回はインド(MSDはインドが本拠地です)、2回目がドバイだったそうです。 REBUILDは単なるイベントではなく、「コミュニティ」だと開催にこめた思いなどがMSDのCEOとCTOから語られました。 “テク ノロ ジー のトレンドは、ユーザーのインフルエンス力が大きなパワーとスピードをもたらす” Dinnerの Keynote スピーチは、元P&GでGlobalのITチーフをしていたAndy Walter氏が務め、レガシー的な大きな組織に「インターネット」を導入した際のお話や、彼のキャリアでは常に「もっと社内の人にインフルエンスしなさい」と言われ続けてきたストーリーを話してくれました。 それから、Chat GPTの話にもなりましたが参加者たちの意見では Google がいずれovertakeするだろうとの見解。 この大きなトレンドには、業界の インフルエンサー たちが大きく貢献しているという例でした。 Dinner Dinnerでは海外のビジネスシーンでは欠かせないネットワーキングで、お互いのビジネスやチャレンジ、コラボレーションの可能性などを話します。(これがいまだに苦手ですが頑張りました) アフリカ向けにブティック連携した マーケットプレイス を展開している会社や、 中南米 の Amazon と呼ばれる マーケットプレイス などEcommerceに関わる企業や、メディカル、 ファイナンス など様々な業界から、CEOやCTO、プロダクトマネジャーが参加していました。 Day 2: Case Studies & Panel Discussion 2日目はカンファレンス本番で、会場を Half Moon Resortに移し、朝から夕方まで ケーススタディ やパネルディスカッションが行われました。(ちなみにこの Half Moon Resortは、 エリザベス女王 を始め多くのロイヤルファミリーが宿泊したそう!) データセントリック vs モデルセントリック? 世界のCIO, CDTO, CDO , CEOが回答した答えはクリアだった Data centric AI approach AIにフォーカスする市場での答えは「 データセントリック 」 CDO とCIOは、20-21年にAIに $50B を費やしたが、ビジネスの成果という点では、何の成果も得られていない(*MITSloan) 機械学習 やAIの技術者・担当者は、「モデル構築」することにフォーカスしがち。しかし正解は「 データのクリーンアップ、コネクト& アクティベーション 」である(モデル構築が答えではない) 全ての基盤となる「データ」 Data is everything MSDが考えるAIアプローチ・AI Transformationの始まりは、全てデータから始まる。 データがクリーンでない、統合されていない、正しいデータソースを見極められない、これらができていないと、結果としてコストが高くなり(データサイエンティストやマニュアル作業の時間的コストも含める)ROIが見合わなくなり、エンドレスにモデル構築をしなければならない。 “これまでの「AI Transformation」から「ROI-Driven AI Transformation」へ” ケーススタディ から学ぶAIアプローチ AYA Healthcare : San Diego発のトラベルナース派遣サービス。Pandemicで急激に増えたトラベルナースの アサイ ンメントのマッチングをするため、リアルタイムで対応できるAIレコメンデーションを使用。 ナースのプロフィールやスキル・資格と アサイ ンメントが合っているか、お給料の希望レンジや希望ロケーションなど、そして特別な アサイ ンメントには条件がクリアできるナースが登録している中から2名とかしかいない場合もあるので、そういった急務な案件をそのナースの検索結果のトップに出せるようにした。 今後はDocumentationスキャンのAutomationを導入しようと思っている。ナース登録や アサイ ンメントに入る際のAgreement、書類のアップロードなどがスムーズにできるようにする Fedex : Fedex x ShopRunner のFulfillment OptimizationにAI活用。 特に荷物がどこのロケーションにあり、どこへ送るのか、またカスタマーが希望している優先順位は何か(配送の速さ、Sustainability、価格)によって配送オプションの出しわけをできるようにした。今後Cross-border向けのDocumentationスキャンもAI導入予定 PICARD : ドイツ発の老舗バッグブランド。PandemicをきっかけにOnline Storeに力を入れることになったが、モデル着用画像がなくEcommerceパフォーマンスは低迷。MSDの提供するVue.aiモデル着用AIを利用し、CVR +65%、AOV +12%、返品率 22%ダウンを実現させた。 Retail業界をAIがどう変えていく!? 実はこのテーマのパネルディスカッションに私も登壇させていただきました。 英語で世界のリーダーたちとゲストの前で登壇をするのはとても緊張しましたが、前もってかなり練習をしていったので、スムーズに発言できたのではないかと思います。 終わった後にたくさん皆さんに声をかけていただき、また BUYMA のサービスにもとても興味をもっていただけました! 消費者の検索動向トレンドに合わせてAIを活用していくケースや ユースケース が出てきている AIを導入することでパーソナライゼーションやレコメンデーションが大幅進化している!例えば同じアカウントを使って違う家族のメンバーがお買い物をしようとしていたら?アクセスする時間帯と傾向をマシンラーニングし、そこでパーソナライゼーションやレコメンデーションを出し分ける例まであるそう。 過剰在庫の世界的問題にAIがどう貢献できるのか?この過剰在庫という問題は環境やエコノミーにも非常に大きく影響している世界的問題。AIを使って、過剰在庫になる前にそれらの商品を予測し、プロモーションをしたり、追加発注をしないようにできる技術も開発されている。 Innovation x Leadership(AIや新しい技術へのアプローチ、組織改革へのアプローチ) Victoria's Secret: どのようにDigital innovationをLegacy化した大きな組織に素早く導入するか。 Story-tellingできるプロトタイプを作ることが重要。 50つのアイディアがあっても、そこから検討テーブルに上がるのが7-8つだったそう。 PassionがInnovationを作っていくこと、社内で新しいInnovationやアイディアをインフルエンスしていくことが重要だとここでも語れました。 そしてGen-z世代はTechnologyと共に生きているので必要不可欠であることを理解する。 Mercado Libre : 中南米 の Amazon と呼ばれる大規模な マーケットプレイス 。 ビジネス拡大が加速し、1000人未満だったエンジニアが数年で15000人のエンジニア組織に急速拡大。 大きな技術・組織改革において、「Culture / Language / Technology」を素早く共有し、適応してもらうにはかなりのチャレンジがあった。 10000人以上にNew Hireのうち、なんと70%がRefarralで構成されていることで、「Culture / Language / Technology」の適応の大部分をカバー、30%は全くの未経験も含んでいたが、この3割にはト レーニン グに注力した。 たくさんの学びがありましたが、 Key Takeaway をまとめてみます。 ★基盤となるデータの重要性 ★TechnologyはCultureであること(技術そのものが人の役割をTake overするのではなく、技術を理解しどのように扱う・活用するか考える人が重要である) ★TechnologyはCommunityであること(今回のイベントのように、様々な業界から人が集まり ケーススタディ やUse caseをシェアし、課題を共有し、アイディアを出せること) 2日目はカンファレンス後、プライベートアイランドでサンセットを見ながらのパー ティー 。 こんな規模でイベントを開催するMSDにとても驚き感心しました! そして何よりMSDのCEOはインド人の女性で、テク ノロ ジー 業界で成功する女性としてインスピレーションをもらい勇気づけられました! Bonding with girls in tech! エンジニアではない私の体験&感想を書かせていただきましたが、いかがでしたでしょうか? 次回はぜひ社内のデータサイエンティストやエンジニアの方にも参加してもらえたら、また違った視点でインスピレーションがあるのではないかとおもいました。 最後まで読んでいただき、ありがとうございました! Hibaru
サーバーサイドエンジニアの岡本です。 BUYMA の出品者向け機能の開発を担当しています。 弊社のエンジニアチームでは、昨年後半からいわゆる「お問い合わせ対応」の組織的な取り組みを行っておりますので、少しではありますがその取り組みについて紹介したいと思います。 エニグモにおけるお問い合わせ対応 お問い合わせ対応の流れ 調査 休日の対応 身に付いたことや改善点など エニグモ におけるお問い合わせ対応 これまで社歴の長いエンジニア数名が対応することが多かったのですが、エンジニア組織体制の見直しに伴い、CS対応の運用方針に関してもテコ入れを行うことになりました。 特定のメンバーがお問い合わせに対応することで他のメンバーに対してナレッジを共有する機会が少なくなり、お問い合わせ対応が属人化してしまうという問題を抱えていました。 BUYMA は機能ごとに大きくSELL/BUY/SI *1 の3チーム(以下、 ドメイン と呼ぶ)に分割している *2 ので、各 ドメイン から一次担当を行うメンバーを選抜し、 ドメイン ごとにお問い合わせに対応する運用を行うようにしました。 運用開始から半年以上が経過しましたので、振り返りを行います。 お問い合わせ対応の流れ お問い合わせ対応で取り組んでいることは以下になります。 一次対応 再発防止策の検討 ナレッジ共有のためのドキュメント作成・定期チケットの作成 休みの共有・緊急時対応への備え 調査 カスタマーサービス チーム(以下、CSチーム)の方がCS対応用のチケットを作成いただき、Slackで連絡していただきます。それをみて対応できそうなメンバーが順次チケットの内容を確認します。 不具合の報告の場合は、弊社で管理しているお客様のアカウント情報をもとに アプリケーションサーバ のログを追跡したり、仕様の調査を行います。調査が終わればチケットに調査内容を記載した上でCSチームの方に連絡をします。ここで、チケット作成から一次調査完了までのスパンをできるだけ短くできるように各自心掛けています。CSチームの方が調査が難航する場合もありますので、その場合はお断りを入れた上で調査を続けます。 調査の上でアプリケーションコードの修正が必要な場合は対応を行います。別途起票をして対応することが多いです。 データ補正が必要な場合は修正用の SQL 文を作成し、レビューを経た上で本番のDBサーバに対して実行します。 一次対応の流れ 対応したチケットは スプレッドシート に記載をして、ふりかえりを行う際や別のお問い合わせの調査を行う際に活用しています。 調査をしてみて、対応した内容や参照したログ、実行したコマンドなどなどを esa 上のドキュメントに記す取り組みも実施しています。 ドメイン ごとに整理でき、とても良いと感じています。 一次対応~対策防止策検討~ふりかえり 休日の対応 有給休暇を取る場合は事前に ドメイン 内で伝えておき、別のメンバーが対応できる体制を整えています。 また極めて稀ではありますが、土日祝日に緊急対応が必要な場合がありますので、待機できるメンバーを予め選出しています。 身に付いたことや改善点など 先日、お問い合わせを担当するメンバーに意見を聞き、これまでの取り組みを通じて身についたことや今後の課題などを話しました。 身に付いたこと ログ監視ツールを使ったり該当のログサーバに ssh するなどして、 アクセスログ やスナップショットを参照する方法が身についた BUYMA の ビジネスロジック を理解する機会が増えた。また、自身の担当 ドメイン 以外のコードも読む機会が増えた 作業見積もりの能力 例えば、午後1時にお問い合わせがきたら調査や作業に4時間くらい確保できると見積もり、その時間内でできそうなことを予想する。 限られた時間内で出来る複数の対応策を提案する CSチームのメンバーとの連携、検索やモバイルなど他チームとの連携を仰ぐ 今後改善できそうなこと 個人的な マインドセット 寄せられるお問い合わせに怯まず淡々とやる 依頼を受けてから返答するまでの時間の短縮・判断力の向上 組織的仕組みづくり 属人化しないために調査手順ドキュメントや仕様の拡充 お問い合わせ対応のリードタイム計測 バグ傾向の分析 お問い合わせ報告が多い機能を分析し、改善につなげる。 定期チケットの作成 プラスになる点として、 BUYMA 及び ECサイト の ドメイン 知識が身につくのは大きいと思います。私も入社して3年目となり、担当している出品者向け機能について少しは知っていると思いますが、まだ把握し切れていない仕様・機能は多くあります。特に決済や配送方法は難しい…。日々のお問い合わせ対応を通じて知見をアップデートしています。 改善点は様々ありますが、隔週で定例会議を行っており、日々改善に向けて取り組んでいます。 株式会社 エニグモ すべての求人一覧 hrmos.co *1 : SELLは出品者向け機能、BUYは購入者向け機能、SIは決済や配送などサービス基盤を担当 *2 : モバイルアプリやデータ分析や 機械学習 系や企画系などチームは他にもあります
こんにちは、22卒エンジニアの 川本 です。 先日「 AWS JumpStart 2023 設計編」という研修に参加してきました。 2日間と短い時間でしたが、とても内容が濃くて勉強になったので、本記事では研修の内容や参加した感想を綴っていきたいと思います。 AWS JumpStartとは? AWS公式HP では以下のように書かれております。 「 AWS JumpStart 2023 設計編」は AWS 初学者のエンジニアの方々を対象とした、実践的な研修プログラムです 将来的に AWS 活用をリードする人材になるための第一歩をスムーズに踏み出せるようなプログラムをご提供します 単なる AWS サービスの学習だけでなく、要件に合わせて適切な アーキテクチャ を検討・設計する経験を積む部分にフォーカスした内容となっております 例えば、以下のような方々にもオススメです! ・ AWS の名前は知ってるが使ったことは無い ・ EC2 等の単体サービスは触ったことあるが、全体のアーキテクティングは経験がない ・ クラウド ネイティブなアプリケーションを設計する上で重要な観点を知りたい AWS 初学者向けの クラウド アーキテクチャ を検討・設計するイベントで、参加人数が600人以上いる大規模イベントでした。 プログラム内容 研修は以下の構成で行われました。 事前学習 ハンズオン グループワーク 事前学習 研修参加前に事前学習として、 AWS SAA向けの動画学習教材が送られてくるのでそちらで AWS の基本的なサービスについて学習します。 また、 AWS のサービス説明だけでなく、アーキテクティングのコツみたいな内容も盛り込まれており、研修当日に非常に役に立ちました。 私は完全に AWS 未経験だったため、こちらの教材で事前学習しておいてほんとによかったです。 ハンズオン 1日目にまずハンズオンがあり、 AWS 上にTodo管理アプリを構築するといった内容でした。 以下の図のように ALB + ECS on Fargate + Aurora MySQL の アーキテクチャ を構築しました。 ハンズオンの中で面白くて勉強になったのが、上記の アーキテクチャ でECSタスクを片方停止させたときの挙動や、Aurora MySQL のフェールオーバーを実行したときの挙動を実際に手を動かして確認したことです。 ECSタスクが片方死んでも自動復旧している様子や、フェールオーバーしたことによりAurora MySQL のリーダーとライターが切り替わる様子を確認することができました。 このような実践的なハンズオンのおかげで、可用性やスーケラビリティを意識した アーキテクチャ とはどういうことなのかというイメージがより具体的になりました。 また、ここまでの アーキテクチャ を個人で作成するとお金がかかりますが、その辺りを意識せずに AWS サービスを触ることができるのもうれしいポイントですね! グループワーク 2日目はグループで課題に沿った アーキテクチャ を構築するといった内容でした。 以下のような要件を満たす ECサイト を構築してくださいという課題が与えられました。 提供規模 利用者数:数万人 ピーク時間帯:日本時間の朝夕 提供エリア:日本 提供プラットフォーム:web システム要件 バックエンド: Java /Spring Boot(Dockerで開発中) フロントエンド:TypeScript/ReactJS データベース: MySQL 必須機能 商品一覧ページ 商品情報 商品画像 カート機能、購入機能 決済、在庫管理、配送システムは外部の SaaS API を利用するものとする アカウント管理機能 追加要件 CI/CD BI ダッシュ ボード機能 レコメンド機能 普段から BUYMA の開発をしておりECサービスには馴染みがあったのでイメージしやすかったです。 しかし BUYMA は全ての箇所で AWS 上のサービスを使っているわけではありません。 なので、 BUYMA のこの部分は AWS だとこのサービスが使えるなというような観点で アーキテクチャ を構築していきました。 このような観点で アーキテクチャ を構築することで BUYMA への理解も深まったので、私にとっては一石二鳥な課題内容でした。 最終的に構築した アーキテクチャ は以下構成図です↓ 工夫した点としては、 ECS on Fargateの構成によりコンテナのAutoScalingを実現してサーバーの可用性up RDSはMulti-AZ構成として、障害発生時にフェールオーバーしてリーダー、ライター インスタンス が切り替わるようにして可用性up ElastiCacheを使うことでデータベースクエリのレスポンスを高速化 Cloud Frontを使うことで静的コンテンツ配信の高速化 他にもCI/CDの整備やBIツールの導入、レコメンド機能への対応などを行いましたが、 AWS にはそれぞれに適したサービスが用意されており、本当にサービスの種類が豊富だなと思いました。 研修を終えた感想 参加前は AWS についてはなんとなくサービス名を知っている程度でしたが、研修で実際にハンズオンで手を動かしたり、チームで アーキテクチャ 議論をすることで AWS の全体感を掴むことができました。 また、Webアプリケーションの アーキテクチャ を設計する上で意識すべき可用性やスケーラビリティについて学べたことが大きな収穫だったかなと思います。 AWS のサービス名について知っていても、 アーキテクチャ を設計する上で重要なことがわかっていないと適切なサービスを選択することもできませんし、設計することもできないと感じました。 最後に 今回の研修を機にインフラのことについても少し興味が湧きました。 AWS SAAの資格取得なども目指していきたいです。 最後に、このような素晴らしい研修を無償で開催してくださったアマゾン ウェブ サービス ジャパン 合同会社 の皆さま、ありがとうございました! 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは、インフラエンジニアの 加藤( @kuromitsu_ka )です。 はじめに Amazon RDSのEoS対応で、 インスタンス クラスとエンジンバージョンを変更する作業をしました。その際、 インスタンス クラスとエンジンバージョンを同時に変更しようとしたのですが即時適用されず困りました。 EoS関係のドキュメント Amazon RDS for PostgreSQL リリースカレンダー - Amazon Relational Database Service DB instance classes - Amazon Relational Database Service 解決の流れ 社内のサポートを受けて、保留になった変更を取り消す方法を教えて貰いました。保留になっていた インスタンス クラスとエンジンバージョンの変更の内、エンジンバージョンの変更を取り消したところ、 インスタンス クラスの変更が走りました。その後、エンジンバージョンも変更して、無事、メンテナンス対応できました。 わかったこと Amazon RDSの変更が保留に入ってしまった問題ですが、 AWS サポート窓口に質問したところ、既知の問題だったそうです。 Amazon RDSの インスタンス クラスとエンジンバージョンを変更する際は、 インスタンス クラスと、エンジンバージョンとで、2回に分けて変更する手順を推奨しているとのことでした。 以下、作業ログ インスタンス クラス エンジンバージョン 作業前 db.m3.xlarge 11.15 作業後 db.m5.xlarge 11.18 インスタンス クラス変更とエンジンバージョンのバージョンアップを同時に適用しようとしたら、変更が保留になってしまった。 実行したコマンド $ aws rds modify-db-instance \ --db-instance-identifier ${DB名} \ --engine-version ${バージョン} \ --db-instance-class ${インスタンスクラス} \ --no-allow-major-version-upgrade \ --apply-immediately --apply-immediately をつけているのに保留となってしまった。 "PendingModifiedValues": { "DBInstanceClass": "xxx", "EngineVersion": "xxx" }, 保留の取り消し 変更前の値を適用することで、保留状態を脱することができました $ aws rds modify-db-instance \ --db-instance-identifier ${DB名} \ --engine-version ${変更前のエンジンバージョン} \ --apply-immediately 保留されていた インスタンス タイプ変更が始まった。 よかった!! 振り返り 該当の インスタンス クラスが、エンジンバージョンをサポートしていないというわけではありませんでした。 Amazon RDS DB エンジンとインスタンスクラスでサポートされている Performance Insights - Amazon Relational Database Service 今回の問題ですが、開発環境ではうまく行って、本番環境だけ発生しました。 こちらは一度のコマンドで インスタンス クラスもエンジンバージョンも変更できた。(たまたまかもしれない。 インスタンス クラス エンジンバージョン 作業前 db.t2.micro 11.15 作業後 db.t3.micro 11.18 当日は、困りましたが、その場で社内のサポートを受けて解決できました。個人的に、 Amazon RDSの変更取り消し(と言っていいのか微妙ですが)コマンドが、裏コマンドっぽいので気に入りました。 株式会社 エニグモ すべての求人一覧 hrmos.co
~合議制 “Committee体制” の導入~ 目次 新体制の導入の背景について Committee体制の実行に向けて Committee体制の詳細について ビジネスサイドとの連携について 〈インタビュイー経歴・紹介〉 安藤 英男 COO/取締役 最高執行責任者 1997年に株式会社 電通国際情報サービス に入社。2004年株式会社 エニグモ 設立。2005年当社取締役、2010年に当社COO(取締役 最高執行責任者 )に就任。 木村 慎太郎 / エンジニア リングマ ネージャー Committee Head 2013年に エニグモ にWebアプリケーションエンジニアとして入社。 データ・ 機械学習 ・検索の基盤開発・運用を担当するエンジニアチームを立ち上げ、 BUYMA のエンジニア組織のマネージャーおよび、組織の運営方針を決定する合議体のHeadを務める。 山本 浩貴/ エンジニア リングマ ネージャー Committee Vice Head 2016年に エニグモ にWebアプリケーションエンジニアとして入社。 現在は出品者向け機能を開発するチームとフロントエンドチームのマネージャーおよび、組織の運営方針を決定する合議体のVice Headを務める。 〈インタビュアー経歴・紹介〉 大谷彰徳/ コーポレートオペレーション本部 人事総務グループ部長 2002年株式会社 博報堂 入社。アカウントプロデュース職として国内外企業のコミュニケーション施策に携わる。2015年に エニグモ に入社。コーポレートオペレーション本部/人事総務グループの部長に就任。採用、人事企画、 労務 、総務、コーポレートITの領域を統括。 新体制の導入の背景について 大谷: 今回、当社のエンジニア組織のマネジメント体制が大きくリニューアルされましたが、その背景や経緯についてCOOの安藤さん、エンジニア リングマ ネージャー(以下EM)の木村さん・山本さんにお話をお伺いできればと思います。 まずは本題に入る前に安藤さんにお伺いしたいのですが、COOとしてどのようなことを意識して、日頃からエンジニアの組織やメンバーと関わっていらっしゃいますか。 安藤: エンジニア以外にも当てはまることですが、特に意識している部分は、まず「人」の部分になります。 どのメンバーに重要なロール(役割)を担ってもらうかの判断はとても大事なため、そこはしっかりと自分なりの確信を持てる状態にしたいと思っています。 技術的な部分は基本的に自分が戦略を立てるわけではありませんが、会社レベルで決めるべき重要なことは、技術的な領域でも重要なロールを担うメンバーとディスカッションした際に、その良し悪しを自信をもって判断できる状態にしています。 大谷: 「どういう人にどのようなロールを担ってもらうのか」という判断は、まさに組織作りにも大きく関わる部分ですが、今回その組織作りの取組みのひとつとして実施された 「Committee体制」 の導入についてお聞きしたいと思います。 今回、 エンジニア組織をCTOや部長を頂点とするワントップ型ではなく、EM陣で構成する「Committee」という合議体を意思決定のトップ機関として新設し、そのHead、Vice Headを1年交代の輪番制で運営する という体制への移行しましたが、その導入背景を教えてください。 安藤: これまで エニグモ はエンジニア組織に関わらず、会社全体として少数精鋭の筋肉質な組織で成長してきました。その為、当社の技術志向の高いエンジニア達には過度なマネジメント負荷をかけずに開発に専念してもらいたいという思いがありました。それがフラットな組織で フルスタ ックに自分のスキルを発揮できる環境に繋がり、そこを魅力に感じるエンジニアが自然と集まっていました。 そして上場から10年が経ち、技術領域も多岐に広がり、組織やサービスも格段に大きくなり、今までのやり方で組織を最適にマネジメントすることが難しくなってきました。 それまでは経営陣もエンジニアにはマネジメントの負荷をなるべくかけないようにと考えていましたが、当社らしいエンジニア流のマネジメント体制への進化が必要なフェーズになりました。 そしてEMたちからも「組織的な課題を解決したい」「こういう組織にしていきたい」という前向きな意見が自然と出てくるようになりました。そのような中で、これまでの エニグモ のエンジニア組織のカルチャーを大切にしながら最適な方向を検討する中でCommitteeというコンセプトが思い浮かびました。 大谷: 新体制の中でも特徴的な 「EM陣による合議制」 のコンセプトや 「CommitteeのHeadとVice Headを1年交代の輪番制」 にしようと考えた背景はなんでしょうか? 安藤: 社内のエンジニアで組織のトップの経験がないメンバーでも、ハードルが高くならずチャレンジしやすいようにしたかったのが一つです。また、属人化させず色々なメンバーの意見を取り入れて多面的に進化していく組織体制にしたいと考えました。 属人化しすぎないためにトップが行う業務を分解して「ロール(役割)」という抽象的な言葉で定義し、それをいろいろな人の手で育てていくような体制であっても良いのではないかと思いました。重要な判断をともなうロールなどにおいても、それをサポートする他のCommitteeメンバーも次回自分がやる可能性がある状況に置くことで、「自分だったらどうするか」という視点になり、自分ごと化して業務に取り込むことができます。そういった状態が組織として健全ではないかと感じ、輪番制を取り入れました。 さらに、マネージャーやトップの業務も1つのロールであると考えています。 優秀なエンジニアが エニグモ で長く活躍する際に、マネージャーとしてパフォーマンスが高かった人でも、自身がチャレンジしたいことに応じて自発的に スペシャ リスト(技術者)に戻るというキャリアがあっても良いと考えています。 マネージャーになること=唯一のキャリアステップアップにしたくない と思っています。 マネージャーはあくまで組織の中でマネー ジャーロ ールを担っている人という形で定義することで、上下という立ち位置にせず、ある時はマネージャーをやっていたが、ある時は スペシャ リストである。らせん階段を登っていくようなキャリアの選択があっても面白いのではないか、それで組織全体にプラスになることもあり、キャリアアップの多様化にも繋がると考えます。 色々な観点でエンジニアが主体的に自らの組織や専門性を成長させていける体制になることを目指したいと考えたのが背景です。 Committee体制の実行に向けて 大谷: 続いて、木村さんと山本さんにお聞きしたいのですが、部長やCTOを置かないフラットな組織運営であるCommittee体制について、初めて方針を聞いた時にどう感じましたか? 木村: 私も、エンジニア組織全体について「自分的にはこうした方がいい」みたいなところは考えていて、実際に話し始めていたタイミングでした。 フラットな組織体制については、他社でトップにCTOがいる場合でも、CTOを補佐するメンバーがたくさんいるCTO室を設置するような会社もたくさんあります。そういったトップを補佐する仕組みが必要であるというのは理解していました。そういったところから安藤さんから提案についても「いいな」と思いました。輪番制についても、Headになることへの 心理的 ハードルが下がりますし、自分に就任を打診された際もポジティブに受け止めることができました。 山本: 自分も今回の話がある前から、組織的にもう少しやった方が良い部分があるなと感じていました。他社の体制や取り組みを調べてみて、 エニグモ にはどんなやり方が最適なのかを考えていたので、Committee体制についても前向きにとらえました。 ただ、初めは部長やCTOという分かりやすいトップがいないことについては少し不安もありました。 でも実際にCommitteeが発足したおかげで、組織作りについてEM同士で定期的かつ積極的に会話する場ができたことで、今まで以上に組織がクイックに良い方向に向かい始めたことをすぐに実感できました。 Committee体制の詳細について 大谷: 木村さんが初代Headに決まってから、さらに具体的なCommittee運営に向けた体制づくりに着手されましたが、最終的な実施体制について概略を教えていただけますか。 木村: 繰り返しになりますが、新体制はCTO、VPoEという役職を置かず、複数名のEMがCommitteeという合議体を形成して、意思決定のトップ機関となっています。トップは輪番制となります。優先順位が高い組織課題は分科会を配下に設置して議論・決定のスピードを上げていきます。 Committeeが発足してまず行ったことは、トップが単独で担っていたロール・タスクを分解・抽象化していって組織に落とし仕込み、Committeeメンバーの誰が担当するかを決めていきました。 その際に現在足りない役割や、新たに採用すべきポジションなども同時に整理しました。 山本: エンジニア組織のトップがやるべき仕事は非常に多岐に渡ります。 トップの役割は、チームのマネジメント(ピープル〜プロジェクトマネジメント)や技術的意思決定、採用・評価に止まらず、システム監査、インシデント指揮、予算・経費管理といった様々な役割があります。技術職から見ると少し敬遠したくなる"雑務”と感じる業務もトップに集まりがちになるので、そういう業務も含めて、誰が担当するか?今後どのように管理・意思決定するのか?をCommitteeメンバー内で前向きに議論しながら決めることができました。 ビジネスサイドとの連携について 大谷: エンジニアとビジネスサイドが密に連携して業務を推進する当社においては、今回の体制変更はビジネスサイドの特にマネジメント陣にしっかりと理解してもらう必要がありますよね。どのような形でインプットを行ったか教えてください。 木村: はい。今回の組織体制はエンジニアだけでなく、ビジネスサイドにもリンクすることがとても重要だと考えました。経営陣からも、せっかくなのでオフィスから離れた場所で1日ワークショップ形式で時間を取って共有とディスカッションをしようよ、と提案いただいたのはありがたかったです。 安藤: エニグモ はエンジニアとビジネス側、企画メンバーが一緒になってプロダクト、サービスを創り上げていくことを大切にしている風土です。 今回はエンジニア組織のターニングポイントとなったので、ビジネス側の部長や、エンジニアと密に仕事をしているメンバーとは事前にキックオフをし、よく理解してもらい、もし疑問があれば解消しておく必要があると考えました。 やはり、エンジニアとビジネスサイドのメンバーが境界なく同じような価値観で同じような背景を理解した上で、協力・連携して仕事をすることはすごく大切なことです。 木村: 今回のキックオフを通して、エンジニア組織の話にとどまらず、開発側とビジネス側のさらなる連携強化についての議論にも発展し、例えば、全社横断的な重要プロジェクトの推進方針(カンパニーベットの概念)についても自然と議論が湧き起こったりして、非常に有意義な日になりました。 キックオフ終了後、そのビルの屋上でみんなでBBQをやったのもいい思い出です(笑) 今回の記事では新体制(Committee体制)の移行についてお話ししました。後半は新たな開発体制についてお話しします。後半もお楽しみに!
こんにちは、インフラエンジニアの 高山 です。 この記事は Enigmo Advent Calendar 2022 の25日目の記事です。 はじめに エニグモ 入社後に AWS を徐々に触れ始め 数年経過しました。 最初はWebコンソールからポチポチしていたのですが、CloudFormationでコード化を進めたり AWSCLIや SDK を使うようになり、最近は Ruby で AWS リソースの情報取得や操作をすることが多くなってきました。 (以下、 RubyでAWSリソースの情報取得や操作をする ことを AWSをRubyで操作する と表現します) AWS を Ruby で操作するようになった理由は以下です。 そもそもWebコンソールは苦手(というより怖い)で、 CLI で操作したい派である 構造的なデータを扱うのは Shell スクリプト だと厳しい(jqが嫌い) Ruby on Rails (以下、 Rails と表記します)を使ったことがあるので、 Ruby に少しは慣れている BUYMA では Rails を採用しているので、社内で聞ける AWS を操作するには python (+boto3)を使っているユーザの方が圧倒的に多そうな気がしますが、 python と比較しているわけではないので、片手落ち感は否めない記事になってます。 相性が良いと思う理由 AWS と Ruby は相性が良いと思う理由、それはデータの シリアライズ が簡単にできるからです。 この一点に尽きるので、ここで記事終了でも良いくらい。 シリアライズ とは シリアライズ というのは データやオブジェクトをファイルに書き込みできるように変換することです。 反対はデ シリアライズ 。 言いにくいですね。 やってみよう シリアライズ は yaml ライブラリを使い、オブジェクトを yaml 化して、ファイルに保存するだけです。 $ export AWS_REGION = " ap-northeast-1 " $ pry [ 1 ] pry(main)> require ' aws-sdk-ec2 ' => true [ 2 ] pry(main)> require ' yaml ' => true [ 3 ] pry(main)> ec2_client = Aws :: EC2 :: Client .new(); [ 4 ] pry(main)> ec2_data_list = ec2_client.describe_instances(); [ 5 ] pry(main)> File .open( " ec2_data_list.yml " , ' w ' ){|h| h.write ec2_data_list.to_yaml} => 896272 [ 6 ] pry(main)> quit $ ls -l ec2_data_list.yml -rw-rw-r-- 1 ec2-user ec2-user 896272 Dec 21 15 : 49 ec2_data_list.yml デ シリアライズ も同じように yaml ライブラリを使ってloadするだけです ※ aws-sdk-ec2 を require する必要はあります $ pry [ 1 ] pry(main)> require ' aws-sdk-ec2 ' => true [ 2 ] pry(main)> require ' yaml ' => true [ 3 ] pry(main)> ec2_data_list = YAML .load_file( " ec2_data_list.yml " ); [ 4 ] pry(main)> p ec2_data_list.reservations.count; 149 簡単ですね。 シリアライズ できることの何が嬉しいのか 簡単に シリアライズ できることは わかっていただけたと思いますが、それの何が嬉しいのか? データ構造を そのままファイルにして、それを読み込むことができるので 以下を分離することができます。 時間がかかるデータ取得の処理 いろいろ試行錯誤したいデータ整形の処理 👆が嬉しいことなのですが、伝わりませんね 実際にやってみましょう。 スクリプト の例 データを取得する スクリプト まずデータを取得する スクリプト です。 EC2 インスタンス が多い場合は next_token が nil になるまでループする必要があります。 (データが少なければ不要です) ここは できるだけフィルターした方が良いですが、今回は検証なのでしていません。 データ取得は数秒程度ですが、検証のたびに取得し直すは地味にストレスですよね。 $ cat get_all_ec2_data.rb #!/usr/bin/env ruby require ' aws-sdk-ec2 ' require ' yaml ' ec2_client = Aws :: EC2 :: Client .new() all_ec2_data_list = [] token = nil loop do ec2_data_list = ec2_client.describe_instances({ next_token : token}) token = ec2_data_list.next_token all_ec2_data_list += ec2_data_list.reservations break if token.nil? end File .open( " all_ec2_data_list.yml " , ' w ' ){|h| h.write all_ec2_data_list.to_yaml} インタラクティブ シェル(pry)で確認 次はデータ構造や、データをどうやって整形するか確認しましょう。 以下は Nameタグの取得方法を確認した時のログです。 [ 1 ] pry(main)> require ' aws-sdk-ec2 ' => true [ 2 ] pry(main)> require ' yaml ' => true [ 3 ] pry(main)> [ 4 ] pry(main)> all_ec2_data_list = YAML .load_file( " all_ec2_data_list.yml " ); [ 5 ] pry(main)> all_ec2_data_list[ 6 ].instances.first.tags => #<struct Aws::EC2::Types::Tag key="Name", value="Test-BM-Rails-19">, #<struct Aws::EC2::Types::Tag key="role", value="Railsweb">, #<struct Aws::EC2::Types::Tag key="Service", value="Buyma">, #<struct Aws::EC2::Types::Tag key="CreateUser", value="takayama">, [ 6 ] pry(main)> all_ec2_data_list[ 6 ].instances.first.tags.class => Array [ 7 ] pry(main)> all_ec2_data_list[ 6 ].instances.first.tags.find{|tag|tag[ " key " ]== " Name " } => #<struct Aws::EC2::Types::Tag key="Name", value="Test-BM-Rails-19"> [ 8 ] pry(main)> all_ec2_data_list[ 6 ].instances.first.tags.find{|tag|tag[ " key " ]== " Name " }[ " value " ] => " Test-BM-Rails-19 " 各EC2 インスタンス のena_supportが有効になっているどうかをチェックする スクリプト 各EC2 インスタンス の ena_support が有効になっているどうか チェックする スクリプト を書いてみました。 (例として良いものが思いつかなかったです。。) $ cat check_all_ec2_ena_support.rb #!/usr/bin/env ruby require ' aws-sdk-ec2 ' require ' yaml ' all_ec2_data_list = YAML .load_file( " all_ec2_data_list.yml " ) all_ec2_data_list.each do |ec2| name = ec2.instances.first.tags.find{|tag|tag[ " key " ]== " Name " }[ " value " ] puts "#{ name } : #{ ec2.instances.first.ena_support }" end 以下のような感じで出力されます。 $ ./check_all_ec2_ena_support.rb | head -5 Test-Railsweb-Server : true Test-Phpweb-Server : true Test-EC2-Instance : false Test-Airflow-Server : false Test-Redash-Server : false EC2のタグだけ取ってファイルに保存する スクリプト 次は EC2のタグだけ取ってファイルに保存する スクリプト を作成してみました。 $ cat check_all_ec2_tags.rb #!/usr/bin/env ruby require ' aws-sdk-ec2 ' require ' yaml ' def convert_tags_to_hash (tags) hash_tags = {} tags.each{|e| hash_tags[e[ " key " ]] = e[ " value " ]} hash_tags end all_ec2_data_list = YAML .load_file( " all_ec2_data_list.yml " ) all_ec2_tag_info_list = {} all_ec2_data_list.each do |ec2| tags = convert_tags_to_hash(ec2.instances.first.tags) all_ec2_tag_info_list[tags[ " Name " ]] = tags end File .open( " all_ec2_tag_info_list.yml " , ' w ' ){|h| h.write all_ec2_tag_info_list.to_yaml} 実行してみます。 $ ./check_all_ec2_tags.rb $ head all_ec2_tag_info_list.yml --- Test-Railsweb-Server : Name : Test-Railsweb-Server role : Railsweb CreateUser : takayama Test-Phpweb-Server : Name : Test-Phpweb-Server role : Phpweb CreateUser : takayama Test-EC2-Instance : yaml になっていると、可読性が高いところもメリットです! いったん、結論 ということで、 シリアライズ の簡単さと メリットがわかっていただけたのではないかと思います。 メリットまとめ そのままのデータ構造で保存できる インタラクティブ シェルでの確認や検証がやりやすい データの取得とデータ整形などの処理を分けやすい yaml で保存するので 可読性が高い Ruby での認証情報の取得 これまでの検証では わかりやすくするため Read権限のあるEC2上で実行していたので 認証情報の取得は不要でしたが、PC上など他の場所で AWS の SDK を使用する場合は 認証情報の取得が必要です。 $ ls -l ~/.aws/cli/cache/ total 24 -rw------- 1 takayama staff 1421 12 8 20:16 3a9ab49ce67fe5806c5af3d5a378fbbb470561d9.json -rw------- 1 takayama staff 1445 10 24 15:24 65d08609cd764dc442d836e7665fbbd663992aea.json -rw------- 1 takayama staff 1433 8 25 16:07 6c11869d293d59bf5a50ceef707e37b36524415d.json AWSCLIだと、一時認証情報が保存され再利用できますが、 Ruby の SDK を使って スクリプト を作っている場合は再利用できず、 スクリプト を実行するたびに認証情報を取得し直さないといけないのが難点でした。 しかし、それも シリアライズ で解決できます。 さすが シリアライズ さん! 以下のような感じです。 role_credentials = Aws :: AssumeRoleCredentials .new( client : sts_client, ...) role_credentials.client.config.retry_backoff = nil role_credentials.client.config.defaults_mode_config_resolver = nil File .open( " role_credentials.yml " , ' w ' ){|h| h.write role_credentials.to_yaml} そのまま保存すると読み込む時にエラーになるので 一部の不要なデータを削除してから保存する必要がありました。 aws-sdk-core のバージョンによって削除する必要のあるデータが変わるようです。 古いバージョンだと retry_backoff のみ削除で大丈夫でしたが 最新バージョンだと defaults_mode_config_resolver も削除する必要がありました。 削除しても動作には問題なさそうでした。 認証周りの機能はクラスにして それぞれの スクリプト で簡単に使えるようにしているのですが、 AWSCLIも併用して使う場合 認証情報の取得が2回になってしまう問題があります。 AWSCLIを併用する場合の認証 ということで、AWSCLIの一時認証情報ファイルを Ruby でも使う方法を考えました。 簡単に書くと、以下のような感じで 一時認証情報ファイル( json )をパースして 環境変数 として設定するだけです。 jq嫌いだけど、このくらいはね うん。 awscli_credentials_cache=~/.aws/cli/cache/xxxxx.json export AWS_ACCESS_KEY_ID= $( jq -r ".Credentials.AccessKeyId" < $awscli_credentials_cache) export AWS_SECRET_ACCESS_KEY= $( jq -r ".Credentials.SecretAccessKey" < $awscli_credentials_cache) export AWS_SESSION_TOKEN= $( jq -r ".Credentials.SessionToken" < $awscli_credentials_cache) export AWS_REGION=ap-northeast-1 実際に試してみましょう $ awscli_credentials_cache=~/.aws/cli/cache/3a9ab49ce67fe5806c5af3d5a378fbbb470561d9.json $ export AWS_ACCESS_KEY_ID= $( jq -r ".Credentials.AccessKeyId" < $awscli_credentials_cache) $ export AWS_SECRET_ACCESS_KEY= $( jq -r ".Credentials.SecretAccessKey" < $awscli_credentials_cache) $ export AWS_SESSION_TOKEN= $( jq -r ".Credentials.SessionToken" < $awscli_credentials_cache) $ export AWS_REGION=ap-northeast-1 $ pry [ 1 ] pry(main) > require 'aws-sdk-ec2' = > true [ 2 ] pry(main) > ec2_client = Aws::EC2::Client.new(); = > #<Aws::EC2::Client> 新たに認証情報を取得せずに実行できました。 スクリプト スクリプト にしたものはこちらです。( mac を使っているので、dataがgdateになっています) スクリプト(長いので、折り畳んでおく) $ cat create_set_env.sh #!/bin/bash help () { echo -e " \n --- usage $0 <awd_profile_name> \n " exit } get_jq() { jq -r " $2 " < $awscli_credentials_cache } mk_credential_file() { rm -f ~/.aws/cli/cache/* aws sts get-caller-identity --profile $1 > /dev/null awscli_credentials_cache= $( ls -1tr ~/.aws/cli/cache/* | tail -1 ) rm -f $credential_file echo "export AWS_ACCESS_KEY_ID= $( get_jq .Credentials.AccessKeyId ) " >> $credential_file echo "export AWS_SECRET_ACCESS_KEY= $( get_jq .Credentials.SecretAccessKey ) " >> $credential_file echo "export AWS_SESSION_TOKEN= $( get_jq .Credentials.SessionToken ) " >> $credential_file echo "AWS_Expiration= $( get_jq .Credentials.Expiration ) " >> $credential_file echo "export AWS_REGION=ap-northeast-1" >> $credential_file echo -e " \n --- creation of $credential_file was completed!!" echo -e " please exec fllow command" echo -e " source ./ $credential_file \n " exit } check_expiration_time() { local expiration_time= $( awk -F "=" '$0 ~ /AWS_Expiration/{print $NF}' $credential_file) local expiration_unixtime= $( gdate -d " $expiration_time " "+%s" ) local current_unixtime= $( gdate "+%s" ) local diff_time= $(( expiration_unixtime - current_unixtime - 60 )) [ 0 -lt $diff_time ] && echo ok } [ $# -ne 1 ] && help credential_file=set_env.sh [ ! -f $credential_file ] && mk_credential_file $1 [ " $( check_expiration_time ) " != "ok" ] && mk_credential_file $1 echo -e " \n --- no need to update !!" echo -e " please exec fllow command" echo -e " source ./ $credential_file \n " $ ./create_set_env.sh < awd_profile_name > Enter MFA code for arn:aws:iam:: 123456789012 :mfa/takayama: --- creation of set_env.sh was completed!! please exec fllow command source ./set_env.sh $ source ./set_env.sh $ pry [ 1 ] pry(main) > require 'aws-sdk-ec2' = > true [ 2 ] pry(main) > ec2_client = Aws::EC2::Client.new() = > #<Aws::EC2::Client> 有効期限が1分以内に切れる場合は認証情報を再取得するようにしてあります。 テキトーに作った スクリプト で 一時認証情報のファイルを全消ししているのがイケてないですが、参考にしてみてください。 この方法は Ruby スクリプト 以外でも、 AWS の 環境変数 で認証情報取得できる機能なら使えます。 例えば Serverless Framework とか、 Terraform とか (最近 触っていないので、 確認できてませんが) 実際 実際には クラスやモジュールを作成してDRYな感じで スクリプト を作っています。 また、例えば 以下のような機能で Ruby を使用しています。 CloudFormationスタック作成や変更セット作成、変更セットの確認 ELBへのインスタスの組み込み、切り離し セキュリティグループへの追加更新用Webアプリ 各種調査 etc この中から2つ紹介します。 変更セットの確認機能 CloudFormationスタックの変更セットは 以下を確認してから適応するようにしています。 テンプレートの差分 パラメータの変更 タグの変更 リソースが作り直されるか 以下が確認時の内容です。 $ ./scripts/check_change_set.sh Lb-Instance-01.yml === Stack Name: Test-Lb-Instance-01 === Diff Check ================================================================ --- [Info]: Lb-Instance-01.yml Template Difference Exist !!! Instance: Instance: InstanceType: { Type: String } InstanceType: { Type: String } Role: { Type: String } Role: { Type: String } Instance: Instance: Type: AWS::EC2::Instance Type: AWS::EC2::Instance > - { Key: addtag, Value: dummy } - | - | RecordSet: RecordSet: Type: AWS::Route53::RecordSet Type: AWS::Route53::RecordSet === Change-Set Check ================================================================ --- - :logical_resource_id: Instance ------------------------- :resource_type: AWS::EC2::Instance :action: Modify :replacement: Conditional !!!!!!!!!!!!!!!!!!!!!!!!! :details: - :attribute: Tags :name: :change_source: - :attribute: Properties :name: InstanceType :change_source: ParameterReference - :attribute: Properties :name: InstanceType :change_source: DirectModification - :logical_resource_id: RecordSet ------------------------- :resource_type: AWS::Route53::RecordSet :action: Modify :replacement: False :details: - :attribute: Properties :name: ResourceRecords :change_source: ResourceAttribute === Change-Set Params Check ================================================================ NAME | CURRENT | NEW | STATUS -------------|----------|-----------|---------- InstanceType | t3.small | t3.medium | change Role | lb | lb | no change === Change-Set Tags Check ================================================================ NAME | CURRENT | NEW | STATUS -----------|---------------------|---------------------|---------- Name | Test-Lb-Instance-01 | Test-Lb-Instance-01 | no change Role | lb | lb | no change CreateUser | dummy | takayama | change === Validation Check ================================================================ --- [Info]: Lb-Instance-01.yml Validation Check OK === Lint Check ====================================================================== --- [Info]: Lb-Instance-01.yml Lint Check OK 補足 Shell スクリプト を実行してますが、複数のShell スクリプト と Ruby スクリプト をラッピングしています。 テンプレートの差分は 差分と項目名のみ抽出しているのでわかりづらいですが、今回は - { Key: addtag, Value: dummy } の行だけが追加になったという結果です。 セキュリティグループへの追加更新用Webアプリ こちらはWebアプリなのですが、リモートワークが始まった時に 簡易的にセキュリティグループへ各メンバーの IPアドレス を追加したいと思って作成した機能です。 AWS を Ruby で操作することに慣れていたので、 Rails アプリも わりと簡単に作成することができました。 (この機能自体は とりあえずで作成したものです。 最近 他の施策で ほぼ不要になり 役目を終えました。) セキュリティグループへの追加更新用Webアプリ 最後に 今回は Ruby の スクリプト の話をしました。 Ruby の スクリプト って あまり書いている人がいないイメージがあるのですが、けっこう書きやすいのではないかと思います。 AWS で情報取得すると複雑なデータ構造で返ってくることが多いので シリアライズ が簡単にできる Ruby も選択肢に入れても良いかなと思いました。 ただ インフラエンジニアでは さらに書いている人が少ないと思うので、可読性に気を使ったり コメントで説明をしっかり書いたり 他の人の迷惑にならないようにした方が良さそうだなとは思います。(自戒を込めて) どなたかの参考になれれば幸いです。 こちらで Enigmo Advent Calendar 2022 は以上となります。 2023年もよろしくお願いします!
この記事は Enigmo Advent Calendar 2022 の23日目の記事です。 こんにちは、 エニグモ 嘉松です。 データ活用推進室というチームでリーダーをさせていただいています。 チームにはデータアナリスト3名、社内の業務システムを開発するGASエンジニア1名、そして私の計5名が所属しています。 目次 目次 エニグモを取り巻くIT環境 AppSheetとは AppSheetによるアプリの開発 AppSheet開発のフロー 1. データを用意 2. データを取り込み 3. アプリを作成 4. アプリをカスタマイズ 5. アプリを公開(デプロイ) 6. アプリをシェア AppSheet 触ってみた感想 良かった点 今回の検証では分からなかった点 不満・不安に思った点 最後に エニグモ を取り巻くIT環境 エニグモ では提供しているサービスが BUYMA という海外通販サイト( ECサイト )ということもあり、日常的な業務において多種多様なシステム、ITサービス、ツールを活用しています。 使用しているシステムを分類すると、 BUYMA の管理画面 BUYMA の業務を行う中心的なシステムです。 しっかりと要件を詰めた上でエンジニアによって開発されます。 アプリケーションソフト(ツール) ソフトウェア・ベンダーが提供しているツールやフリーで使用できるツール 例えば以下のようなツールがそれにあたります。 Gmail や Outlook などのメールソフト Google Spreadsheetや Excel などの 表計算 ソフト Google SlidesやPower Pointなどのプレゼンテーションツール 秀丸 やCodEditoerなどの テキストエディタ desknet’s や サイボウズ などの グループウェア Google Analytics やRTmetricsなどの アクセス解析 ツール LookerやTableau、RedashなどのBIツール など、など、など。 最近はブラウザ上で利用できるツールが多いですね。 (ちなみに上にあげたツール、私は謎に全部使ったことあります。年の功か?) お助けツール 管理画面ではカバーできず、アプリケーションソフトだけでもカバーできない領域。 人力で行っていた繰り返し作業を自動化(ボタンひとつで実行)するツールや、複数のアプリケーションソフトを組み合わせて行っていた作業を統合するツールなど。 代表的のものとしては Excel と VBA を組み合わせた業務効率化ツール。 サービスの改善や運用・保守で忙しいエンジニアに開発をお願いすることができず、現場のITに詳しいメンバーがネットで調べながら開発することも多い。(私がこれまで所属していた企業や一般論として。) ツールを使わず人力で行っていることも多く、その業務はとても生産性が低い。(日本の 労働生産性 が OECD 37加盟国中21位(2020年度)と低迷している1つの要因かとも密かに思っています。) ということで(?) エニグモ でもこの手のお助けツールの開発に力を入れています。 Google Spreadsheet + GASのように、 Google Workspace(旧 G Suite)や Google Cloud( GCP )といった Google サービスを上手いこと組み合わせてお助けツールを開発することが多いです。 Google サービスを活用する理由としては、 多くの機能(サービス)が揃っていること(下記に記載) それらが安価にかつ素早く(サーバの構築などが必要なく)利用できること そして各機能を Google Apps Scriptで連携することである程度のシステムを短期間に開発できること が挙げられます。 主な Google サービス Gmail (メール) Google Drive (ストレージ) Google Spreadsheet( 表計算 ) Google カレンダー(スケジュール管理) Google Form(アンケート) Google Map(地図) Google Apps Script( プログラミング言語 ) BigQuery(データベース(DWH)) ただ、これらの Google サービスを組み合わせたときに課題になるのがデータの入力です。 多くの場合は Google Spreadsheetにデータを入力しますが、 Google Spraeadsheetは自由すぎるので、行や列の追加や削除が容易に出来てしまいます。プログラム( Google Apps Script)ではどの列(例えばC列)には何の値(例えば商品ID)が入っている、データは何行目から入力される、といったことが決まっていることが前提として作られているので、自由に(勝手に)行や列を追加、削除されるとエラーになったりします。 もちろん、セルの保護(変更できないようにする)やシートの保護などで対応は出来なくはありませんが、Webアプリのように美しく入力を制御することが難しい。更に言えば、入力のチェック(バリデーション・チェック)も出来たら理想です。 ということで(??)目をつけたのがGoogle AppSheet。 前置きがとても長くなりましたが、以下ではGoogle AppSheetについてざっと紹介します。 AppSheetとは さっそく Wiki で調べてみると、 AppSheet is an application that provides a no-code development platform for application software, which allows users to create mobile, tablet , and web applications using data sources like Google Drive , DropBox , Office 365, and other cloud-based spreadsheet and database platforms. The platform can be utilized for a broad set of business use cases including project management, customer relationship management, field inspections, and personalized reporting. これを Google Translate(翻訳)で日本語に訳すと、 AppSheet は、アプリケーション ソフトウェア用のノーコード開発プラットフォームを提供するアプリケーションです。これにより、ユーザーは、 Google ドライブ 、 DropBox 、Office 365、およびその他の クラウド ベースの スプレッドシート およびデータベース プラットフォームなどのデータ ソースを使用して、モバイル、 タブレット 、および Web アプリケーションを作成できます。このプラットフォームは、プロジェクト管理、顧客関係管理、現場検査、パーソナライズされたレポートなど、幅広いビジネス ユース ケースに利用できます。 だいたい意味がわかる翻訳になりますね。(優秀!!) 要約すると、 ノーコードでアプリを開発できるプラットフォーム 「ノーコード」とは、コードを書かなくて良い、プログラミングが不要、ってことです。(一応補足) 多くのデータソースに対応( スプレッドシート やデータベースなど) マルチプラットフォーム (モバイル、 タブレット 、 Webブラウザ で使用できる) また、 AppSheet was acquired by Google in January 2020. というように、2020年に Google に買収され、 Google Cloudに組み込まれました。 「ノーコードでアプリを開発」といっても、どんなアプルでも作れる訳ではないでしょう。いかんせんノーコードですから。 では実際にアプリを作りながらAppSheetでの アプリ開発 について見ていきましょう。 AppSheetによるアプリの開発 まず、AppSheetの開発にはAppSheetの画面をブラウザで開く必要があります。 今回は以下のページから「無料トライアル」で試していきます。 cloud.google.com AppSheet TOPページ 無料トライアルなので出来ることに制限があります。 また、無料トライアルならではの設定が必要になります。 ただ、ざっくりと使用感を試すには十分かと思います。 AppSheet開発のフロー AppSheetでアプリを開発する流れは以下のとおりです。 データを用意 データを取り込み アプリを作成 アプリをカスタマイズ アプリを公開(デプロイ) アプリをシェア 1. データを用意 AppSheetはAppSheet自体にデータを保持するわけではなく、以下のようなアプリをデータの保存先(データ−ソース)として動作します。 (有料版ではAppSheet自体にデータを保持できるようになったようです) Google Sheets( Google スプレッドシート の正式名称ですね。) Microsoft Excel (Office 365や Dropbox など クラウド に保存されているファイルが対象) データーベース( Microsoft SQL Server 、 MySQL 、 PostgreSQL など) 今回は Google Sheetsに以下のようなデータを用意して進めていこうと思います。 id name category brand sale_start_date url pic データを用意 2. データを取り込み AppSheetの画面から用意したデータを取り込みます。 データをAppSheetに取り込み Google SheetsのデータがAppSheetに取り込まれました。 データが取り込まれました。 3. アプリを作成 取り込んだデータを指定してアプリを作成します。 アプリを作成 これで(これだけで)自動的にアプリが作成されます。 右に写っているのが スマホ 版のアプリのプレビュー画面です。 アプリが完成 4. アプリをカスタマイズ 自動で作成されたアプリをカスタマイズします。 取り込まれたデータのデータ型を変更します。 sale_start_date を Data に、 url を Url に、 pic を Image に変更してあげます。 項目のカスタマイズ プレビュー画面では、 sale_start_date が年月日の形式に、 url に右側にリンクボタンが、 pic が画像に変更されました。 項目のデータ方を変更 id の EDITABLE のチェックを外して変更を出来なくします。 idを変更不可に 5. アプリを公開(デプロイ) カスタマイズしたアプリを公開(デプロイ)、つまり利用できるようにします。 Not Deployed デプロイできるかをチェックしています。 ここでエラーがでたらエラーを修正してあげます。 無料トライアルでは、利用制限があるので、いくつかの設定を変更する必要があります。 デプロイチェック 6. アプリをシェア デプロイが無事に完了すると、利用するためのURLを取得できます。 LINK Editor Link このアプリを修正する画面へのURLです。 Browser Link Webブラウザ で利用するときのURLです。 Install Link スマホ で利用するときのURLです。 スマホ に Install Link を転送してクリックすると、最初(まだ「AppSheet」アプリを スマホ にインストールしていない場合)は、ストアに遷移するので「AppSheet」アプリをインストールします。 ちゃんと スマホ でも表示されました。 スマホ 画面 スマホ でデータを変更したら、データソースの スプレッドシート のデータも正しく変更されていました。 AppSheet 触ってみた感想 今回さらっと(約5時間くらい)AppSheetを使ってみました。 その中で感じた良い点と不満・不安に思った点、また今回の検証では分からなかった点を以下にあげます。 良かった点 スプレッドシート にデータを用意して読み込むだけでテータ定義が自動で作成される テーブル定義を1から設定する必要がないので、その手間が省ける 取り込んだデータの型は Image や Url など多くが用意されており、また変更も容易 データの型に応じて表示が自動で変わるので、UIの作成が必要ない データの参照、変更、追加の機能が自動で作成されるので、これも便利。 今回の検証では分からなかった点 データの定義やデータの表示については、多くのパラメータ(設定できる項目)があったが、どのような設定ができるのかまでは分からなかった。 デプロイの設定も多くの設定項目があったが、どのようなカスタマイズが可能なのかは分からなかった。 不満・不安に思った点 AppSheetは Google WorkspaceのEnterpriseプランで利用ができるが、Businessプラン(Business Starter、Business Standard、Business Plus)では利用できない。 Enterpriseプランを契約しておらず、AppSheetを利用する場合は、AppSheet個別の契約が必要となる。 MOST POPULAR のCoreプランで $10 USD/ user / month となかなかのお値段。 AppSheetの画面、ドキュメントが英語。 ドキュメントは Google Translateを利用すればある程度は解決するが、ハマッたときに困りそうな気もする。 Google がAppSheetにどこまでコミットしていくか不安。 2021年にサービス終了したApp Makerのような末路を辿らないか不安。 最後に では、AppSheetは「 Google サービスを組み合わせたときに課題になるのがデータの入力」を解決できるのか? 正直、出来ると思います。 AppSheetでアプリを作成して、その使い方を含めた業務マニュアルを用意すれば業務は回ると思います。 アプリを通して スプレッドシート のデータを触らせる(変更する)ことで、データの保護も出来るので、オペミスによるデータの消失なども防げると思います。 ネックはライセンスですね。多くの企業が契約している(であろう)Businessプランで利用できるようにしてほしい。 そうすればより多くのユーザが増えて、マニュアルの日本語化なども進むのではないかと思いました。 以上、読んでいただきありがとうございました。 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは、 エニグモ でデータアナリストをしている井原です。 この記事は Enigmo Advent Calendar 2022 の22日目の記事です。 本記事の概要 この記事は、データ分析案件の進め方に関して、課題の選定からゴールの具体化、分析完了に至るまで、私が今年実際に対応した事例でどのようなことに気をつけながら対応したのか、振り返ってみることを趣旨とした記事になります。 データ分析の案件は必ずしも具体的な目的やゴールがある時ばかりとは限りません。 漠然とした課題意識から始まり、 ヒアリ ングを重ねて具体的な目的やゴールを明確化していくプロセスが入ることがあります。 ことによると、初めから目的やゴールが明確化されている案件の方がレアケースかもしれません。 この分析以外のプロセスの進め方について、分析そのものと同等、あるいはそれ以上に難しいと感じることが多々あります。 しかし、分析の手法や アルゴリズム の解説記事などはよく見かける一方、プロセスの進め方についてはなかなか具体的な対応事例というものを知る機会が少ない印象があります。 プロセスの フレームワーク としてCRISP-DMといった概念は存在しており、それ自体は非常に有用かと思うのですが、概念であるため解説を読むとやや抽象的な印象もあります。 これは致し方ないところもあるとは思いまして、こういったプロセスの進め方は個別状況に応じて柔軟に対応を求められる場合が多く、これをすればよいという銀の弾はないということかなと思っています。 ただ、やはり、具体的な事例でプロセスの進め方について考えてみることも重要で、自分の中で糧にしていくため、自分のやってきたデータ分析のプロセスを振り返ってみること、それをこのような形でアウトプットしてみることは、一定の意味があるのではないかと思いますのでこの機会に振り返りをしてみたいと思います。 この記事ではデータ分析をどのようなプロセスを経て実行していったか、というテーマがメインになります。 具体的な分析手法などの説明は記載しておりませんので、ご了承ください。 解決したい課題を確認する まず初めに実施したことは、そもそもどのような課題を解決することが有益であるかを確認することでした。 状況を軽く説明すると、私は昨年 エニグモ にジョインしたばかりということもあり、業務や課題の理解はまだまだ浅い状態でした。 反対に、今回自分が担当したチームにメインでデータアナリストが アサイ ンされたのも自分が初めてということもあり、ビジネス側でもデータ分析でどのようなことが出来るのか、おそらくイメージが漠然としていたであろうとも思っていました。 そのため、まずはざっくばらんに雑談という名目で、各チームメンバーに ヒアリ ングをさせてもらいました。 この時気を付けたのはデータ分析ということにこだわらず、普段どのような業務を行っていて、メインで対応していることはどのようなことか、困っていることは何か、という相手の業務理解に集中したことです。 これは、イメージが漠然としている中でデータ分析の話に寄せてしまうと、本質的な課題が出づらいのではないかと思ってのことで、話が発散してもよいのでまずは自分の理解を高めようと思ってのことでした。 一人ひとり取れた時間は短いものでしたので、完全に理解ができたというものではなかったですが、それでも、普段チームメンバーが困っている課題をある程度把握することができました。 全ての課題に着手することは出来ないので、雑談の後で見えてきた課題に対してデータ分析でサポート出来そうなことを羅列し、ビジネスサイド側の部長と優先度の確認を行うという作業を行いました。 ちなみに、イメージとして ヒアリ ングした結果を以下のような表にまとめて会話を行いました。 課題 ヒアリ ング後のまとめシート(イメージ) このプロセスを経ていくつか対応するべきテーマを絞り込み、次の ユースケース の具体化に進むこととなりました。 ユースケース を具体化する 対応するテーマは決まりましたが、具体性に欠ける部分がありましたので、ビジネスの ユースケース を具体化していくフェーズに入ります。 ※対応したテーマはいくつかありますが、ここでは「需要予測による売れ筋商品の出品強化」のテーマを例に記載します。 ここでは、実際にビジネスの対応をするチームメンバーと週次の MTG で具体的な内容をすり合わせていきました。 ビジネスでやりたいこととデータ分析のアウトプットに齟齬が生じてしまうと、有用な分析が出来なくなってしまいますので、これはかなり重要なポイントで、念入りに細かく認識合わせをしていくことが肝になります。 一つ一つ詳細に書くことはしませんが、例として具体的に確認した項目を羅列すると、 需要予測のデータをどのように活用するか? 対象としたいカテゴリやブランドはどこか? 商品はどの程度の粒度で確認したいか?(カテゴリ、ブランド、SKUなど) 予測を行いたい期間はいつからいつまでか? 一回きりの対応か?定常的にやりたいか? スケジュール感 分析結果のアウトプットイメージ などの要素があります。 これらは一つずつきれいに決まっていったわけではなく、何度か会話の行き来を繰り返し、徐々にお互いの認識をすり合わせていく流れになりました。 ここで自分が気を付けたこととしては、業務理解が浅いなりにある程度の仮説をもって MTG に臨むようにしたことです。 一例として、最初、自分の中で需要予測の ユースケース は以下のような想定をしていました。 日次で確認する 予測日から30日程度先の予測ができる 需要予測と在庫量(出品商品数)を比較して、供給不足になりそうな商品をピックアップして出品促進(※)する ※ BUYMA は商品の出品もユーザーにしていただくCtoCのサービスですので、 BUYMA で商品を 仕入 れて出品するということは基本的になく、PSさん(出品者)に出品募集を行うというアクションをとります。 しかし、話をする中でまとまっていった ユースケース は以下のようなものでした。 季節ものの商品の 仕入 れ時期を狙って、メールで出品促進を行いたい 特に会話をしていた時期(6月末~7月初旬)は、アウターの 仕入 れが8月ごろから始まるので、8月に一度出品促進メールを送り、初動を見たうえで9月に再度メールを送りたい。 アウターの売れる時期である9月~翌年1月までの需要(どのブランドモデルが特に売れるのか?)が知りたい。 将来的には、季節に応じたカテゴリの需要を定期的に取得して、出品促進メールを送れるようにしたい。 日次での確認や予測期間が30日程度という私の想定は間違っていたわけですが、それ自体は問題ではなく、こういうイメージで問題がないか?ここが分からないのだがどうなるか?と一つずつ確認を進めていったことで、 ユースケース のイメージの齟齬がなくなっていきました。 分析ゴールの設計 ここまでビジネスのイメージが明確になると、分析ゴールは大分設計しやすくなるかと思います。 今回の場合は、 需要予測が業務利用可能なレベルの精度で予測可能か?という検証結果 今期の需要予測結果 という二つのアウトプットが必要になります。 一つ目に関して、データサイエンスに関わったことのある方ならご存知だと思いますが、予測タスクはデータの質などによって必ずしもうまくいくとは限らないというリスクがあります。 そのため、今回も作成するモデルの精度が妥当であるか否か?という検証を行ったうえで、問題がなければ二つ目のアウトプットを出すというステップを踏む必要がありました。 このリスクについてビジネスサイドにも理解をしてもらったうえで、最悪うまくいかなかった場合、ビジネスサイドである程度売れ筋の商品はナレッジとして押さえていること、そのナレッジだけでも出品促進メールの作成・配信には支障がないことの確認はしていました。 もう少し細かい話をすると、人のナレッジだけでは限界もあるだろうという前提で、この需要予測の結果を取り入れることで、より有用な出品促進が行えるとビジネスサイドが思えるかという定性的観点の検証もあわせて確認する必要がありました。 定性的観点はアウトプット結果を見てもらうことで判断するとして、 定量 的に需要予測が業務利用可能なレベルの精度とはどういうものか?という定義をする必要がありました。 ここでは ユースケース を踏まえ、 アウターのブランドモデルにおいて、売上件数上位100件を予測できること をメインの検証観点としました。 また、ある程度前年に比べて伸びるか否かという視点も含まれるとよいという意見があり、副次的ではありますが、 前年比100%、120%、150%、程度の粒度で伸長率の予測が可能か? という点も検証することとしました。 これらの検証観点について、実際に昨年度のデータでどのような結果になるかを検証することとしました。 需要予測タスクではある期間に売れる商品件数を予測しますが、今回の目的は売れそうな商品をピックアップして出品促進を行うというものですので、必要な在庫数の考慮などは不要であり、売上件数の予測精度は(全く見ないということはないですが、)重要視しないことをビジネスサイドと合意しました。 やや余談ですが、モデルの精度をあげようとするには検証期間が短かったことや取得できるデータが限られることから、売上件数の予測精度については不安があったので、ここでハードルを下げられたことは大分ありがたく、この後の結果を見ても期待値コン トロール は大事だなと感じるところでした。 結果 分析のゴールを合意出来たら、最適な予測が出せるモデルの作成を目指し、 アルゴリズム やパラメータの変更、データ量(期間や特徴量)の増減などを時間の許す範囲で試しました。 ちなみに、ベースラインとして単純な直近1ヶ月の売上件数の昨年比をそのまま予測期間にも当てはめる、というルールベースの手法も試したりしています(意外と精度は悪くなかったりしました)。 最終的な結果としては、状態空間モデルを使用した予測がもっとも精度が高く、売上上位100件に入るブランドモデルのうち80件のブランドモデルを予測することが出来ていました。 伸長率の予測は細かく見ると微妙な部分もありましたが、大雑把に昨年から伸びそうか否か程度の予測は悪くなく、ここは副次的な検証観点でもあるため許容としました。 なお、売上件数の予測精度もめちゃくちゃな予測結果でも問題なので確認をしたところ、予測結果が描く期間中の週次売上件数と実績の比較結果では、大雑把に秋~冬にかけて売上件数が伸びていく予測グラフが作成出来ており(下記グラフ参照)、ビジネスサイドの定性評価も踏まえて総合的に業務利用可能であるとの判断に至りました。 あるブランドモデルの実績(青線)と予測結果(オレンジ線) まとめ 私が今年度対応してきた需要予測タスクの企画の始まり~予測モデルの検証まで、簡単にですが振り返ってきました。 この後、ビジネスサイドに今期の需要予測結果を共有し出品促進メールを配信した結果、配信後に対象商品の出品数は増加し、PSさんからも好意的な反響をいただいたとのフィードバックをいただいております。 振り返ってみて、改めて ディレクション やコミュニケーションの大切さを感じることとなりました。 大きな齟齬もなく、また、よくある分析の結果が放置されることもなく、ビジネスサイドのアクションに繋がったのは、時間はかかりながらも(かけたからこそ?)相互理解を進め適切な分析を行えたからではないかと考えています。 細かくは書いていませんが、今回拙いながらプロジェクトマネジメントの知識なども要所で意識しながら案件を進めていきました。 データ分析の手法や アルゴリズム などの勉強はもちろん重要であると思いつつ、同時にプロジェクトマネジメントやCRISP-DMなどプロジェクトを前に進めるための知識もデータアナリストとして磨いていきたいと思う1年でした。 今回の記事は以上になります。 最後まで読んでいただき、ありがとうございました。 明日の記事の担当はデータアナリストチームマネージャーの嘉松さんです。お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは。データエンジニアの谷元です。 この記事は Enigmo Advent Calendar 2022 の21日目の記事です。 目次 はじめに どうしてデータ基盤を最適化する必要があるの? どうしたら改善できるの? 現状のデータ基盤のおさらい 主要なBUYMA基幹データの最新ビューに着目してみる 最新ビューをどう変更するの? システム概要としてはどんな感じ? この方針で思ったこと BQ履歴テーブルの作成方針だけど 本当にその方法で改善するの? 運用保守する上で気になっていたこと 見込み効果はどうなの? 実装する上で意識したところ BQ履歴テーブル作成前提となるDAG依存関係 本番データを使った確認期間をできるだけ長めにとろう データ品質担保はどうしよっかな 今回は見送ったデータ品質対応 既存の手動実行スクリプトをAirflowに移植しようと思ったら そろそろリリース後の話をしよう 効果はどうだったの? BQクエリコストとそのクエリ数を月次単位で比較してみる(課金対象のみ) 効果測定するにあたって BQクエリ平均実行時間と処理量を月次単位で比較してみる(課金対象のみ) とあるLookerダッシュボード内部のクエリ実行時間を日次で見てみる 過去のとある時点のデータを遡ってみる こんな感じのクエリかな タイムリープして思ったこと Looker上でもexploreを作成してタイムリープしてみた 所感 最後に はじめに 皆さんどのようにお過ごしでしょうか。 私は昨年に猫ちゃんの可愛さに目覚めてしまい、リモートワーク中も近くで愛猫に見守られる生活を過ごしております。 今年、ねこ検定初級に合格し、愛猫と仲良くなれた気がします🐱 さて、データ基盤の開発運用保守やBI上でのデータ整備などを対応をしてまして、 今回は "データ基盤の処理最適化によるBigQueryコスト削減" の話をさせていただきたいと思います。 どうしてデータ基盤を最適化する必要があるの? エニグモ は全社的にデータを活用する文化が強く、誰でもデータ活用がしやすいように様々なデータをBigQuery(以下、BQ)に自動集約しております。 規模でいうとデータ基盤上のクエリスキャン量は ペタバイト [PB]規模/月であり、 前年同月比 約300%での増加傾向にあります。 しかし、データ活用が進むにつれて下記の課題を感じていました。 昨今の円安事情も重なり、BQクエリコストが大幅に増加傾向にある データ参照が遅く、シームレスに分析やドリルダウンがしづらい (BIや アドホック クエリ) 思考の妨げにつながってしまい、分析機会の損失につながっていると感じる 連携元で履歴が残っていないテーブルの場合、複数のテーブルを用いた過去のとある時点のデータが遡りにくい さらに下記の現状もあり、データ基盤の最適化を進めようと思いました。 基幹データでも数千万〜数億レコードあるテーブルが複数存在する 現状の仕組みでは時間経過と共にBQクエリスキャン量も増加してしまう どうしたら改善できるの? 現状のデータ基盤のおさらい バッチ処理 でBQ連携しており、データ鮮度は原則、最大1時間遅延です。 BQ連携時は差分更新分を連携し、それらのデータから重複や物理削除などを考慮したビュー(以下、最新ビュー)で連携元と同じ最新状態のデータを再現してます。 参考: Apache Airflow で実現するSQL ServerからBigQueryへのデータ同期 主要な BUYMA 基幹データの最新ビューに着目してみる 汎用的に全ての最新ビューを最適化する方針にしました。理由は下記となります。 BQ連携している基幹データだけでも200テーブル以上あり、今後も含めてテーブルの利用状況はわからない 現状のアクセス内容を調査して個々に性能改善するとなると テーブル数や処理量も多い 調査や対応方法を考えるのも大変だし、運用保守負担も大きそう ビュー内部の改善なので、BQ利用者への影響を考慮する必要がなく、サイレントでリリースできるのも良さそう 最新ビューをどう変更するの? 最新ビューは差分更新データから再現していたため、不要なスキャンが多すぎる状態でした。 なので、基幹DB全体を定期的にテーブル化し、最新ビューでそのテーブルを利用してスキャン量を改善しようと考えました。 最新ビューの変更方針は以下のとおりです。 現状. 月次差分+時間次差分のBQデータを組み合わせる 提案. 日次全件(※)+時間次差分のBQデータを組み合わせる ※ 月次差分+時間次差分でテーブル化、AM0:00固定、以下、BQ履歴テーブルと呼ぶ システム概要としてはどんな感じ? 図にすると下記のようになります。 尚、白色の箇所は既にあり、今回新規に対応したのは黄色の箇所になります。 データ基盤のシステム概要 この方針で思ったこと リアルタイム連携が実現できた場合でもBQに入れる処理の置換で済み移行もスムーズそう 基幹DB全体をBQ履歴テーブルとして残すことで、過去に遡ってデータ活用しやすそう BQなのでデータ量をあまり気にしなくて良いメリットを活かせる BQ履歴テーブルの作成方針だけど 既にBQ上に取得済みの更新差分データを用いることで後からでも過去の任意時点まで遡ってデータを再現できるのも良さそう 基幹DBが古いため、できるだけ影響を与えないようにしたかった 尚、BQのマテビューも少し検討したのですが現状では利用制約に引っかかり見送りました。 本当にその方法で改善するの? 仕組みからいうと性能は改善するとは思ってましたが、以下の懸念がありました。 最新ビューがどの程度使われているのかがわからなかった BQ履歴テーブル作成など、今回の対応により増加するBQクエリコストもある 運用保守する上で気になっていたこと データ基盤の仕組みが現状より複雑になり トラブルシューティング が大変になる BQ履歴テーブルが最新ビューに組み込まれるため、よりデータ品質に注意を払う必要あり データ基盤の運用保守で新規テーブル取り込み時は一部手動運用している 本対応後はオペレーションがより複雑化する 手動 スクリプト 実行や設定ファイル修正、データの初期移行など 愛猫の可愛い顔をみながらだとオペミスするかもしれない 社内外でBQデータが既に多方面で活用されている 対応後のデータ不備は影響が大きそう データの復旧も大変そう 見込み効果はどうなの? あまり時間をかけたくなかったのもあり、下記の確認に留めました。 現状のBQクエリコスト確認 主要テーブルを用いた SQL 単体での効果検証 改善版の最新ビューを用いた効果検証では スキャン量と実行時間共に1/2程度削減 を確認できました。 1/5や1/8程度改善しているケースもあり想定より効果があるのかもと思いました。 尚、定期的なBQ利用状況の効果測定はLooker上のMarketplaceでBQ利用状況が簡単に見れたため、そちらを利用しました。慣れてる方でしたら1日で作成できるかと思います。 実装する上で意識したところ 実際やってみるとたくさんあった気がするのですが、パッと思い出した話をしてみます。 BQ履歴テーブル作成前提となるDAG依存関係 本番データの確認期間をできるだけ長めにとろう 手動 スクリプト をAirflowに移植しようと思ったら データ品質担保はどうしよっかな BQ履歴テーブル作成前提となるDAG依存関係 BQ履歴テーブルを作成開始するにあたり、 その抽出するクエリ内部で参照されているテーブルで必要な情報が揃っている必要があります。 最新ビューは時間軸の異なるデータを複数組み合わせて物理削除も考慮してるため、テーブル毎に依存先DAGや時間軸、依存先のテーブル数も異なります。 これらの情報を設定情報として事前に定義した情報から自動で構成しています。 図にすると下記となります。 左がExternalTaskSensor、右がBigQueryExecuteQueryOperatorとなり、 右の数だけテーブルがあるようなイメージです。 参考: DAG間の依存の話 DAG依存関係 本番データを使った確認期間をできるだけ長めにとろう 本番データでの確認期間を少しでも長めに取るため、 本番影響がないよう部分的に先行リリースを繰り返しました。 そうすることで、本番データで確認を進めつつ開発も進められますし、 別件の対応も並行して進めやすくすることも可能でした。 確認期間は2,3週間ほど動かしてエラー検知されなければ大丈夫だろうぐらいで考えてました。 データ品質担保はどうしよっかな 経験上あまり手を抜かない方が良いと考え、バリデーションを入れました。 現状では気になる所だけにしておき、今後必要に応じて増やしていけば良いと考えました。 主要テーブルの意味合いチェック 新旧の最新ビューで件数比較 など 尚、BigQueryCheckOperatorがシンプルで汎用性が高かったので採用しています。 開発途中でも想定外にエラー検知をしたり、今後の運用でもデータ品質の監視にもなるので、やはり大事だと感じました。 今回は見送ったデータ品質対応 昨今の技術進歩だともっと賢くやる方法があるはずだ!と調べてたら、 Great Expectations というのがありました。 今回、時間の兼ね合いで検証はできなかったのですが、BQテーブルを自動診断してデータの品質診断結果までファイル出力してくれるようです。 GreatExpectationsOperatorもあるようですし、機会があれば触ってみようかなと思います。 既存の手動実行 スクリプト をAirflowに移植しようと思ったら 最新ビューには個人情報列あり/なしの2つ存在しており、今までは新規テーブル追加時のオペレーション時は ruby スクリプト を用いてローカルから手動実行して作成してました。 バリデーションで新旧の最新ビューを比較するのに必要でしたし、手動でやるのも手間でしたので、 これを気にAirflow( python )に移植して自動で実行しようと考えました。 対応途中で、よくみると内部でgsutilコマンド使ってることに気づき、 "現行のAirflow環境だとgsutilコマンド( CLI )が入ってなさそうやから使えへんやん!" となりました。 目標リリース期限の2週間前を切っており、効果測定やこのブログを書くタイミングのこともあったので期限をずらしたくなかったのです。 CLI 入れるとなると「あれ、間に合うかな。。後回しにしすぎた」となりました(汗 ただ、よく考えると全く同じ方法でやらなくてもいいかと頭を切り替え、 BQのINFORMATION_SCHEMAやBigQueryHookを使う方法で対応を進めて乗り切りました。 蓋開けたら CLI が移行先で使えなくて、対応期限も近づいてたので慌てたという話ですねw そろそろリリース後の話をしよう 無事に予定通り、10月末にリリースできまして、その後の話をしたいと思います。 効果はどうだったの? BQクエリコストとそのクエリ数を月次単位で比較してみる(課金対象のみ) BQクエリコストですが米ドル比較で "前月比 約25%削減" となりました。 BQクエリスキャン量だとPB( ペタバイト )レベルでの削減です。 桁が大きすぎてよくわからないですね.. 月別BQクエリコストとクエリ数 効果測定するにあたって もちろん比較月で使われ方が変更になったり増減した分もある エニグモ 内のほぼ全てのプロジェクトを含んだ数値である つまり、今回改善した最新ビュー以外の数値も含んでいる クエリ数ですが、BQ履歴テーブル自体は7月には動かしていた 10月からバリデーションも入れて先行リリースしてた影響もありクエリ数が増えてそう 約14万回は今回追加した処理が原因そう BQクエリ平均実行時間と処理量を月次単位で比較してみる(課金対象のみ) BQクエリ平均実行時間ですが、 "前月比 約40%削減" されておりました。 最新ビューが絡まないクエリも多数あると思うのですが、 単純な平均でこの数値は思ってた以上に効果があったのかもしれません。 後、10月時点で少し下がってるのはなんでだろう。 先行リリースでバリデーションとかで軽いクエリを流し始めた影響か、 または重たいのが別件で改善されたのですかね。 月別BQクエリ平均実行時間 とあるLooker ダッシュ ボード内部のクエリ実行時間を日次で見てみる LookerではSystem Activity が用意されているので、そちらで確認してみました。 やはり半分程度の性能改善がされてそうです。 私も ダッシュ ボードをいくつか触ってみましたが、 体感でも「お、ちょっと早くなったな」とわかるぐらいでした。 とあるLooker ダッシュ ボードの日別クエリ実行時間 過去のとある時点のデータを遡ってみる こんな感じのクエリかな 下記のようにすると、過去のとある時点のデータ参照もできそうでした。 本来のテーブルリレーションだけ意識すれば良いので楽ですね。 DECLARE target_date string; SET target_date = ' 20221201 ' ; WITH _table_a AS ( SELECT _TABLE_SUFFIX AS tabledate, id, value, times FROM table_a__* WHERE target_date <= _TABLE_SUFFIX -- 見たい履歴の期間を指定 ), _table_b AS ( SELECT _TABLE_SUFFIX AS tabledate, id, value2 FROM table_b__* WHERE target_date <= _TABLE_SUFFIX -- 見たい履歴の期間を指定 ) SELECT ta.tabledate, ta.id, ta.value, ta.times, tb.value2 FROM _table_a ta -- BQ履歴テーブル INNER JOIN _table_b tb -- BQ履歴テーブル ON ta.id = tb.id -- 本来のテーブル結合条件 AND ta.tabledate = tb.tabledate -- _TABLE_SUFFIX同士で結合する ORDER BY ta.tabledate, ta.id タイムリープ して思ったこと 見たい履歴の期間を大きく取りすぎると利用するテーブルによってはデータの参照が遅いですし、やはりスキャン量がやばいことになりそうです。 また、日次のAM0:00時点のみしかBQ履歴テーブルを残してないのもありますので、 傾向を掴むような分析や他に見る参照する方法がない時などの利用用途で向いてそうです。 Looker上でもexploreを作成して タイムリープ してみた やはり少し重いですね... こんな感じで使うのが良さそうですかね。 他のexploreで探索的に分析しつつ 過去のあの時のデータはどうだったんだろうと気になる 今回作成したBQ履歴テーブルを用いたexploreで確認する 定期的に確認しそうな場合は ダッシュ ボード化して性能改善もする 所感 全体を通して概ね計画通りに進められ大きな問題も発生せず、ほっとしました。 懸念してたBQ履歴作成分などで増えるコストもありましたが、それ以上に減少してくれたので良かったです。 スキャン量も右肩上がりだったので、実施タイミングも良かったのかなと思います。 また、この機会に手動で実施していた箇所を少し自動化できたのも良かったです。 ただ、今回作成したオペレータ数が約数千あって、AirflowのWebUI画面でログ表示しようとしたら少し重くて開きづらくなってました(ぇ) 今後、データ基盤の活用が進むほど、今回対応したコスト削減効果も増えると思います。 最後に データ基盤の開発運用保守に携われている方に少しでも参考になればと思い、このテーマで記事を書いてみました。本記事を通して少しでもイメージを掴めて頂けますと幸いです。 また、お忙しい中、設計の相談やコードレビューをして頂けた上司には感謝しております。 私からは以上となります。最後までお読み頂きありがとうございました。 明日の記事の担当はデータアナリストの井原さんです。お楽しみに。 株式会社 エニグモ 正社員の求人一覧 hrmos.co
こんにちは、 iOS エンジニア の 池田 です。 この記事は Enigmo Advent Calendar 2022 の 20日 目の記事です。 はじめに 2018年の WWDC で発表されたCreateMLですが、発表当初 Xcode を用いたモデル作成など Mac での利用に限定されていました。 ですが最近では iOS 、iPadOS、tvOSでも利用できるようになっており、オンデ バイス での 機械学習 モデル作成ができます。 (利用可能OSは iOS15.0以降、iPadOS15.0以降、tvOS16.0以降です。) この記事では iOS を用いたオンデ バイス での 機械学習 モデル作成と、作成したモデルの利用をしてみようと思います。 MLStyleTransfer を利用してモデル作成を行い、画像の画風変換をしてみます。 コード内に見やすさのため Forced Unwrapping してる箇所がありますが、実装時はguard文等を使って適宜書き換える想定をしています。 機械学習 モデルの作成 モデルの作成は以下のようなコードで作成できます。コード量も多くなく、簡単に 機械学習 のモデル作成ができます。 必要ライブラリの読み込み import CreateML import CoreML import Combine 学習用のデータ、パラメータの準備 let styleUrl : URL // スタイル画像のURL let contentUrl : URL // 学習用コンテンツ画像のディレクトリURL let data = MLStyleTransfer.DataSource.images(styleImage : styleUrl , contentDirectory : contentUrl ) let sessionParameters = MLTrainingSessionParameters(sessionDirectory : sessionUrl ) 学習実行 let job = try MLStyleTransfer.train(trainingData : data , sessionParameters : sessionParameters ) 学習結果の待ち受けとモデルの保存 let writeToUrl : URL // モデルの書き込み先URL var mlModel : MLModel // 作成した機械学習モデル job.result.sink { result in switch result { case .failure( let error ) : // エラー時の処理 case .finished : // 完了後の処理 } receiveValue : { model in do { try model.write(to : writeToUrl ) let compiledUrl = try MLModel.compileModel(at : writeToUrl ) mlModel = try MLModel(contentsOf : compiledUrl ) } catch { // エラー時の処理 } } .store( in : & cancellables) モデル作成コード実装時の注意事項 シミュレータのビルドでは動かないため、実機ビルドでビルドする必要があります。 シミュレータでビルドしようとすると、CreateMLの フレームワーク 自体が見つからず以下エラーが出ます。 No such module 'CreateML' 機械学習 モデルの利用 上記で作成したモデルは以下のように利用できます。 画風変換対象のUIImageを用意し、出力をUIImageとして利用できるように実装してみます。 必要ライブラリの読み込み import CoreML import Vision import VideoToolbox 入力値の準備 let inputImage : UIImage // 画風変換の適応対象画像 let cgImage = inputImage.cgImage let imageConstraint = mlModel.modelDescription.inputDescriptionsByName[ "image" ]?.imageConstraint let featureValue = try MLFeatureValue(cgImage : cgImage! , constraint : imageConstraint! ) let featureProvider = try MLDictionaryFeatureProvider(dictionary : [ "image": featureValue ] ) 画風変換後の出力データ取り出し let mlModel : MLModel // 作成した機械学習モデル let stylizedImage = try mlModel.prediction(from : featureProvider ) let imgBuffer = stylizedImage.featureValue( for : "stylizedImage" )?.imageBufferValue UIImageに変換 var cgImageForConvert : CGImage? VTCreateCGImageFromCVPixelBuffer(imgBuffer ! , options : nil , imageOut : & cgImageForConvert) let stylizedUIImage = UIImage(cgImage : cgImageForConvert! , scale : 1.0 , orientation : inputImage.imageOrientation ) 結果の確認 変換結果 変換対象の画像に スタイル画 像の画風を適応すると、こういった結果になるようです。 今回はデフォルトの設定をそのまま利用しましたが、モデル作成時にIterations、Strength、Densityなどのパラメータを調整することもできるので、そちらを変更するとまた違った出力を出すことができます。 おわりに モデルの作成・利用が少ないコード量で簡単に実現できました。 この記事では画風変換を扱ったこともあり利用ケースは多くないかもしれませんが、Classfier や Regressor も利用できるものがあるため様々な展開が考えられそうです。 スマートフォン のデ バイス 上で動くので、データをクローズドな状態で管理でき、WebAPIに投げる必要もないので安全に扱うことができるのが大きなメリットだと思います。 反面の懸念事項としては、デ バイス の処理能力に依存するので、快適な利用を考えるとある程度 ユースケース に制限がかかってくるかもしれません。 (今回はチューニングなどは特に加えてないので、 iPhone 11 Pro 端末でモデル作成時に30分ほど時間を要しています。) とはいえ簡単に実装でき、 機械学習 のモデル作成も利用もオンデ バイス で完結して動く、とても強力なFrameworkだと思います。直近の WWDC では Create ML Components が発表されていたり、 iOS でも 機械学習 関連はさらに進化を続けているのでこれからも楽しみです。 明日の記事の担当はデータエンジニアの谷元さんです。お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co
この記事は Enigmo Advent Calendar 2022 の 19 日目の記事です。 こんにちは、Webエンジニアの平井です。普段はSELLチームに所属していて BUYMA における出品者側の機能開発を担当しています。 今回は、最近リリースしたカタログシステムをサーバレス アーキテクチャ で開発したので利用した技術や学びについて書きたいと思います。 目次 目次 サーバレスアーキテクチャ メリット デメリット カタログシステムとは システム設計 技術スタック サーバレスフレームワーク API カタログデータ新規作成、更新処理 メリット デメリット 学び 良かった点 悪かった点 サーバレス アーキテクチャ そもそもサーバレス アーキテクチャ とは何でしょうか。人によって解釈は異なるかと思いますが、私はイベント駆動型のプログラム実行環境を利用してアプリケーションを開発する アーキテクチャ だと理解しています。システムを開発していく上でサーバーを意識する必要が無いという特徴があります。ざっくりメリットとデメリットは以下が挙げられます。 メリット サーバーを構築する手間が省けて、開発者がアプリケーションの開発に専念できる。 リソースの利用料金はコードを実行した時間に対して課金される。アイドル時間は課金されない。 デメリット 利用できる言語が限られている。 実行時間制限 Lambdaだと最大15分 カタログシステムとは 次に今回開発したカタログシステムについて説明します。カタログシステムは BUYMA のカタログ出品機能のためのシステムです。 カタログ出品機能は、出品者に対して BUYMA 側で用意したカタログを提供することで、出品者の出品作業の効率化、高品質な画像の提供を目的としています。 カタログ出品の大まかな流れは以下になります。 撮影チームが商品を撮影、画像を クラウド にアップロード オペレーションチームが色名、型番の確認、サイズの計測を実施 1,2の情報をカタログシステムの API 経由でデータ保存 4で保存したデータを API で BUYMA 側に提供 BUYMA 上のカタログ出品画面から出品者が適当なカタログを選択して、出品 以上の流れの3,4の部分(カタログデータの新規作成/更新、提供)をカタログシステムが担当していて、弊社の クラウド サービス利用実績より AWS 上に構築しました。 システム設計 詳細は省略していますが、以下が アーキテクチャ 図になります。 カタログデータ新規作成/更新は Google App Scriptから API 経由で実行され、図の上部が該当部分です。 カタログデータ提供も API 経由で実現しています。 技術スタック 次にカタログシステムの開発に利用した技術、主に AWS のサービスについて紹介します。 サーバレス フレームワーク まず、サーバレス フレームワーク については SAM を利用しました。 サーバレス フレームワーク とはサーバレスアプリケーションを構築する上でInfrastructure as Codeを実現するためのものです。今回利用したSAMの特徴は以下になります。 サーバレスアプリケーション構築用の オープンソース フレームワーク YAML ファイルでリソース管理 CloudFormation構文を拡張してサーバレスアプリケーションの構築が簡単になっている サーバレス フレームワーク にはSAMを含めて代表的な3つのサービスがあり、それぞれのメリット・デメリットは以下だと考えています。 SAM メリット CloudFormationを抽象化したものなので, CloudFormationを知っていたら書きやすい。 デメリット 構文が若干冗長 serverless メリット AWS , GCP , Azureで利用できる。 デメリット serverless独自の構文を覚える必要がある。 AWS CDK デメリット ブログラミング言語で設定を記載できるが、可読性が yaml に比べると低い ローカルでのテスト実行には、SAMを使う必要がある。 やり方 今回、開発チームにCloudFormationの経験があるエンジニアが居た点、マルチ クラウド に対応する必要がない点、ローカル環境での実行が簡単な点より SAM を選択しました。 API API は一般的な API Gateway とLambdaの構成です。工夫した点としては API Gateway とSwaggerの yaml ファイルを連携して API 定義するようにしました。 以下のようにSwaggerで定義した yaml ファイルのパスを指定することで連携できます。Swaggerで API 定義するようにしたことで API を追加するためには API 定義 yaml ファイルを更新する必要があるため、 API 追加によるドキュメントの更新漏れを防ぐことができます。 Resources : Api : Type : AWS::Serverless::Api Properties : DefinitionBody : 'Fn::Transform' : Name : 'AWS::Include' Parameters : Location : api.yaml カタログデータ新規作成、更新処理 カタログデータの新規作成、更新処理部分には AWS Step Functions を利用し、Lambdaをワークフロー的に実行しています。 AWS Step Functionsはワークフロー管理サービスで json でワークフローを定義します。 AWS Step Functionsを導入してみて感じたメリット、デメリットは以下になります。 メリット Step Functionsの GUI がリッチである。 ワークフローの全体像、各タスクの進行状況、ログ、成功状況がわかりやすい。 Lambdaを分割することで各Lambdaの凝集度が高まり、メンテナンス性があがる。 各Lambdaのリトライ設定が簡単。 デメリット 途中のLambdaで失敗した際のデータ整合性を考慮する必要がある。 個人的には GUI がリッチな点が特に好きで、データ作成、更新処理に何か不具合がある際は基本的にこの GUI から デバッグ を開始するため、 デバッグ が効率的になるようにタスク成功時の出力内容や失敗時の例外メッセージの内容を工夫して実装しました。 以下が処理詳細画面で、左のアイコンをクリックすることで各タスクのInput, Outputも確認できます。 学び 最後に開発して得た学びについて書きたいと思います。まず、サーバレス アーキテクチャ で開発して体感した良かった点、悪かった点は以下になります。 良かった点 開発者だけで構築できるリソースが多く、管理が不要なので開発体験が良かった。 AWS を利用した過去の ユースケース が多く、参考にする情報に困らなかった。 公式ドキュメント Serverless Land 悪かった点 コードの共 通化 が難しい Lambda Layer を使えば可能そう。 今回の場合各Lambdaに共通するモデル定義は共 通化 したかった。 また、今回Lambdaは Python で開発しましたが開発初期は普段利用している Ruby との言語的違いが原因で開発に時間がかかりました。 Lambdaの内 58%がPythonを利用 しているという情報を知り、メインの潮流に乗ったほうが良いと判断して Python を選択しましたが、 特に Python を利用して良かった点が無かったのでスケジュールがかなりタイトな場合は普段慣れている言語を使ってもよいと思いました。 以上になります。 明日の記事の担当はエンジニアの池田さんです。お楽しみに 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは、UIUXデザイナーの和田です。 この記事は Enigmo Advent Calendar 2022 の18日目の記事です! 弊社では、 BUYMA のサービスやアプリ・WebサイトのUIUXをよりよくしていくことを目的に、 「より深くユーザーを理解して」「ユーザーにとって価値のある体験」を届けていくために、UXリサーチに基づいた改善に力を入れています。 今回は、 BUYMA の顧客理解のために進めているUXリサーチの取り組みについてご紹介します。 【1】ユーザーセグメント分類|User Segmentation BUYMA の会員について、RFMの指標をベースに「 利用頻度軸 (Recency&Frequency)」「 価格志向軸 (Monetary)」「 年代軸 」 からユーザーセグメントの分類を進めています。 【各セグメントのボリューム】を把握して、 主要なセグメントにおけるユーザーの購買傾向や利用傾向 について、 視覚的に捉えられるようにLookerのツール整備をデータアナリストとUIUXデザイナーが協働で実施しています。 利用頻度軸(Recency&Frequency) 全体の購買傾向から適切な 閾値 を検討して、「利用頻度」と「直近の利用傾向」からセグメントの分類を進めています。 価格志向軸(Monetary) ユーザーにおける純粋な生涯累計購入金額で分類するのではなく、「どのくらいの価格帯のアイテムを中心に購入しているか?」「どんな価格帯のアイテムに興味関心が高いか?」という観点で、F0ユーザーやF1-2といった利用歴の浅いユーザーについても価格(購買行動)に関する志向を把握できるように分類を進めています。 年代軸 年代については、生活スタイルや行動特性の異なりを考慮して分類しています。 上記の3つの軸を考慮して、【社内で主要なセグメントのユーザーモデルについて共通理解できるようにすること】を目標にユーザーセグメントの調査・分類を進めています。 また、これらの 定量 的なユーザーセグメントの分類をもとに、 【2】や【3】の定性調査を進めることで、各セグメントのよりリアルな価値観・行動特性、UXに関する課題を把握して、具体的な改善を進められるようにしています。 【2】ユーザーアンケート|User questionnaire 弊社では、主に Google フォームを用いてユーザーアンケートを運用しています。 主に以下のような手順で、【1】のユーザーセグメント分類をベースに、UXについて深堀り調査したいセグメントに絞ってアンケートを実施しています。 アンケートは、メールやLINEによる配信や、Webサイト上にアンケート募集バナーを出すなど、対象のユーザーセグメントに合ったタイプで実施するように心がけています。 アンケートの計画・実施手順 アンケートのリサーチ目的・検証内容の整理 配信対象者の選定 アンケート設問の設計、 Google フォームの作成 アンケートの配信・公開 インセンティブ (謝礼)の付与 アンケート結果まとめ・共有・ふりかえり 【3】のユーザーインタビューを前提に、 設問の中でインタビューに協力いただける協力者を募るかたちでアンケートを実施することもあります。 会員向けのユーザーアンケートでは、会員データと紐付けて分析できるようにしているため、 ユーザーセグメントやユーザーの購買傾向・利用傾向を踏まえて、ユーザーインタビューにご協力いただきたい方を選定させていただくようにしています。 また、細かく検証したいUXについての設問をアンケートに用意することで、 アンケート回答内容から「あらゆる価値観や行動特性を持つユーザー」に対してインタビューが実施できるように工夫しています。 【3】ユーザーインタビュー|User Interview ユーザーインタビューは【2】のユーザーアンケートから、UXについてより深堀りして調査したい場合に実施しています。 近年のインタビューは、すべてオンライン(Zoom)を用いたインタビューとさせていただいており、さまざまな地域からご参加いただいています。 インタビューは約60分間で実施しており、 ユーザーの価値観や行動特性(日頃の行動や嗜好など)から インサイト を深堀りしていく 【 A. ユーザー モデリング 型の設問 】と、 過去の体験やこれから行いたい事柄を実際の画面を用いてシミュレーションいただきつつ、 その様子を観察・フローに沿ってUX(そのタイミングにおける思考やペイン・ゲインなど)について深堀りしていく 【 B. UX検証型の設問 】の2つから構成しています。 インタビューの主な計画・実施手順について、ご紹介します。 インタビューの計画・実施手順 インタビューの目的・ ヒアリ ングポイントの整理 インタビュー候補者選定 *1 インタビューシナリオの作成 インタビュー打診・調整、スケジュール作成 個別インタビューシートの作成 ユーザーインタビューの実施 インセンティブ (謝礼)の付与 インタビュー結果まとめ・共有・ふりかえり ユーザーインタビューの前に、ユーザーそれぞれの「個別インタビューシート」を用意するようにしています。 「プロフィール」や「購買傾向」、「利用傾向(お気に入りや登録年など)」、「購買や問い合わせの履歴」、「アンケートの回答」などを細かくまとめたシートとなっており、 基本的なインタビューシナリオに基づいた ヒアリ ングの中で、インタビュー対象者それぞれに合った ヒアリ ングをできるように工夫しています。 また、「インタビューの記録」についても同一シート内に収めることで、ユーザー単位で俯瞰できるようにして「傾向の把握」や「振り返りしやすいかたち」にしています。 弊社では、定期的にユーザーインタビューを実施させていただいております。 今後も、ユーザーインタビューを通じて 定量 的な数値からは読み取ることが難しいさまざまなペインや気付きを得ていきたいと考えています。 さいごに 弊社では、UXリサーチから導いたUXにおける課題(AS-IS)から、施策・企画(TO-BE)を検討して、日々サービスとUIUXの改善に取り組んでいます。 仮説通りの効果が得られているのか確認してよりよいかたちにしていくために、ABテストの活用や効果検証を実施して細かいアップデートや方向修正もおこなっています。 UXリサーチを通じて「より深くユーザーを理解して」「ユーザーにとって価値のある体験」を届けられるよう、 BUYMA のサービス・UIUXの改善にご期待いただけますと幸いです。 明日の記事の担当は サーバーサイドエンジニア の 平井 さんです! お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co *1 : 【2】ユーザーアンケートにて、インタビュー協力者を同時に募るようにしています
こんにちは、データサイエンティストの堀部です。 この記事は Enigmo Advent Calendar 2022 の16日目の記事です。 普段の業務では情報検索(検索/レコメンド)、不正検知、ユーザー属性の推定などを BUYMA にプロダクトとして組み込むことを行っています。その中でも モデリング 以前のタスク設計や探索的データ分析( EDA : Explanatory Data Analysis)、データのクレンジング・前処理、特徴量エンジニアリングなどを主に SQL (BigQuery)で行う部分に多くの時間を割いています。 1 今回は、違和感のある予測結果から気づいた傾向を元にデータの前処理を追加したことでモデルの精度改善につながった一例を紹介いたします。 概要 気づいた経緯 検出方法 結果 まとめ おまけ 概要 データから 機械的 な(ボットのような)アクセスを除外したことで、 機械学習 モデルの精度が改善しました。 そもそも気づいた経緯や検出方法、除外した結果について紹介いたします。 気づいた経緯 商品のブランドのitem2vecを閲覧履歴から生成した際に、 BUYMA 内で人気のブランドと直近1年で1件も購入されていないマイナーなブランドの類似度が非常に高く出ているパターンが複数見受けられました。違和感を感じ、学習データでマイナーなブランドに対してアクションを行なっているユーザーのlogを閲覧数が多い順に見たところ、一定間隔で別の商品詳細に遷移するというのを繰り返しているlogが見受けられ、人間ではないアクセスの可能性が高いと判断しました。 ちなみに、item2vecなどのベクトルはarray型でBigQueryに格納し、コサイン類似度などを SQL で計算できる様にしていますがとても便利です。 create temp function cos_sim(vec1 array<float64>, vec2 array<float64>) returns float64 as ( ( select sum (elem1 * elem2) / sqrt ( sum (elem1 * elem1))/ sqrt ( sum (elem2 * elem2)) from unnest(vec1) elem1 with offset pos1 inner join unnest(vec2) elem2 with offset pos2 on pos1 = pos2 ) ); 検出方法 「1度でも1分以内に次の商品詳細への遷移を100回以上繰り返しているユーザー」という条件で検出しました。 2 こちらを SQL でセッショナイズを行うことで実装しました。 3 セッショナイズのイメージ サンプルクエリ with item_action_view_detail as ( select ial.user_id, ial.time, ial.time - lag(ial.time) over ( partition by ial.id order by ial.time ) as interval_action from item_action_log as ial where ial.action = " view_detail " ), session_head as ( select id, time, case when lag(time) over ( partition by user_id order by time ) is null then 1 when time - lag(time) over ( partition by user_id order by time ) > interval 60 second then 1 else 0 end as session_head_flg from item_action_view_detail ), session as ( select user_id, time, concat ( user_id, " - " , sum (session_head_flg) over ( partition by user_id order by time rows between unbounded preceding and current row ) ) as session_id, from session_head ), session_summary as ( select session_id, user_id, count ( 1 ) as cnt_view, from session group by 1 , 2 ) select distinct user_id from session_summary where cnt_view >= 100 結果 ランキング学習を行っているモデルに対し、検出したユーザーIDを除外する前と除外した後のデータそれぞれ学習させたモデルでのテストデータでの精度を比較したところMAP(Mean Average Precision)が約2%改善しました。商品のブランドのitem2vecも除外後のデータで生成し直したところ、直感に合うようなブランド同士が類似度が高く出るようになりました。 機械学習 での推論結果をBigQueryに格納しているため、MAPなどの評価指標も SQL で計算できるようにしています。 (下記、average_precisionの平均をとったものがMAPになります) create temp function precision (y_true array<int64>, y_pred array<int64>, n int64) returns float64 as ( ( select sum ( case when elem1 = elem2 then 1 else 0 end ) / n from unnest(y_true) elem1 with offset pos1, unnest(y_pred) elem2 with offset pos2 where pos2 < n ) ); create temp function average_precision(y_true array<int64>, y_pred array<int64>, n int64) returns float64 as ( ( select sum ( precision (y_true, y_pred, m+ 1 )) / array_length(y_true) from unnest(generate_array( 0 , n -1 )) as m where y_pred[safe_offset(m)] in unnest(y_true) ) ); まとめ やったことは単純ですが、データの前処理の大切さを体感できた事例だったので紹介させていただきました。 Garbage In, Garbage Outを胸に刻みましょう。 おまけ 最近話題のchatGPTに BUYMA について歌詞を書いてもらいました 手にしたいものを 思い浮かべたら BUYMAに行くよ みんなの想いが集まる 世界中の商品が たくさん見つかるよ お求めやすい価格で 今日も新しいものが届くよ ハイブランドの服や靴 おしゃれなバッグやアクセサリー 雑貨や家電まで BUYMAで探してみよう 会員登録すれば さらにお得な特典が たくさんあるよ お気に入りを見つけて 買い物の楽しみを増やそう BUYMAで楽しい買い物 手にしたいものを 思い浮かべたら BUYMAに行くよ みんなの想いが集まる 今すぐBUYMAで 買い物しよう! 宣伝上手ですね。 話題のAIに弊社のサービスを認知されていて少し嬉しかったです。 明日の記事の担当は人事の右川さんです。お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co データクレンジング〜特徴量生成部分で dbt の活用を検討中です ↩ 実際の SQL ではユーザーエージェント( UA )でのボット除外を行ったデータに対して処理しています ↩ SQL でのセッショナイズは、 10年戦えるデータ分析入門 や ビッグデータ分析・活用のためのSQLレシピ に詳しく記載されています ↩
こんにちは、エンジニアの竹田です。 この記事は、 Enigmo Advent Calendar 2022 の15日目の記事です。 さっそくですが、エンジニアのみなさまは一流のエンジニアとはどんなエンジニア像をお持ちでしょうか。 自分は「障害を未然に防ぎ、継続的に安定運用可能なシステムを構築できるエンジニア」を一流のエンジニアだと考えています。 ひとえに障害と言っても、仕様と異なる動作をしない、リソース不足等によるシステム停止が発生しない、などいろいろと定義はあるかなと思います。 今回のエントリでは前者の「仕様と異なる動作をしない」という点について、業務を通じて見識を深められる場面がありましたのでご紹介したいと思います。 検索システムのリプレイス 今期は、とある検索システムのリプレイスに注力していました。 エニグモ では検索システムに Apache Solrを利用しており、今回リプレイスするシステムについても構成としては過去に こちらのブログ で紹介したものと近い構成となります。 自分は検索システムへのデータ投入、および検索リク エス トを行って結果を整形する箇所(主に Rails )の改修を担当しています。 リプレイスに当たり、 Rails からSolrへの直接リク エス トではなく、中間媒体として検索 API を経由する形式に変更しました。 このため、まずは既存コードやログを調査してリク エス ト方法や動作仕様をまとめ、いざコード改修に移りました。 コード改修 調査した仕様を元に一旦コード改修を完了し、ある程度動作するものができました。 その後、既存のテストコードを元に新コードのテストコードに移植を進める中で、細かな動きを実装できていないことに気付きました。 (画像はイメージです) 型が数値なのか文字列なのか nil 許容するのか 調査しきれていなかったリク エス ト方法や利用箇所がある 中には、えっ、そんな動きするの、みたいなものまで... コードやログを目視しただけでは分からなかったことが次々とでてきました。 テストコードの重要性の再認識 テストコードを動作させることで、より詳細な動作を知ることができました。 後から考えると、もっとしっかりとコードチェックをしていれば把握できていた点もあると思いますが、やはり作業しているのが人ですので、どうしても見落としは避けられないと思います。 テストコードがなければ デグレ を引き起こしていた可能性があり、「仕様と異なる動作をしない」点を満足できない状態にしてしまうところでした。 普段コードを書く際、テストコードも意識して書いてはいたものの、作成に当たってはコード カバレッジ 、モックの使用、境界値や複雑なパターンの網羅をどこまで厳密にするか等、、考慮することが多いです。 それなりに時間を要しますし、テストコード自体の視認性に納得がいかなかったりと、正直あまりテストコードを書くことは好きではありませんでした。 ですが、今回、多くの点をテストコードに助けられました。 テストコードの意義などを検索すると様々な方の記事がヒットするためその辺りの言及はしませんが、理屈としては理解できるもののなかなか溜飲を下げられないものだと思っています。 その点においても、実際にテストコードに助けられたという体験は非常に貴重なものでした。 最後に 過去にテストコードを地道に作成いただいた担当の方に感謝をしつつ、今後の誰かの助けになるということを意識して、テストコードを書くことを心掛けていこうと思います。 テストコードを全てパスした状態でのリリースは、精神的な安心感にも繋がりますね。 明日の記事担当は、データサイエンティストの堀部さんです。お楽しみに! 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは、サーバーサイドエンジニア の 橋本 です。 この記事は Enigmo Advent Calendar 2022 の 14 日目の記事です。 はじめに エンジニアとして仕事をしているとコードを読むことが多いと思います。例えば、仕様調査、CSからのお問合せ対応、レビュー対応などがあると思います。 今年を振り返るとコードを書く以上に読むことが多く、コードをより正確かつ速く読むにはどうすればいいかを考えることが多くありました。 ということで、この記事では私個人がコードを読む時に意識していることを紹介していこうと思います。 いきなりコードは読まない 1つ目はいきなりコードは読まないことです。業務で使われているコードの量は1つの機能でもとても多いです。いきなり読み始めるととても時間がかかったり、迷子になってしまうかもしれません。なのでまずはシステム全体を把握してインプットとアウトプットが何なのかの理解を進めます。把握の仕方は、システム仕様書を読んだり、担当した方と MTG して処理の大まかな流れを教えてもらっています。 全体の把握と同時並行で、実際に動かしてみることが多いです。実際に動かすと理解が進みます。 読む目的を意識する 2つ目は読む目的を意識することです。コードを読む目的は様々だと思います。表は一例です。 コードを読むケース 知りたいこと レビュー対応 バグが無いか、仕様を満たしているか、設計的に問題ないかを確認する。 CSからのお問合せ対応 バグが発生している原因を知る。 目的が曖昧な状態でコードを読み始めると、本来は読む必要が無いコードも読むことになり時間が足りなくなるケースがあると思います。業務は期限が決まっていることが多いので、効率的に進めるためにも目的を意識することは大事だと考えています。 適度にメモを取る 3つ目は適度にメモを取ることです。業務で使われているコードは量が多く、一度に読んで全てを把握するのは大変です。なので私はメモを取りながら読み進めることが多いです。メモの取り方ですが、 ソースコード 上に直接書いたり、別途テキストファイルに書いたり、slackのスレッドに書いたりなどして流れを整理しています。まだ慣れていない プログラミング言語 の場合は読むのに時間がかかると思うので、メモはかなり有効だと感じています。 おわりに 今年は色々な機能のコードを読むことが多く、 BUYMA の仕様について詳しくなりました。それだけでなくコーディングの技術についても学ぶことが多かったので、コードを読むというのはとても大事だなと改めて感じました。多分来年も読むことが多いので頑張りたいと思います。 明日の記事の担当はエンジニアの竹田さんです。お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co
この記事は Enigmo Advent Calendar 2022 の13日目の記事となります。 お疲れさまです。インフラチームの山口です。 弊社では一部イン フラリ ソースのモニタリングにDatadogを利用しています。 その中で、今回はDatadogの利用開始当初に GUI で作成されたモニターをTerraformerとTerraformを使用して構成管理した際の事例について報告します。 同様の技術スタックを使用したインポートや構成管理における具体的なテンプレート等の事例には事欠かないと思いますので、作業計画を中心に説明します。 要は、TerraformerやTerraformの使い方は様々良い資料があると思うため、今回固有の対応をした点を注力して説明します。 本稿の構成を以下に記載します。まず、対象とするモニターの状態などの前提を説明します。次に、作業の流れを概説し、Terraformの ディレクト リ構成等を少し説明します。そして最後にまとめます。 1. 前提 まず作業の目的と対象とするモニターについて説明します。 目的 GUI で人間が手で作成したモニターをTerraformで構成管理する。 対象とするモニター 構成管理の対象とするモニターの概要を以下に記載します。 あるプロジェクトでのイン フラリ ソースの監視のために手で作成されたモニター309件を対象とします。 複数種類のイン フラリ ソースの監視のためのモニター群ですが、当該プロジェクトであることを示すタグのみが付与された泥団子状態です。対象のモニターを、サーバロールごとのタグを付与した上で、ロールごとにmodule化し取り扱いをしやすくすることを目的とします。 モニター件数 特徴 309件 ・インポート対象を識別できる特定のタグが付与されている(例: project: xxx といったタグのみ) ・モニターは Rails のWebサーバや、バッチサーバ、DBサーバといったイン フラリ ソースの監視目的 2. 作業の概要 作業の概要について説明します。今回の対応は大きく2段階に分かれます。 まず、STEP1としてインポート対象のモニターをTerrformerで一旦1つのtfファイルにインポートし、その後人手でサーバのロールを表すタグをモニターに付与しapplyすることで、泥団子状態を改善させます。 次に、STEP2として、サーバのロールごとに再度Terraformerでインポートし、tfファイルを リファクタリング しapplyを行います。 以降で各STEPの内容とポイントを説明します。 STEP1: 事前準備 STEP1では泥団子状態を脱することを最優先とします。 そのため、一旦Terraformerでインポートした後に、人間が大雑把にモニターにタグを付与しapplyします。その際のポイントとしては、モニターによっては「どのようなタグを付与するべきか」悩むケースもあると思いますが、Terraformで管理可能になることで泥団子状態より悪くはならないため速度優先で「エイヤ」でタグを付与しapplyしてしまいます。 実際にタグの付与は私が作業したのですが、作業当時の記録を見ると10分で25%進んだと記録があり、1時間もかからずに思いの他早く済んでいたようです。 一旦既存のモニターをTerraformerで一括で1つのtfファイルにインポートする tfファイルのモニターの内容を精査し、各モニターの用途(サーバロール)が判別可能なようなタグを人手で付与しapplyする 図1 STEP2: サーバロール単位でのインポートと リファクタリング 以下をサーバロール数分繰り返します。 端的には、Terraformerでインポートしたtfファイルの内容を人間が読みやすいように修正し、かつ意図しないリソース再作成なども発生しないようにtfstateも修正した上でapplyします。 特定のサーバロールのモニターをterrformerでインポート tfファイルを リファクタリング してapplyする 図2 3. インポート後の ディレクト リ構成や修正内容 インポート後の ディレクト リ構成やTerraformerが自動生成した内容からの修正ポイントを説明します。 本記事は、技術的な説明を主とする記事ではないため概要のみを簡単に記載します。 ディレクト リ構成 ディレクト リ構成を以下図に記載します。 複数環境に対応可能なようmodule側に主なリソースを切り出して、そのmoduleを環境ごとに呼び出しモニターを作成する構成としています。 また、 terraform workspace 等は使わずに愚直に環境・サーバロール単位でtfstateを分ける構成としています。 リモートバックエンドも使わずに、原始的にtfstateを リポジトリ にコミットします。 これは、複数人で 人海戦術 的な方針で分担して作業する際にリモートバックエンドを操作するためのキーの設定やミスする可能性のある箇所を極力減らすことを念頭においたというのがもっともらしい言い訳ですが、実際は横着をしたためです。 図3 tf、tfstateの リファクタリング Terraformerでインポートした際に リファクタリング を行った観点を以下で箇条書します。 リソース名を人間が判読可能なものにする resource "datadog_monitor" "tfer--monitor_1234567" といった自動生成されたリソース名を人間が判別しやすいものに修正します。 1のリソース名の修正に伴いtfstateも修正する これは、モニターの場合は状態を持たないリソースのため特に再作成でも大きな問題は無いですが、 リファクタリング 時の修正差分等を terraform plan で確認したいために tfstateも修正し極力再作成を回避します。 ヒアドキュメントを使う Terraformerでインポートしたモニターは message が1行で可読性が良くないためヒアドキュメントを使うよう修正します。 まとめられるリソースはfor_eachでまとめる for_eachでまとめられるリソースは for_eachで複数作成します。その際の2との兼ね合いは状況を見て判断します(場合によっては再作成もやむなしとする)。 4. まとめ(所感) 最後に所感とまとめを記載して終わります。 所感 利用開始直後でも最低限の初期設計は重要 その時はその時のベストを尽くしてるはずなので昔を悪し様に思わない気持ちが重要(今もそのうち昔になるので) ただし過去の経緯や判断に過度に忖度をする必要性はない(でないとずっと辛いままのため) こういった、過去のしがらみ踏まえた改善活動ができるのは事業会社ならでは まとめ ある作業を、「すべて人間 or すべて スクリプト で対応する」といった形に拘ってしまうと辛いことがあるため最も早く目的を達成できそうな方法を選ぶことが重要。それは会社の人的リソースの状況にもよると想像されるため、適度な塩梅は自分たちで考えていくしか無い(身も蓋もないまとめ)。 明日の記事の担当はエンジニアの橋本さんです。お楽しみに。 株式会社 エニグモ すべての求人一覧 hrmos.co
こんにちは、新卒エンジニアの川本です。 BUYMA のサーバーサイドを中心に開発しています。 この記事は Enigmo Advent Calendar 2022 の12日目の記事です。 データ モデリング について学習中で、DB設計の入門書を読んで論理設計について第1~5正規化といった内容を学習しましたが、いざ個人開発でデータ モデリング しようとしたらどうしたらいいのかよくわからず、手を動かすことはできませんでした。 そんな状況の時にイミュータ ブルデー タ モデリング という モデリング 手法について知ったことをきっかけけに、データ モデリング がイメージしやすくなりました。 この記事ではイミュータ ブルデー タ モデリング を実践してみて感じたことを紹介できればと思います。 目次 データと情報の違い イミュータブルデータモデリングとは イミュータブルデータモデリングの手順 普段Railsで開発していて感じたこと イミュータブルデータモデリングとの向き合い方 最後に データと情報の違い データと情報には以下の違いがあります。 データ 客観的な事実を記録したもので、文脈や解釈がない RDB に記録される 情報 文脈や解釈の与えられたデータ SQL で抽出する この違いから正確な情報が必要ならデータが正確に記録されていなければならないことがわかると思います。 イミュータ ブルデー タ モデリング とは イミュータ ブルデー タ モデリング とは、データを失わずに RDB に正確に記録できるように、更新と削除がなるべく起きないようにデータ モデリング することです。 更新と削除が起きるということは、データが変更された、失われたということです。 つまり、正確なデータをすべて RDB に記録できていないことになり、必要な情報を抽出できない可能性が出てくるということです。 イミュータ ブルデー タ モデリング の手順 ここでは、イミュータ ブルデー タ モデリング を実践したことで、正規化について理解が深まった瞬間があったので例を交えて紹介できればと思います。 詳しい手順が知りたい方は以下の記事がすごくわかりやすいです。 scrapbox.io エンティティはイベントとリソースにに分類される 分類の判断には、エンティティが日時属性を持つかどうかで判断できます。 日時属性を持つエンティティはイベントエンティティに分類されます。 エンティティに対して、「~する」という動詞をつけてみると識別しやすいです。 例えば「会員する」という日本語は不自然ですけど、「注文する」という日本語は自然です。 ここから注文はイベントエンティティで会員はリソースエンティティであることがわかります。 今回はこのイベントエンティティについて少し深ぼって説明していきます。 イベントエンティティには日時属性を1つだけ持つようにする イベントは1つの日時属性を持ちます。 例えば、注文エンティティなら注文日時を持ちます。 ここで以下のような設計の注文テーブルがあったとします。 上記の注文テーブルは、注文日時の他に請求日時、入金日時、更新日時を持ってしまっています。 これはこの注文テーブルの中に、以下の異なるイベントが混在していることを示しています。 請求 入金 これらは別のイベントエンティティである請求エンティティ、入金エンティティとして分解することができます。 そうすると以下のように設計することができます。 こうすることで、請求や入金が発生しても注文テーブルをUPDATEする必要なく、それぞれのテーブルへのデータのINSERTのみでデータを記録することができます。 ここまでの流れは実はOne Fact in One Place(1つの事実は1つの場所に)という正規化の行為そのものとなっています。 第1~5正規化を意識しながら初学者が正しく正規化するのは難しいと思いますが、ここまで紹介した手順だとまだイメージがつきやすいのではないでしょうか。 普段 Rails で開発していて感じたこと Rails で普段開発をしていると更新日時をもたないことは違和感があるかもしれません。 Rails でscaffoldすると更新日時カラム(updated_at)が自動で入ると思います。 order(注文)リソースをscaffoldする。 $ rails g scaffold order amount:integer 自動的に作成日時(created_at), 更新日時(updated_at)が入る。 # == Schema Information # # Table name: orders # # id :bigint not null, primary key # amount :integer not null # created_at :datetime not null # updated_at :datetime not null # class Order < ApplicationRecord end これは Rails がWEBシステムで必要なのは、最新のデータだけであるという制約を設けていて、UPDATEが起こること前提の設計になっているからだと思われます。 この強い制約を設けることでUPDATEやDELETEを許容する代わりに、たいていのことはデータベースと1対1となったModelの CRUD で表現できるというシンプルさを手に入れることができます。 Modelに書くことができず、Serviceクラスが肥大化したりするのはデータ モデリング の設計が悪い可能性が高いそうです。 このあたりは以下の Podcast で詳しく説明されているので、聞いてみてください。 anchor.fm イミュータ ブルデー タ モデリング との向き合い方 イミュータ ブルデー タ モデリング で考えると、イベントをエンティティとして捉えることからエンティティの数も増え、INSERTのみで記録することからデータ量も増えます。 そうすると、論理設計の段階では問題なかったかもしれませんが、いざ物理設計する際に実装を考慮するとパフォーマンスの問題に直面することもあるかと思います。 イミュータ ブルデー タ モデリング はデータ モデリング における正解ではなく、一種の論理設計をする際の制約として捉えるといいと思います。 考え方としては以下のような順番かと思います。 イミュータ ブルデー タ モデリング で論理設計する。 物理設計の段階で実装を考慮するとパフォーマンス的に厳しい箇所が見つかる。 問題となる箇所に対してUPDATEを許容する。 最後に イミュータ ブルデー タ モデリング はデータ モデリング における正解ではなく、一種の考え方です。 私のように初学者でデータ モデリング に対して苦手意識がある人は一度イミュータ ブルデー タ モデリング について調べて実践してみるといいかもしれません。 興味がある人は、 WEB+DB PRESS Vol.130のデータ モデリング 特集を面白いので読んでみてください。 gihyo.jp こちらの楽々ERDレッスンという書籍も実践的な内容が多くおすすめです。 www.shoeisha.co.jp 明日の記事の担当は インフラエンジニア の 山口 さんです。お楽しみに! 株式会社 エニグモ すべての求人一覧 hrmos.co