Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeCrafters にチャレンジして PHP で Redis を作ってみる

gennei
March 24, 2023

CodeCrafters にチャレンジして PHP で Redis を作ってみる

みなさんは CodeCrafters というサイトを知っていますか?
このサイトは少し複雑なソフトウェアを作りながらプログラミングを学ぶことができるサイトです。
このサイトではRedisやDockerコマンド、SQLite などの基本的な機能を作るような練習問題があります

Redisを作る課題にチャレンジしました。そこで学んだことを話そうとおもいます。

■話すこと
・CodeCraftersってどんなサイトなのか
・CodeCrafters で Redis を作る手順について
・Redisのプロトコル(RESP)について

■ターゲット
・PHPの基本的な文法はわかるけど次に何をするか悩んでいる人
・PHP以外の言語でなにか作りたいけど作りたいものがない人

gennei

March 24, 2023
Tweet

Other Decks in Programming

Transcript

  1. CodeCrafters にチャレンジして
    PHP で Redis を作ってみる
    2023/03/24 @PHPerKaigi 2023

    げんえい (@gennei)


    View Slide

  2. こんなことで悩んでいたりしませんか?

    🤔🤔🤔

    2

    View Slide

  3. 悩み

    ● チュートリアルを終えたけど次なにをしたらいいかわからない

    ● WAFを使ってアプリは作れるけど0から作る自信がない

    ● PHP以外の言語を学んでみたいけどなにをしたらいいかわか
    らない

    ● 複雑なアプリケーションの裏側を知りたい

    3

    View Slide

  4. 今日はそんな悩みを

    解決できるかもしれない話をします

    4

    View Slide

  5. 自己紹介

    $profile = [

    '名前' => 'げんえい', 

    '所属' => 'カオナビ', 

    'ロール' => 'テックリード', 

    '好き' => ['コーヒー', 'サンフレッチェ広島', '読書'],

    ];

    5

    View Slide

  6. 6

    View Slide

  7. Code Crafters とは

    ● 複雑なソフトウェアを作る練習ができるサイト

    ● “車輪の再発明” を通してプログラミングを学べる

    7

    View Slide

  8. どんなものを作るのか

    ● Redis

    ● Docker

    ● Git

    ● SQLite

    ● grep

    ● etc…

    8

    View Slide

  9. 9

    View Slide

  10. CodeCrafters の学習サイクル

    1. アカウント作成

    2. 課題のリポジトリをClone

    3. 課題に沿ってコードを書く

    4. PUSH すると CI が動きパスすると次の課題に進む

    10

    View Slide

  11. PHP で Redis を作ってみました

    11

    View Slide

  12. Redis

    ● インメモリデータストア

    ● Key-Value でデータ取得、保存

    ● 有効期限の設定ができる

    12

    View Slide

  13. RESPとは

    ● Redis Serialization Protocol の略

    ● 特徴 

    ○ Simple to implement.(実装が簡単)

    ○ Fast to parse. (パースが速い)

    ○ Human readable. (人間が読むことができる)

    13

    View Slide

  14. *2\r\n$4\r\nECHO\r\n$3\r\nphp\r\n

    14

    View Slide

  15. RESPの読み方

    先頭の記号はデータのフォーマットを表す

    15
    記号
 意味

    +
 Simple String (改行コード許容しない) 

    -
 Error

    :
 Interger

    $
 Bulk String (改行コード許容する。バイナリセーフ。) 

    *
 Array


    View Slide

  16. Simple String

    ● +PING\r\n

    ○ + から始まり \r\n で終わる

    16

    View Slide

  17. Error

    ● -Error message\r\n

    ○ - で始まり \r\n で終わる

    17

    View Slide

  18. Integer

    ● :1000\r\n

    ○ : で始まり \r\n で終わる

    18

    View Slide

  19. Bulk String

    ● $5\r\nhello\r\n

    ○ $ は Bulk String を表す

    ○ $ の次の数字は文字列の長さを表す

    19

    View Slide

  20. Array

    ● *2\r\n$4\r\nECHO\r\n$3\r\nphp\r\n

    ○ * は Array を表す

    ○ * の次の数字は配列のサイズ

    ○ $ の次の数字は文字列長

    20

    View Slide

  21. *2\r\n$4\r\nECHO\r\n$3\r\nphp\r\n

    21
    *2 = 配列のサイズが2

    $4 = 4文字(ECHO)

    $3 = 3文字(php)


    View Slide

  22. RESP完全に理解した

    22

    View Slide

  23. CodeCraftersチャレンジしてみる

    23

    View Slide

  24. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    24

    View Slide

  25. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    25

    View Slide

  26. 1. 6379 port で待受

    ● cloneしたらすでにコードが書かれているので詳しく知らなくても大丈
    夫

    ● 主に socket_xxx() 系の関数を利用します

    ○ socket_create() // ソケット作成

    ○ socket_bind() // 作成したソケットをaddress、portにバインド

    ○ socket_listen() // 接続待ち

    ○ socket_accept() // ソケットへの接続許可

    26

    View Slide

  27. 27

    View Slide

  28. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    28

    View Slide

  29. 2. ping を送ると pong が返ってくる

    ● +ping\r\n がクライアントから送られてくる

    ● +pong\r\n をクライアントへ返せば終わり

    ● レスポンスを返すときは socket_write() を使う

    29

    View Slide

  30. 30

    View Slide

  31. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    31

    View Slide

  32. 3. 複数回コマンド対応

    ● while で無限ループしてコマンドを待つ

    32

    View Slide

  33. 33

    View Slide

  34. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    34

    View Slide

  35. 4. 並列でクライアントからのリクエスト処理

    35
    ● どのクライアントからの通信かを判定してレスポンスを返す

    ○ JavaScript で作っているとなにもしなくていいぞ


    View Slide

  36. 36

    View Slide

  37. 37

    View Slide

  38. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    38

    View Slide

  39. 5. ECHO コマンドの実装

    ● RESP フォーマットをパースして文字列を取得

    ● socket_write() で入力された文字列を返す

    39

    View Slide

  40. *2\r\n$4\r\nECHO\r\n$5\r\nworld\r\n

    40
    *2 = 配列のサイズが2

    $4 = 4文字(ECHO)

    $5 = 5文字(world)


    View Slide

  41. 41

    View Slide

  42. *2\r\n$4\r\nECHO\r\n$5\r\nworld\r\n

    42
    *2 = 配列のサイズが2

    $4 = 4文字(ECHO)

    $5 = 5文字(world)


    View Slide

  43. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    43

    View Slide

  44. 6. SET, GETコマンドの実装

    ● PHPの1プロセスが起動している状態なのでストレージとなる
    シングルトンを作成し読み書きする

    44

    View Slide

  45. 45

    View Slide

  46. 7つのステップ

    1. 6379 port で待受

    2. ping を送ると pong が返ってくる

    3. 複数回コマンド対応

    4. 並列でクライアントからのリクエスト処理

    5. ECHO コマンドの実装

    6. SET, GETコマンドの実装

    7. Expire の実装

    46

    View Slide

  47. 7. Expire の実装

    ● Expire

    ○ SET KEY VALUE 単位 (時間) で指定する

    ○ 指定は ex(秒) または px(ミリ秒) で指定する

    ○ ex) SET lang php px 100

    47

    View Slide

  48. 48

    View Slide

  49. 49

    View Slide

  50. 時間があればデモ

    50

    View Slide

  51. まとめ

    ● RedisはRESPがわかれば作れる!

    ● 順番に小さく作ることでコア機能は作れる

    ● 新しい言語を習得するときはCodeCraftersでやってみるのい
    いかもしれない

    51

    View Slide

  52. 参考文献

    ● Redis 公式ドキュメント

    ○ https://redis.io/docs/

    ● 実践Redis入門 技術の仕組みから現場の活用まで

    ○ https://gihyo.jp/book/2022/978-4-297-13142-5

    52

    View Slide

  53. おわり

    53

    View Slide

  54. おまけ

    54

    View Slide

  55. RESP3

    ● Redis6.0 以降ではRESP3を使うことができる

    ● 主な変更点

    ○ CRLF -> LF に変更

    ○ データ型の追加

    ■ Map、Set、Boolean、etc..

    55

    View Slide