男女比はカレーと福神漬けと同じくらい

マサカリよろしくお願いします。

心理的安全性について

バイト先の人に「うちで働く可能性ってある?可能性が低いとしたら何があれば高くなる?」という質問をされて考えたことを書きます。

人は皆「心理的安全性」の高いところで働きたい

心理的安全性を「自分がそこに所属していてもよいと思えるかどうか」と定義したとき、大きく分けて3つの心理的安全性が存在するのではないかと考えました。

  1. 精神的な心理的安全性
  2. 金銭的な心理的安全性
  3. 成長に対する心理的安全性

そして、それぞれの心理的安全性に対する係数を自分の中で持っていて、係数を掛け合わせた3つの和を各企業で比較して「どこで働くか」を決定しているのではないかと考えました。

a + b + c = 1; 0 ≦ a,b,c ≦ 1

働きたさ = a * 精神的な(ry + b * 金銭的な(ry + c * 成長に対する(ry

式で表すとこんな感じです。

精神的な心理的安全性

本来の意味での心理的安全性です。 「精神的な」と「心理的」は意味が重複している気もしましたが、明確に分けて使いたかったのでこのように表現しました。

基準として挙げるなら

  • チーム内で安心して発言できるか
  • チームにおいて自身が必要な存在だと思えるか

とかだと思います。

精神的な心理的安全性を見極める方法は

くらいしか思いつかないです。

しかし、残り2つの心理的安全性と比べチームで大きく上下する気がします。
入社するまで部署が決定しないような大きめの会社だとギャンブルですね、、、

金銭的な心理的安全性

ざっくりと言えば「お金がいっぱい・安定してもらえるかどうか」です。いくら精神的に肯定されているとしても求める生活水準に達していないと働き続けるのは難しいですよね。

会社が潰れにくいかどうかもこの安全性に入るのではないでしょうか。
大きめの会社は金銭的な心理的安全性が高く、小さいベンチャーのような会社は金銭的な心理的安全性が低い傾向にあると言えます。

基準として挙げるなら

  • 満足した水準の生活が送れるか
  • 突然辞めさせられてもXヶ月無職で生きていける程度の貯蓄が可能か
  • そもそも辞めさせられる可能性が高いかどうか

とかだと思います。

金銭的な心理的安全性を見極める方法は

  • 提示された年収を見る
  • 会社の業績をチェックする
  • 働いている人のTwitterとかをチェックして生活レベルを把握する*1

くらいだと思います。

成長に対する心理的安全性

ざっくり言うと「自身の市場価値が上げやすい環境か」、もっと言うと「何も考えなくても自然と市場価値が上がっていく環境か」です。

精神的な心理的安全性は「自分がそこ(そのチーム/企業)に所属してもよいと思えるか」だとすると、成長に対する心理的安全性は「自分がそこ(その業界)に所属してもよいと思えるか」に対応すると考えています。

もちろん、何も考えなくても自然と市場価値が上がっていく環境に属しているから自身は何も努力しなくていい、という話ではないです。
毎日5時間勉強するのが当たり前の高校に通っている人と毎日カラオケ・ゲーセンで遊び呆けているのが当たり前の高校に通っている人*2を大学受験の入試難易度という物差しで比較すると有意な差は存在するよね、という話です。

そもそも学び続ける必要があるのかという議論があると思いますが、自分の所属するIT業界の中のWebサービス開発の分野においては「学び続ける必要がある」と考えています。
理由は、利用している技術の代謝が早いため、今主流となっている技術が1,2年後も主流であるとは限らないからです。 この辺りは散々議論されてるのでここでは割愛します。

成長に対する心理的安全性を見極める方法は

  • 技術発信をしている
  • 技術的に難しいとされる領域に取り組んでいる
  • 勉強会の会場になっている
  • 強い人がたくさんいる

とかになると思います。

 


 

人生のフェーズによってどの心理的安全性を重視したいかは変わってくるだろうし*3、会社によってもどの心理的安全性を重視しているかは違うと思います。*4

なので、現時点での自分の志向性に合った心理的安全性を重視している会社を選ぶのが良さそうです。

*1:一応書いておくと自分はこれやったことないです

*2:それはそれで楽しそう

*3:所帯を持つと「一定ラインの金銭的な心理的安全性は必須」とかなりそう

*4:働きやすさを推す会社もあるし、高給を推す会社もあるし、圧倒的成長を推す会社もある

引っ越し備忘録

筑波大学に3年次編入してからもうすぐ2年になります。 卒業に必要な単位は取得し、卒業論文も提出し、あとは卒業研究の発表と細々した課題を出せばOKという状態になりました。

ありがたいことに就職先も決まっています。
オフィスは都内なのでつくばからは通えません。(ぜっっっっったい通いたくない)
なので引っ越し先を探して引っ越すことにしました。

ちなみに情報科学類に3年次編入した同期で院進せずに就職したのは自分だけなはず。
なぜ院進せずに2年で卒業する判断をしたのかはまた今度書きます(多分)。

2年前に編入でつくばに来た時に引っ越しを経験したはずなのに全然覚えてなかったため、忘備録としてまとめておくことにします。

いつ・どうやって物件を探すか

まず悩んだのが「いつ・どうやって物件を探すか」でした。
これは自分なりの答えを持っていて、それは「ちょい遅めに不動産屋さんに行く」です。

「ちょい遅め」とは4月入社の場合、1月第2週くらいを指します。 成人の日前後辺りでしょうか。

Q. なぜちょい遅めなのか

Ans. たくさんの候補の中から探すのが面倒だから。

自分は物件の条件の下限が高専の寮になってしまっていました。
そのため、ほとんどの物件はパスし「まあ住めないことはないよなあ」と全然絞れませんでした。
なので他の人がある程度選んだ状態から物件決めようと考えました。

加えて、都内の物件だと契約後2,3週間以内から家賃が発生するケースが多く、住んでいないのに家賃を払うのはもったいないな、という気持ちもありました。

Q. なぜ不動産屋さんなのか

Ans. いい感じにチョイスして提案してくれるから。

これに尽きます。web上のだと迷ってしまうので。

物件の検索条件をどうするか

先ほど述べた通り、ほとんど物件に対する必須の条件がありませんでした。

強いて挙げるなら

  • オフィスから1.5km圏内(社の住宅補助の範囲)
  • 1Kで7畳以上
  • コンビニかスーパーがそれなりに近い
  • 自転車の置けるスペースが欲しい
  • 家にお風呂がついていてほしい

くらいだと思います。 住宅補助圏内以外の条件は無理なら無理でまあ対応できるかなと考えてました。

結果どうやって決めたかと言うと、不動産屋さんが提案してくれたものの中からなんとなく良い気がする物件を選択しました。

次引っ越すときはもっと主体的に決めようと思います。

初期費用で全財産溶ける

初期費用は家賃の4~5ヶ月分だから早めに貯金しておこうね、という話です。

初期費用は敷金、礼金、仲介手数料、初月家賃、保険、鍵交換代などによって構成されています。 敷金・礼金がそれぞれ1ヶ月分、初月家賃はもちろん1ヶ月分、仲介手数料1ヶ月分、保険・鍵交換代その他諸々合わせて1ヶ月分、合計して5ヶ月分という感じでしょうか。

ざっと計算すると

家賃 8万 → 初期費用 32~40万
家賃 10万 → 初期費用 40~50万
家賃 12万 → 初期費用 48~60万

くらいになるかと思います。

都内のイケイケIT企業のオフィスへ自転車通勤できる物件となると1K7畳で10万前後するのは普通みたいです。

つくばの家賃は3~4万くらいで初期費用もそれほどだったというのもあり、あまり準備してなかったので全財産が溶けました。

引っ越しタイミングでバロンチェアを買う計画を立てていたのですが、一瞬で消滅しました。

引っ越し運送費は時期によって値段めっちゃ変動する

サカイ引っ越しセンターは実際に家まで来てくれて荷物の量から見積もりを出してくれます。
自分は何もしなくていいのでありがたい。 ついでにお米2kgくれました。

で、見積もり結果は

  • つくば〜東京
  • 3月上旬
  • 家具一式+段ボール20箱分(よくある一人暮らし分程度)
  • 荷造りと荷解きは自分で行う

で8万ちょいでした。
荷造りと荷解きもやってもらうプランにすると+3,4万くらいになるとのこと。
5~10万くらいなのかなと思っていたので想定内です。

見積もりに来てくれた人に話を聞くと

  • ヤマト運輸が引っ越し事業から撤退したせいでまじヤバイ。
  • もし引っ越し時期が3月下旬だったら3,4倍の見積もり金額を提示してる。
  • 3月下旬に北海道〜東京、一人暮らしサイズで100万近い額を提示したことがある。客からの怒られが発生した。が、他の引っ越し業者は見積もりを出すことさえできなかったので客は100万近い額で引っ越しを行った。

など色々面白い話が聞けました。

なぜ繁忙期はそこまで値段が跳ね上がるのかという質問をしたところ、
「自社で持っている運送能力を超える量の注文を受けると運送能力を外注して注文を遂行する、という仕組みになっている。外注はオークションのような仕組みになっていて、競合他社と文字通り競り合った金額分引っ越し費用に上乗せされてしまう」
との回答が得られました。 なるほど。

運送能力の入札の最適化とトラックへの積み込みの最適化(1つの大きなトラックに複数人分の荷物を載せることがある)の2つを同時に解いているらしく、なかなか面白そうな領域だなと思いました。

ライフライン・住民票といった事務処理

まだ手をつけてないので後で書く。

 


 

次に引っ越すときは東京の波に揉まれて調子乗った物件の条件を提示してたりするのでしょうか。
自分の成長が楽しみです。

プログラミング以外の趣味を探した話

年末なのでポエムを書いてみようと思った。

プログラミングという趣味は一般社会に対してウケが悪く、属性が異なる初対面の人との話題に超困ったので他の趣味を探してみたよ、という話。
「プログラミングが趣味で何が悪い、ウケを気にして趣味を探すことがそもそも間違っている」といった議論をする気はない、と一言添えておきます。

プログラマは趣味もプログラミングの人が多いと感じる。 プログラミングと言ってもコードを書くことだけがプログラミングではなくネット記事・雑誌を読む、知人との議論による情報収集もプログラミングに含まれると考えている。

このサービスを作るとしたらどんな技術選択をするか、最近よく聞く言語/ライブラリを触ってみてどう感じたか、サービスを作る上でどんなことを大事にしているのかといった議論をするのは最高に楽しい。

自分もプログラミング以外の趣味はなく、「あなたの趣味/好きなことは何ですか?」と誰に聞かれると「コードを書いてなにか物を作ることです!」と答えていた。

もちろん世界中の人が「プログラミング」という趣味を面白がってくれるわけではないということは理解していたが、通っていた高専という学校の属性上あまり気にすることはなかった。*1

 

プログラミングという趣味は一般社会においてウケが悪い *2と気付いたのは知り合いがやっている居酒屋で定期的に行われているパーティに参加したときだった。

パーティでの会話
初対面の人「休みの日とかって何してるの?」
ぼく「コード書いたり技術系の記事読んだりすることが大半な気がします」
初対面の人「へー!すごい、ずっと勉強してるんだ」
初対面の人「そういうのじゃなくてどこか行ったりとか普通に遊んだりとかってしないの?」
ぼく「プログラミング以外?うーん、あんまりないですね...」

書いていると趣味関係なく自分が単純にコミュ障なだけではという気がしてきた。

どうやら「プログラミングは勉強だから遊びの内に入らない」と考えている人たちがいるらしい。 大学へ編入するため広島から関東へ拠点を移し色々な人と会うようになると、そのように捉える人たちに会う回数は増えていった。

高校へ行き大学へ進学した人たちが当たり前のように持っている「初対面の人と共通の話題を探しつつ会話を膨らませる能力」に対する強い憧れを抱くようになった。

「エンジニア属性を持たない人との共通の話題がなくて話が盛り上がらない」

この現状に危機感を感じた自分はプログラミング以外の趣味を探すことにした。

読書

とはいえどうやって探せばいいのか分からなかったため、小説を読み登場人物の趣味を参考にするという方法を考案し実践した。 (元々本を読むのは苦ではなかったというのも大きいのかもしれない)

しかし読んでいるうちに目的を忘れ単純に読書を楽しんでしまっていた。 が、読書は現在も継続できているので結果オーライ

最近はpaperwhiteを購入したため読書が加速している。

ダーツ

前からダーツが少し気になっていたので少し真面目にやってみようとマイダーツを買い、家の近くにあるダーツができる漫画喫茶に定期的に行くようにしてみた。

  • 肘のxyz座標を変化させない
  • 投げる時の手の軌道と肘が同一面上にあるか
  • リリースのタイミング

この3つのパラメータを調整し最適解を探索する計算機になった気分でやっていた。
自身をチューニングする感覚が新鮮で楽しかった、

ただ、だんだんと同じことの繰り返しに感じるようになり足が遠のいていった。 ある日ダーツをしている間は耳と頭が暇なことを発見したのでダーツしながらTech系Podcastを聞いたところ、体験がとても良かったのでなんとかまだ継続できている。

1,2時間くらい投げてると1,2本HAT TRICKが出るくらいになった。

美術館

「美術館行ってみない?」と友達に誘われたのがきっかけで美術館に行くようになった。それまでは美術館は行っても面白くないと思っていたが、一度予習して美術館に臨むと面白いことに気付いた。

漠然と作品を見て綺麗・荒々しいといった感想を持つのではなく、 作者が何を感じながら生き死んだのかを追体験するためのマイルストーンとしての作品、そう考えながら見ていると面白いと感じるようになった。

おそらく鑑賞する対象が作品から作者へ移ったからだと思う、
1人で行くときは音声ガイドを必ず借りる

 


 

現段階では読書・ダーツ・美術館が定番になっている。見返すとインドア且つソロで楽しめる内容に偏っていることに気付いた。まあいいだろう、突然アウトドアの趣味を探しても継続できないことは目に見えている。

もちろん定着しなかった趣味も存在する。

 

ウケが悪くない趣味を見つけるという本来の目的を達成したかどうかを確かめるには「初対面の人と話す」という検証フェーズが行う必要があるが、それは自分にとって多大なエネルギーを必要とするため現時点では実行に移せていない。

消費エネルギーが少なく、それなりのサンプル数を得るための効率的な方法としてはマッチングアプリがいいのかなあと思案している。同性のサンプルは得られないので別の方法も考える必要がありそうだけど。

 

そんな感じで2018年お疲れさまでした。来年もよろしくお願いします。

*1:高専在学中は「4学科もあるんだしそれなりに多様性あるよね」と思っていたが、卒業してから偏りがあったことに気付いた

*2:この記事で"ウケが悪い"とはそのネタを元に会話を膨らませる難易度が高いことを指す

Slackにアップしたスライドをいい感じに見れるやつ作った

これは呉高専 Advent Calendar 2018の23日目の記事です。

先日、kosen12sというコミュニティで発表した内容をつらつらと書いていきます。
スライドはこちら ↓

speakerdeck.com

なぜ作ったのか

自分が所属している研究室では毎週交代で最近読んだ論文をスライドにまとめて発表し合うイベントがあります。
とても良いイベントなのですが、現状として作ったスライドが共有されず「他の人が作ったスライドを見返せない」「自分が紹介するときに紹介済みの論文を載せていないか心配」という問題がありした。

以下のような脳内議論が行われた結果、、、


案1 : Slackにアップロードするよう声かけをすればよさそう?

Pros

  • Slackは研究室でよく使ってるのでアップロードは楽で良い

Cons

  • スライドを見返すのに使うのは難しい、整頓されていてほしい
  • スライドアップ時にキーワードも同時にpostすれば検索できるかもしれないけどSlackの検索のUXあんまり良くない(個人的感想)
  • 無料枠で使っているのでファイル容量を超えると古いファイルは削除されてしまう

案2 : speaker deck, slideshareにアップするよう声かけすればよさそう?

Pros

  • スライドが見やすく、検索しやすい
  • publicに公開するので自分のポートフォリオページとして活用できる

Cons

  • そこまで真面目にスライドを作り込んでないので心理的ハードルが高い
  • ページ開いてわざわざアップロードするのは面倒

 

Slackの特定のチャンネルにスライドをアップロードしたらシュッとweb上で公開されるランニングコスト0のツールがあればいいのでは?と思ったので作りました。

作ったもの

webページ(サンプル) → https://teppei-slides.netlify.com/

主な機能

  • アップロードしたスライドが一覧できる
  • スライドがキーワード検索できる
    • Slackでアップしたpdfのスレッドに書き込んでもらうことによりキーワードを設定
  • ユーザーのアイコンをクリックするとユーザーごとのスライドが見られる

リポジトリ

github.com

github.com

ざっくりとバックエンド、フロントエンドはこんな感じのツールで構成されています。

f:id:euglena1215:20181223154729p:plain

バックエンド

  1. GASがSlackの特定のチャンネルに新しいスライドがアップされていないか定期的に見に行く
  2. 新しいスライドがアップされていた場合、Google Driveにスライドを保存し直してスライド情報をスプレッドシートに保存する
    (Driveに保存し直しているのはSlackのファイル容量対策)
  3. GASがシートの内容をAPIとして公開する

フロントエンド

  1. GatsbyJSを使ってReactでページを作り、↑で作成したAPIを叩いて情報を取得し静的サイトを生成する
  2. netlifyを使ってwebページをホスティング

これら一連のフローで使っているツールは全て無料です。ほんといい時代ですよね。

GAS, GatsbyJS, netlifyなどのツールの説明はここでは割愛します。 スライドではめちゃくちゃ雑に紹介してるので初耳な人は↑のスライドを見てみてください。

がんばったところ

PDFの表紙画像の取得

表示画像の取得はスライド共有ツールを作るときに悩む問題で、この記事だとpdftocairoを使っています。

今回は無料の範囲という制約があるためGASで完結できるよう色々調べていると、 Slackはpdfをアップロードすると表紙の画像も取得できることを発見しました。

f:id:euglena1215:20181223191210p:plain

今回はこの機能を利用して表紙画像を取得しました。

余談ですが、Slackは画像をアップロードすると数種類のリサイズした画像も返してくれます。Slackは画像のリサイズ用マイクロサービスとしてとても優秀です。

react-pdf-js で日本語が表示されない

PDF.jsをReactで使いやすくするためにwrapしてくれているreact-pdf-jsを使ってスライドの表示をしていたのですが、日本語が表示されないという致命的問題がありました。

原因としてはフォント情報が入っているcmapファイルのpathがPDF.jsにちゃんと届いてないという、PDF.jsを使った開発をしているときによく発生するあるある問題でした。

github.com

なのでreact-pdf-jsにPRを投げて修正しました。

研究室での普及活動

いくら頑張ってツールを作っても、作りっぱなしだと普及しないのは今までの経験から分かっていることなので

  • 使い方スライドを作ってアップロードする
  • 論文紹介の担当者にアップロードしてもらえるようDMで根回しをする

といった普及活動をしています。

まだ論文紹介の担当が1周していないのでもう少し普及活動は続けていく必要があるかなと思ってます。

 


 

こんな感じのツールがランニングコスト0&だいたい3日間くらいでできたのでほんといい時代だなと思いましたまる。

RailsのCookieStoreをnodeで復号する

背景

既に動いているRailsアプリケーションとfrontendの間にBFF用のnodeサーバを立てて、認証情報(currentUserIdの取得)はBFFで吸収させたい。

※ Session管理にCookie Storeを使っているRailsアプリケーションを想定しています。

書いた

RubyMarshal.loadRuby独自の機構なのでnode-marshalを利用した。

環境変数Railsアプリケーションで使っているSECRET_KEY_BASEを設定する必要がある。
expressのmiddlewareとして書いたので使うときは下のような感じになる。

import cookieParser from "cookie-parser";
import express from "express";

const COOKIE_NAME = "_sample_app_session_development"

// middleware
const app = express();
app.use(cookieParser()).use(setDecryptCookies(COOKIE_NAME));

参考にしました

encryption - How to decrypt a Rails 5 session cookie manually? - Stack Overflow
rails-cookie-parser/index.js at master · instore/rails-cookie-parser · GitHub

ISUCON8で予選敗退してきました

昨日、ISUCON8のオンライン予選があり予選敗退してきたのでその様子を報告します。

牛久大仏「う〜ん、顔採用w!」 というチーム名で筑波に編入した同期の@k5342, @chigichan24とISUCON8オンライン予選に参加してきました。

↓↓チームメンバーの記事はこちら↓↓

k5342.hatenablog.com

chigichan24.hatenablog.com

Rubyで参加しBest Scoreは5000点、最終Scoreは4000点と学生枠ボーダーには全然届かない点数でフィニッシュしました。

サーバはserver1: DB, server2: app1, server3: app2として利用し、
app1にベンチに来てもらい、ラウンドロビンでapp1とapp2にロードバランシングするといった構成になっていました。

スコアが目に見えて上がったのは複数台構成に変更したときくらいでした。

github.com

もちろんやってないこともたくさんあったけど、それなりに高得点者の歩いていた道を辿っていた気がするのでもう少し点数伸びてもよかったなぁというのが正直な感想です。


以下詳細です。

また、自分が関係するムーブだけ書いていきます(他のメンバーのムーブはブログに書いてくれるはず)

時刻 作業内容
前日
16:00 Redisの使い方をブログにまとめる→ これ
22:00 1台構成→複数台構成時に変えたときに起こりうる問題を色々考える
今まで1台構成でばかり解いていたので色々考えることがあることが分かって、色々調べた
当日
8:00
10:05 DBのschemaを確認する
10:30 自分のポートでwebサーバを立ち上げようとするが失敗する、ここで時間を多少消費する(firewalld周り)
11:30 reservationsのreserved_atにindexを貼ってみる
11:45 kataribe, myprofierを入れる(nginxに置き換え作業が発生していたため待ち時間が発生する)
←DBめちゃ重との連絡を受けたのでN+1を潰していくことにした
15:00 get_eventsから呼ばれてるget_eventのみ修正しN*N+1をN+1に改善した #6 
サクッと書いたクエリを「ほんまに合っとんかこれ?」と3人で悩む時間が発生していた(合っていた)。ここでかなりのタイムロスをした感がある
15:20 get_eventsのtransaction要らなくね?となったので外した #7
16:30 get_eventをN+1→1にした #8
クエリ自体は1になったけど処理方法がよくなかった(Array#selectでぐるぐる回しまくっていた)
17:00 開発に使っていたサーバからの移動を命じられ、いそいそと移動する
17:15 app serverのメモリがやべえという連絡を受け、メモリを節約できそうな場所を探すがよくわからん(残り1時間を切っていたのでget_eventを複数回呼んでいるところの修正は諦めた)
17:30 メモリ使用を減らすためにとりあえずSELECT *を消した、が終了直前だったのでマージは見送られた #10
17:45 app serverの再起動確認を行った&ベンチにenqueueされる様子を眺めていた
17:55 やることがなくなったので反省会開始
ISUCON終了
18:30 同じ場所でISUCONに参加していたluvtechno(カニオムライス), qnighy(カニオムライス), Altech(カニオムライス), gedorinku(winjisucon)と一緒に反省会会場(焼肉)へ移動
f:id:euglena1215:20180917115632j:plain:w450
↑反省し終わった(肉を撮り忘れていた)
Wantedly社員の人が反省会費用を出してくれた(特にCTO)!ありがとうございます!
22:30 つくばへ帰り反省会2次会(ラーメン)へ移動
ISUCON第2ラウンド開始
23:45 色々とやってないことはあったのでおもむろにPRを作り始める
f:id:euglena1215:20180917115924p:plain:w500
24:00 get_eventsでpublicなイベントだけ欲しい場合も一度全てのイベントを取得してからフィルタリングしていたのでSQLで行うように変更 #11
24:30 get_eventの修正後の処理がよくなかったので最適化した #12
25:20 get_eventをループ内で複数回呼んでるところ用にget_events_from_idsを作った、これが動けばN+1は全滅のはず #13
26:00 メモリが足りないとのことだったので不必要な変数の取り回しをなくした #14

おまけ

また、今回は自分のインターン先のWantedlyオフィスを会場として使わせてもらいました。

f:id:euglena1215:20180917123610j:plain

チームメンバーのうち1人は元インターン生、1人はWantedly全然関係ないという状況でしたが快諾してもらってありがとうございました!

f:id:euglena1215:20180917124431p:plain

所感

  • 初動が遅かった
    コードを書き始めたのが13:00ごろだった、このころには1万点弱に到達していたチームもちらほらいた気がする
  • 例年よりも作り込まれていてすごいと感じた
    フロントエンドはvue.jsで書かれていて時代の波を感じた
  • p debugよりもbinding.pryの方がやはり優秀
  • 帰ってからlocalで開発してみた結果、明らかにlocalで開発した方が実装速度が早いことが判明した(vim難しい)
  • 来年からは社会人として出るのでもっと力をつけていきたい

【ISUCON用】Redis Cheat Sheet

ISUCON予選が明日に迫ってきました。

Redisの操作が全く覚えられないのでまとめておきます。

セッティング

インストール

qiita.com

この辺とか見たらいい感じにできるのではないでしょうか(未確認)

使い方

# デフォルトは127.0.0.1:6379で繋がるはずなのでとりあえずこれで
def redis
   @redis ||= (Thread.current[:isu8_redis] ||= Redis.new(host: "127.0.0.1", port: 6379))
end

# keyはこんな感じでメソッドで隠してあげるとtypoが減ってよさそう
def redis_key_unread_count(channel_id)
  "isu7:unread_count:#{channel_id}"
end

# redisの操作もこんな感じでメソッドで隠してあげよう
def redis_increment_unread_count(channel_id)
  user_ids = redis_get_user_ids
  user_ids.each do |user_id|
    redis.hincrby(redis_key_unread_count(channel_id), user_id, 1)
  end
end

Redis豆知識

格納されているフォーマットについて

Redisには数値という概念がなく、一度全て文字列として格納されている。 (incrとかは文字列を数値に変換してから+1して文字列に戻すなどの操作をしているっぽい)

そのため、redis.get ...とかで取得した数値は毎回to_iする必要がある。

redis-cliでのデバッグ

  • とりあえず格納されているkeyを全部見たい
keys *
  • 一旦格納されてるデータ全部消したい
flushall

データ型

つらつら書いていこうかと思ったけどドキュメント見ればわかると思ったのでひとことに留めておきます。

String

標準的なkey value get, set, mget, mset, incr, incrby とかをよく使う気がします。

文字列型 — redis 2.0.3 documentation

# 使う可能性のあるコマンド一覧
SET(key, value)
GET(key) # なければnilを返す
GETSET(key, value)
MGET(key1, key2, ..., keyN)
SETNX(key, value)
MSET(key1, value1, key2, value2, ..., keyN, valueN)
MSETNX(key1, value1, key2, value2, ..., keyN, valueN)
INCR(key)
INCRBY(key, integer)
DECR(key, integer)
DECRBY(key, integer)

List

Listです。
両端からアクセスできる(rpush, lpush)けどisuconだとListは帯に短し襷に長し感があります。
Hashを使った方がいい場合の方が多そう。
idを保存しておいてllenとかでSQLのcountの擬似実装とかには使えるかも?

リスト型 — redis 2.0.3 documentation

# 使う可能性のあるコマンド一覧
RPUSH(key, string)
LPUSH(key, string)
LLEN(key)
LRANGE(key, start, end) # key, 0, -1 で全取得
LINDEX(key, index)
LSET(key, index, value)
LPOP(key)
RPOP(key)

Set

sorted setを使おう。setを使いたい場面ってisuconであんまり思いつかない。

セット型 — redis 2.0.3 documentation

Sorted Set

score付きのset。コマンド名に癖があるけどなんかすごい高機能。
DBのtableをそのままredisに載せようと思ったら

  1. Hashとしてそのままデータをredisに突っ込む
  2. Sorted Setでkeyをテーブル名、memberをhashのkey, scoreをDBのindexとして使う

みたいな感じになるんじゃないかな。(やったことない)
scoreの範囲を指定して取得とかできるので本当にtableと置き換えられる。
ただ、データの変形をせずにそのままテーブルの置き換えてパフォーマンスがどのくらい変わるのかはよく分かっていない。

ソート済みセット型 — redis 2.0.3 documentation

# 使う可能性のあるコマンド一覧
ZADD(key, score, member)
ZCARD(key) # memberの数を返す
ZSCORE(key, member) # 対応するmemberのscoreを返す
ZREM(key, member) # memberを削除
ZINCRBY(key, increment, member)
ZRANK(key, member) # 指定したmemberのスコア順にソートされた場合のindexが取得できる
ZREVRANK(key, member) # ZRANKの降順版
# indexで範囲指定してmemberを取得できる、WITHSCORESをつけると対応するscoreも取得できる
ZRANGE(key, start, end, [WITHSCORES])
ZRANGE(key, start, end, [WITHSCORES]) # ZRANGEの降順版
# scoreで範囲指定してmemberを取得できる。LIMIT, offsetも指定できるので実質SQL
ZRANGEBYSCORE(key, min, max, [LIMIT, offset, count, [WITHSCORES]])
ZCOUNT(key, min, max) # ZRANGEBYSCOREのCOUNT版

# 複数のsorted setから和集合、積集合を作る。共通するmemberのscoreは和をとる。
# ランキング計算とかするときにめちゃくちゃ便利なんだけど、複雑なので時間が余らないと使わない気がする?
ZUNIONSTORE(dstkey, N, k1, ..., kN, [WEIGHTS, w1, ..., wN], [AGGREGATE, SUM|MIN|MAX])
ZINTERSTORE(dstkey, N, k1, ..., kN, [WEIGHTS, w1, ..., wN], [AGGREGATE, SUM|MIN|MAX])

Hash

Hash。tableをそのままredisに持ってこようとするような荒技を使うときに使う。 操作方法自体はStringと大差ない。

ハッシュ型 — redis 2.0.3 documentation

# 使う可能性のあるコマンド一覧
HSET(key, field, value)
HGET(key, field)
HMSET(key, field1, value1, ..., fieldN, valueN)
HMGET(key, field1, ..., fieldN)
HINCRBY(key, field, value) # 負数を指定すればデクリメントもできる
HEXISTS(key, field)
HLEN(key)
HKEYS(key)
HVALS(key)
HGETALL(key)