forget for get

覚えるために忘れる

phpredisまとめ

PHPでRedisを扱う場合に使うphpredisのまとめ。

redis-cliコマンドとほとんど同じなので、説明を省略しています。
redis-cliコマンドを理解してない人は先にこちらを読んでください。

lightwill.hatenablog.com


ほとんど同じだけど微妙に違う。(引数指定でより拡張されてる)
 
phpredisのgithubにあるドキュメントを参考にしました。

github.com

 

基本

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->get('key');
$redis->set('key', 'value');
$redis->setEx('key', 3600, 'value');
$redis->pSetEx('key', 100, 'value');
$redis->setNx('key', 'value');
//setで書くこともできる
$redis->set('key','value', 10); //有効期限10秒
$redis->set('key', 'value', ['nx', 'ex'=>10]); //キーが存在してなかったら設定
$redis->set('key', 'value', ['xx', 'px'=>1000]); //キーが存在してたら設定
 
$redis->del('key3');
$redis->del(['key3', 'key4']);
$redis->unlink(['key1', 'key2']); //Redis >= 4.0.0
$redis->exists('key');
$redis->exists(['foo', 'bar', 'baz]);
 
$redis->incr('key1');
$redis->incr('key1', 10);
$redis->incrBy('key1', 10);
$redis->incrByFloat('key1', 1.5);
$redis->decr('key1');
$redis->decr('key1', 10);
$redis->decrBy('key1', 10);
 
$redis->expire('x', 3);
$redis->pexpire('x', 3000);
$redis->expireAt('x', time() + 3);
$redis->pexpireAt('x', time() . 500);
$redis->ttl('key');
$redis->persist('key');
 
$redis->mGet(['key1', 'key2', 'key3']);
$redis->mSet(['key0' => 'value0', 'key1' => 'value1']);
$exValue = $redis->getSet('x', 'lol');
$redis->append('key', 'value2');
$redis->randomKey();
$redis->keys('*');
$redis->keys('user*');
$redis->type('key');
$redis->strlen('key');

$redis->getRange('key', 0, 5);
$redis->setRange('key', 6, "redis");
$redis->getBit('key', 0);
$redis->setBit('key', 5, 1);
$redis->rename('x', 'y');
$redis->move('x', 1);
$redis->select(1);
$val = $redis->dump('foo');
$redis->restore('bar', 0, $val);
 

ハッシュ

$redis->hSet('lightwill', 'hp', 100);
$redis->hGet('lightwill', 'hp');
$redis->hSetNx('lightwill', 'hp', 200);
$redis->hGetAll('lightwill');
$delCount = $redis->hDel('lightwill','hp','pow');
$redis->hLen('lightwill');
$redis->hExists('lightwill', 'hp');
$redis->hKeys('lightwill');
$redis->hVals('lightwill');
$redis->hMSet('lightwill', ['def' => 30, 'spd' => 50]);
$redis->hMGet('lightwill', ['hp', 'spd']);
$redis->hIncrBy('lightwill', 'hp', -1);
$redis->hIncrByFloat('lightwill','hp', -0.5);
$redis->hStrLen('lightwill','name');
 

リスト

$redis->lPush('key1', 'D'); //先頭(left)に追加
$redis->lPush('key1', 'C', 'B', 'A');
$redis->lPushx('none', 'A'); //キーがなければ何もしない
$redis->lRange('key1', 0, -1);
$redis->lPop('key1'); //A
$redis->rPush('key1', 'A'); //末尾(right)に追加
$redis->rPushX('none', 'A');
$redis->rPop('key1');
$redis->lLen('key1');
$redis->lRem('key1', 'A', 2); //左から2個Aを削除。-なら右から。0ならすべて。
$redis->lInsert('key1', Redis::AFTER, 'A', 'X');
$redis->lInsert('key1', Redis::BEFORE, 'C', 'X');
$redis->lindex('key1', 0); //-なら右から
$redis->lSet('key1', 0, 'X');
$redis->lTrim('key1', 0, 1);
$redis->rPopLPush('key1', 'key2')
$redis->blPop('key1', 'key2', 10);
$redis->brPop('key1', 'key2', 10);
$redis->bRPopLPush('srckey', 'dstkey', 10);
 

セット

$redis->sAdd('larc' , 'hyde');
$redis->sAdd('larc' , 'ken', 'tetsu', 'sakura');
$redis->sMembers('larc')
$redis->sCard('key1'); //件数取得
$redis->sIsMember('larc', 'hyde');
$redis->sRem('larc', 'sakura');
$redis->sRandMember('larc');
$redis->sRandMember('larc', 2);
$redis->sRandMember('larc', -5); //重複ありで5件
$redis->sPop('larc'); //ランダムに取得して削除
$redis->sPop('larc', 2);
$redis->sMove('larc', 'vamps', 'hyde');
$redis->sDiff('saiueo', 'sai', 'su'); //eo
$redis->sDiffStore('seo', 'saiueo', 'sai', 'su');
$redis->sInter('saiueo', 'sai'); //ai
$redis->sInterStore('sai2', 'saiueo', 'sai');
$redis->sUnion('sai', 'su'); //aiu
$redis->sUnionStore('saiu', 'sai', 'su');
 

ソート済みセット(スコアで順位付け、メンバーの重複なし、同じスコアはあり)

$redis->zAdd('ranking', 100, 'melon');
$redis->zAdd('ranking', 120, 'melon'); //スコア更新
$redis->zScore('ranking', 'melon');
$redis->zCard('ranking'); //件数取得
$redis->zIncrBy('ranking', 2.5, 'melon'); //キーがなかったら追加
$redis->zRem('ranking', 'pine', 'apple');
$redis->zRange('ranking', 0, -1);
$redis->zRange('ranking', 0, -1, true); //スコアも取得
$redis->zRevRange('ranking', 0, -1); //降順
$redis->zCount('key', 60, 80);
$redis->zCount('key', '(60', '(80'); //60 <、< 80
$redis->zCount('key', '-inf', '+inf'); //システムの最小値と最大値
$redis->zRangeByScore('ranking', 60, 80);
$redis->zRevRangeByScore('ranking', 80, 60, ['withscores' => TRUE]);
$redis->zRangeByScore('ranking', -inf, inf, ['limit' => [0, 2]]);
$redis->zRemRangeByScore('ranking', '-inf', 10); //10以下は削除
$redis->zRangeByLex('ranking','-','[momo') //momo以下
$redis->zRangeByLex('ranking','(momo','+') //momoより上
$redis->zRangeByLex('ranking','-','[momo',1,2) //limit指定
$redis->zRank('ranking', 'melon');
$redis->zRevRank('ranking', 'melon');
$redis->zRemRangeByRank('ranking', 80, 100); //81位から101まで削除
$redis->zinterstore('year', ['month1', 'month2']); //積集合の合計
$redis->zinterstore('year', ['month1', 'month2'], [1, 2]); //各スコアを倍にして重みづけ
$redis->zinterstore('year', ['month1', 'month2'], [1, 2], 'max');
$redis->zinterstore('year', ['month1', 'month2'], [1, 2], 'min');
$redis->zunionstore('year', ['month1', 'month2']); //和集合 weights、aggregateも同じ

redis-cliコマンドまとめ

redis-cliコマンドの自分用のまとめです。
 
参考記事はこちら。

qiita.com

基本

set name lightwill
get name
setnx name lightwill2
setnxだと上書きできない
 
有効期限を指定 5秒
setex name 5 lightwill
psetex name 5000 lightwill
有効期限を確認
ttl name
pttl name
 
取得してから更新
getset name light
 追記
set str abc
append str def //abcdef
バイト数取得(日本語だと文字数にならない)
strlen name
日本語が文字化けしないようにする
redis-cli --raw
 
複数
mset name lightwill age 35
mget name age
msetnx name lightwill2 age 135 blood a
既存キーがあると新規キーも登録されない
 
加算減算
set age 30
incr age //31
incrby age 2 //33
decr age //32
decrby age 2 //30
incrbyfloat age 0.5 //30.5
incrbyfloat age -0.5 //30
 

ハッシュ

hset lightwill hp 100
hset lightwill pow 20
hget lightwill hp
hsetnx lightwill hp 200
hgetall lightwill
hdel lightwill pow
hlen lightwill
hexists lightwill hp
hkeys lightwill
hvals lightwill
hmset lightwill def 30 spd 50
hmget lightwill hp spd
hincrby lightwill hp -1
hincrbyfloat lightwill hp -0.5

 

セット(順番のない、重複のないメンバーの集合)

sadd larc hyde
sadd larc ken tetsu sakura
smembers larc
scard larc //件数取得
sismember larc hyde
srem larc sakura
srandmember larc
srandmember larc 2
srandmember larc -5 //重複ありで5件
spop larc //ランダムに取得して削除
spop larc 2 //件数指定はバージョン2.6、2.8、3.0では不可
smove larc vamps hyde

sdiff saiueo sai su //eo
sdiffstore seo saiueo sai su
sinter saiueo sai //ai
sinterstore sai2 saiueo sai
sunion sai su //aiu
sunionstore saiu sai su
 

ソート済みセット(スコアで順位付け、メンバーの重複なし、同じスコアはあり)

zadd ranking 100 melon
zadd ranking 80 mango 80 momo 70 pine
zadd ranking 120 melon //スコア更新
zscore ranking melon
zcard ranking //件数取得
zincrby ranking 10 melon
zincrby ranking -10 pine
zincrby ranking 50 apple //追加される
zrem ranking pine
zrem ranking pine apple
zrange ranking 0 2
zrange ranking 0 2 withscores //スコアも取得
zrange ranking 0 -1 //すべて
zrevrange ranking 0 -1 //降順
zcount ranking 60 80
zcount ranking (60 (80 //60 <、< 80
zcount ranking -inf +inf //システムの最小値と最大値
zrangebyscore ranking 60 80
zrevrangebyscore ranking 80 60 withscores
zrevrangebyscore ranking inf -inf limit 0 2
zremrangebyscore ranking -inf 10 //10以下は削除
zrank ranking melon
zrevrank ranking melon
zremrangebyrank ranking 80 100 //81位から101まで削除

zinterstore year 2 month1 month2 //積集合の合計
zinterstore year 3 month1 month2 month3 weights 1 2 3 //各スコアを倍にして重みづけ
zinterstore year 2 month1 month2 aggregate max
zinterstore year 2 month1 month2 aggregate min
zunionstore year 3 month1 month2 month3 //和集合 weights、aggregateも同じ
 

リスト(順番保持、重複あり)

lpush list a //先頭(left)に追加
lpush list b c d
lpushx none a //キーがなければ何もしない
lrange list 0 -1
lpop list //d
rpush list d //末尾(right)に追加
rpushx none a
rpop list //d
llen list
lrem abababa 1 a //bababa
lrem abababa -1 a //babab
lrem abababa 0 a //bbb
lpush aiueo a i u e o //oeuia
linsert aiueo after u k //oeukia
linsert aiueo before u s //oesukia
lindex abcde 2 //c
lindex abcde -2 //b
lset abcde 0 z //zdcba
ltrim abcde 1 3 //dcb
rpoplpush abc def //cb afed
 
blpop list1 list2 0 //どれかから値を取得するまでブロック
brpop list1 list2 0
brpop list3 3 //3秒待つ
brpoplpush list1 list2 0 //list1から2へ移動させるまでブロック
 

その他

exists list1
exists list1 list2 list3 //個数が返ってくる
type list1
rename bakarudi summers //変更先のキーがあったら上書き
renamenx bakarudi summers
del list

expire list1 5 //期限を設定
expireat list2 1592382942 //unixtime指定
pexpire list1 5000
pexpireat list 1592383942999
persist list //期限を削除
randomkey //ランダムにキーを返す
keys list* //パターンに合うキーを取得
 
部分操作
set str abcdefg
getrange str 0 2 //abc
getrange str 0 -1 //abcdefg
getrange str -3 -1 //efg
setrange str 2 CD //abCDefg
setrange str 7 hi //abCDefghi
setrange str 11 lm //abCDefghi\x00\x00lm 間にzero-bytesが入る
 
ビット操作
setbit mybit 0 1
getbit mybit 0
bitcount mybit
bitop and result bit1100 bit1010 //result=1000
bitop or result bit1100 bit1010
bitop xor result bit1100 bit1010
bitop not result bit1100
 
dump larc //シリアライズしたデータ
restore larc2 0 "\x02\x02\x04yuki\x05tetsu\b\x00#\xfcO\xc2n\x9f*\x8b"
move larc 1 //別のDBへ移動(デフォは0)
select 1

Laravel EloquentでModelをgetしたときに配列のキーをidにしたい

たとえば、

$channels = Channel::get();
[0]=>"id"=>4,"name"=>"日本テレビ"
[1]=>"id"=>8,"name"=>"フジテレビ"

フジテレビが欲しいときに、

$channels->where('id',8);

としていたのを

$channels[8];

で取れるようにしたい

$channels = Channel::get()->keyBy('id');
[4]=>"id"=>4,"name"=>"日本テレビ"
[8]=>"id"=>8,"name"=>"フジテレビ"

ロリポップでLaravelをSSHを使わずにFTPでアップロードする

ロリポップでLaravelを使いたい

ロリポップでLaravelを使おうと、アプリケーションのディレクトリをそのままFTPでアップロードすると、
vendor配下のファイルが多過ぎて死ぬほど時間がかかる。

SSHを使わずに

SSHが使えると、composerでlaravelをインストールできるけど、
スタンダード未満のプラン(エコノミー、ライト)だとSSHは使えない。

zipをFTPアップロードして解凍する

そこで、アプリケーションのディレクトリをzipで圧縮してFTPでアップロード、
それを解凍しました。

解凍はphpからunzipコマンドを実行。
以下のようなファイルを作って、ブラウザからアクセス。

unzip.php

<?php
    $zipfile = "laravel.zip";
    return shell_exec("unzip $zipfile");

解凍が終わったら、念のためunzip.phpは削除しておく。

phpからコマンド使えるなら、unzipじゃなくて、composerでlaravelをインストールできるのでは、、

GitExtensionsをインストールして日本語化

githubからインストーラをダウンロードしてインストール

Downloadsの項目から最新バージョンのダウンロードページへ行く。

Windowsなら.msiを選べばいい。

github.com

 

日本語化する

上記ダウンロードページからSource code(zip)をダウンロードする。

GitUI/Translation/配下にある

Japanese.Plugins.xlf
Japanese.gif
Japanese.xlf

をGitExtensionsのインストール先のTranslation配下に置く。

 

GitExtensionsを起動して、

ツール(tools)→settings→外観(appearance)で

言語(language)をJapaneseにする。

 

 

 

Chainer初心者向け入門

Chainerビギナーズハンズオンに行ってきました。

chainer.connpass.com

 

ディープラーニングフレームワークChainerを使ってみるハンズオン。
GoogleColaboratoryという無料で使えるオンライン環境でサクッと試せました。

2時間ちょっとで画像判定ができるようになりました。

 

以下の動画とスライドで追体験できるので、ディープラーニングに触れてみたい方はぜひ。

youtube ライブ配信

スライド

www.slideshare.net

 notebook

 https://chainer-colab-notebook.readthedocs.io/ja/latest/notebook/hands_on/chainer/begginers_hands_on/00_How_to_use_chainer_on_colaboratory.html

 

 

 

Cookpad Tech Kitchen #20 クックパッドのマイクロサービスプラットフォーム現状

Cookpad Tech Kitchen #20 クックパッドのマイクロサービスプラットフォーム現状

cookpad.connpass.com

 こちらのイベントに参加してきました。

場所は恵比寿ガーデンプレイス
11月だというのに、クリスマスツリーが!

f:id:lightwill:20181129213137j:plain

 

小野大器「サービスメッシュの構築と運用」

サービスメッシュって概念も初めて聞いたのですが、
Istio,envoy,Prometheus,Grafanaなど初めて聞くツールがたくさん出てきました。
スライドが英語で書かれているし、ほぼほぼ何言ってるか理解できず、
単語だけ拾って後でググろうと思って聞いてました。

クックパッドブログに今回の内容と同じようなものがありました。

Service Mesh and Cookpad - クックパッド開発者ブログ

 

岩間 雄太 「gRPC in Cookpad

マイクロサービスではRESTよりRPC
Protocol Buffers サービスのインターフェース定義 IDLで記述
RubyでgRPCだとgrpc gem
→CPUを使いきれない、Graceful Shutdownがない
→自作でgriffin
今後はカナリアリリースとかできるようにしたい

関係ないけど、以下の記事も参考になるかと。

REST APIの設計で消耗している感じたときのgRPC入門 - Qiita

 

鈴木 康平「Amazon ECS の安定運用のために」

hako(自作ツール)でデプロイ
オンデマンドとスポットは1:4くらい
スポットインスタンスの方が安い
Fargateは起動が遅い→起動したままのWebならいいけど、バッチジョブだとつらい
自前のオートスケール

コンテナのログはfluentd→S3→Athena AWS Glueで目次更新
CloudWatch Logsだとログが膨大だとリアルタイムで入りきらない、S3に比べて高価

モニタリングはcAdvisorでメトリクス取得
Prometheus→Grafana

 

QA

マイクロサービス化するタイミングは?
組織が大きくなってきたら、コミュニケーションコストが高くなってきたら。
2000人とかなら有効。
あるいは200人とかでも将来2000人目指すならやってもいい。
マイクロサービス化するにはコストがかかるので、コミュニケーションコストとの兼ね合いで判断。

 

懇親会

f:id:lightwill:20181129213321j:plain

さすがクックパッドさん、おいしい料理でした。

 

感想

内容がハイレベル過ぎてなかなかついていけなかったですが、良い刺激を受けました。
私もシアトルで登壇できるエンジニアになりたいものです。。