ウェブ開発者向けインフラの基本2


## 分散処理とロックと、待ちが発生する仕組み

あなたが忙しいカフェのバリスタだと想像してください。カウンターにはコーヒーを待つお客さんがたくさん並んでいます。一度に一人ずつしかコーヒーを淹れられないとしたら、どうなるでしょう？お客さんは長い列を作り、待ち時間にイライラしてしまいます。しかも、列が長くなればなるほど、店が混乱して破綻してしまうかもしれません。これが、データベースやウェブサーバーでロックが発生する状況と似ています。複数の処理が同時に同じデータにアクセスしようとすると、誰かがロックを取得するまで他の人は待たなければならないのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60530/9678d63c-0742-4ccb-4723-cff8522ab2f8.png)



### 分散処理
分散処理。複数のコンピューターが協力して仕事を片付ける仕組み。仕事を分担。スピードアップ。負荷分散。サーバーに優しい。

```mermaid
sequenceDiagram
    participant ユーザーA
    participant ユーザーB
    participant ユーザーC
    participant 分散処理システム

    ユーザーA->>分散処理システム: タスクを実行
    ユーザーB->>分散処理システム: タスクを実行
    ユーザーC->>分散処理システム: タスクを実行
    分散処理システム->>ユーザーA: 結果を返す
    分散処理システム->>ユーザーB: 結果を返す
    分散処理システム->>ユーザーC: 結果を返す
```

### ロック
ロック。データを守るための鍵。複数の処理が同時に同じデータをいじると混乱。ロックをかけて、一度に一つの処理しかデータをいじれないようにする。データの一貫性を保つ。

```mermaid
sequenceDiagram
    participant ユーザーA
    participant ユーザーB
    participant データ

    ユーザーA->>データ: ロックを取得
    データ-->>ユーザーA: ロック取得成功
    ユーザーA->>データ: データを変更中
    ユーザーB->>データ: ロックを取得（待機中）
    note right of ユーザーB: Aが終わるまで待つ
    ユーザーA->>データ: データ変更完了
    ユーザーA->>データ: ロックを解除
    データ-->>ユーザーB: ロック取得成功
    ユーザーB->>データ: データを変更
    ユーザーB->>データ: ロックを解除
```

### SQL Server や MySQLのロックと分散処理

SQL Server や MySQLは、テーブルの更新に対してロックを発生させる。行が別なら分散処理を行うことができる。

#### テーブル例

| 行ID | データ |
|------|--------|
| 1    | データ1 |
| 2    | データ2 |
| 3    | データ3 |
| 4    | データ4 |
| 5    | データ5 |

```mermaid
sequenceDiagram
    participant ユーザーA
    participant ユーザーB
    participant SQLサーバー

    ユーザーA->>SQLサーバー: 行ID 1 を更新（ロック取得）
    SQLサーバー-->>ユーザーA: ロック取得成功
    ユーザーB->>SQLサーバー: 行ID 3 を更新（ロック取得）
    SQLサーバー-->>ユーザーB: ロック取得成功
    ユーザーA->>SQLサーバー: 行ID 1 の更新完了（ロック解除）
    ユーザーB->>SQLサーバー: 行ID 3 の更新完了（ロック解除）
```

### SQL Server や MySQLのロックと分散処理

SQL Server や MySQLは、テーブルの更新に対してロックを発生させる。行が別なら分散処理を行うことができるが、同じ行を更新しようとすると競合が発生する。

#### テーブル例

| 行ID | データ |
|------|--------|
| 1    | データ1 |
| 2    | データ2 |
| 3    | データ3 |
| 4    | データ4 |
| 5    | データ5 |

#### 行が別なので競合しない場合

```mermaid
sequenceDiagram
    participant ユーザーA
    participant ユーザーB
    participant SQLサーバー

    ユーザーA->>SQLサーバー: 行ID 1 を更新（ロック取得）
    SQLサーバー-->>ユーザーA: ロック取得成功
    ユーザーB->>SQLサーバー: 行ID 3 を更新（ロック取得）
    SQLサーバー-->>ユーザーB: ロック取得成功
    ユーザーA->>SQLサーバー: 行ID 1 の更新完了（ロック解除）
    ユーザーB->>SQLサーバー: 行ID 3 の更新完了（ロック解除）
```

この図では、ユーザーAが行ID 1 を更新中にロックを取得し、ユーザーBが行ID 3 を更新中にロックを取得しています。行が異なるため、同時に更新が可能です。

#### 行が競合する場合

```mermaid
sequenceDiagram
    participant ユーザーA
    participant ユーザーB
    participant SQLサーバー

    ユーザーA->>SQLサーバー: 行ID 2 を更新（ロック取得）
    SQLサーバー-->>ユーザーA: ロック取得成功
    ユーザーB->>SQLサーバー: 行ID 2 を更新（ロック取得待機）
    note right of ユーザーB: ロック待機中
    ユーザーA->>SQLサーバー: 行ID 2 の更新完了（ロック解除）
    SQLサーバー-->>ユーザーB: ロック取得成功
    ユーザーB->>SQLサーバー: 行ID 2 の更新完了（ロック解除）
```

この図では、ユーザーAとユーザーBが同時に行ID 2 を更新しようとしています。ユーザーAがロックを取得中にユーザーBが待機しており、ユーザーAがロックを解除するまでユーザーBは更新できません。

---

はなしはかわります。

### 昔のCGIとロック

昔のCGIの時代は、ウェブサーバー上でCGIスクリプトが動いていました。これによるファイル操作などは分散処理ではなかったことが多く、例えばファイル更新処理などを行う場合は、ユーザーが増えると応答時間がどんどん伸びてしまいました。応答時間が伸びるだけならいいですが、待ちを発生させるだけでも、ウェブサーバーはリソースをたくさん消費するため、サーバーダウンにつながることもありました。

```mermaid
sequenceDiagram
    participant ユーザー1
    participant ユーザー2
    participant CGIスクリプト
    participant ファイル

    ユーザー1->>CGIスクリプト: アクセス開始
    CGIスクリプト->>ファイル: ファイルをロック
    CGIスクリプト->>ファイル: 書き換え操作
    CGIスクリプト->>ファイル: ロック解除
    CGIスクリプト->>ユーザー1: レスポンス返却

    ユーザー2->>CGIスクリプト: アクセス開始（待機中）
    CGIスクリプト->>ファイル: ファイルをロック
    CGIスクリプト->>ファイル: 書き換え操作
    CGIスクリプト->>ファイル: ロック解除
    CGIスクリプト->>ユーザー2: レスポンス返却
```



---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60530/63c7eef3-8f4d-9a54-6898-d2d454a6faa6.png)


分散処理って、ユーザー数が予測できないウェブシステムにはめちゃくちゃ重要なんです。でも、社内で使うイントラのウェブアプリの場合、ユーザーが一人だけならそこまで気にしなくてもいいんですよね。家で一人で開発していると、ついつい性能とか同時接続性のことを忘れがちですよね。だから、注意してくださいね。



## 最近のメモ

 
 [**ウェブ開発者向けインフラの基本**](https://qiita.com/dms-matthew/items/22440f59370e84be3f55)
 
[**ウェブ開発者向けインフラの基本2**](https://qiita.com/dms-matthew/items/3db4fd1c4328e4efffd3)

[**ウェブ開発者向けインフラの基本3**](https://qiita.com/dms-matthew/items/0b7900723e58003f86d6)
 
[**ウェブ開発者向けインフラの基本4**](https://qiita.com/dms-matthew/items/8bbdc0bf51002fbd8603)