Tech Hotoke Blog

IT観音とは私のことです。

AWS IAM インラインポリシーの設定方法

これは何?

インラインポリシーの設定方法を忘れてしまった AND 検索してもすぐに見つからなかったので備忘録として

設定方法

  1. 任意のロールを作成する
  2. 任意のロールを選択する
  3. 許可タグの許可ポリシーから、インラインポリシーを作成を選択
  4. 任意のポリシーを作成する

AWS SNSとSQSの連携についての学習メモ

これは何?

AWS SNS, SQSの連携周りを触ることになったので、その際の学習メモ。

AWS SNSって何?

  • Amazon Simple Notification Serviceの略
  • 配信者から受信者へのメッセージ配信を提供するマネージドサービス
  • 論理アクセスポイントおよび通信チャネルであるトピックという単位で管理される
  • 非同期的に通信する
  • A2A(aplication-to-application) メッセージングとA2P(aplication-to-person)通知が可能

A2Aメッセージング

  {
   "Type" : "Notification",
   "MessageId" : "63a3f6b6-d533-4a47-aef9-fcf5cf758c76",
   "TopicArn" : "arn:aws:sns:us-west-2:123456789012:MyTopic",
   "Subject" : "Testing publish to subscribed queues",
   "Message" : "Hello world!",
   "Timestamp" : "2012-03-29T05:12:16.901Z",
   "SignatureVersion" : "1",
   "Signature" : "EXAMPLEnTrFPa3...",
   "SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
   "UnsubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:123456789012:MyTopic:c7fe3a54-ab0e-4ec2-88e0-db410a0f2bee"
}

A2P(aplication-to-person)通知

標準および FIFO トピック

  • FIFO トピック:メッセージの順序を厳格に保つ。メッセージグループを定義し、メッセージの重複を防止する。FIFO トピックにサブスクライブするには、FIFO キューと標準キューの両方を使用可能。(AWS SESと連携する場合は2024/02/27時点ではサポートされていないので注意)
  • 標準トピック:メッセージの配信順序やメッセージの重複が重要でない場合。サポートされているすべての配信プロトコルは、スタンダードトピックにサブスクライブ可能。

メッセージの耐久性

  • 公開されたメッセージは、地理的に分離された複数のサーバーおよびデータセンターの間で保存されます。
  • サブスクライブされたエンドポイントが利用できない場合、Amazon SNS は配信の再試行ポリシーを実行します。
    • 配信の再試行ポリシー:サブスクライブされたエンドポイントをホストするシステムが利用できなくなったときにメッセージの配信を再試行する方法
    • 配信ポリシーが枯渇すると、Amazon SNS は配信の再試行を停止し、 メッセージを破棄 する (デッドレターキューが添付されていれば破棄されない)

    • 配信ポリシーの段階

      1. 即時の再試行段階(遅延なし) - 最初の配信の試行の直後に発生。この段階では再試行間の遅延時間はない。
      2. バックオフ前段階 - 即時の再試行段階の後。Amazon SNS は、バックオフ関数を適用する前に、この段階を使用して一連の再試行を試みる。この段階では、再試行回数と再試行間の遅延量を指定する。
      3. バックオフ段階 - この段階では、再試行バックオフ関数を使用して、再試行間の遅延を制御する。この段階では、最小遅延、最大遅延、および遅延が最小遅延から最大遅延までどれだけ速く増加するかを定義する再試行バックオフ関数を設定する。
      4. バックオフ後段階 - この段階はバックオフ段階の後。再試行回数とその間の遅延量を指定する。

デッドレターキュー

  • Amazon SNS サブスクリプションが受信者に正常に配信できないメッセージの送信先としての Amazon SQS キュー
  • どんなときにメッセージの配信が失敗する?
    • クライアントサイドの原因
      • 所有者がエンドポイント (Amazon SNS トピックにサブスクライブされている Lambda 関数など) を削除した場合
      • サブスクライブしているエンドポイントに添付されているポリシーを、Amazon SNS がエンドポイントにメッセージを配信できないように所有者が変更した場合
    • サーバーサイドの原因
      • サブスクライブされたエンドポイントを担当するシステムが利用できなくなった場合
      • Amazon SNS からの有効なリクエストを処理できないことを示す例外を返す場合
  • サーバー側のエラーが発生するとどんな挙動をする?

    • サーバー側のエラーが発生すると、一次バックオフ関数またはエクスポネンシャルバックオフ関数を使用して、失敗した配信を再試行する。
    • Amazon SQS または AWS Lambda によってバックアップされた AWS 管理のエンドポイントに起因するサーバー側エラーについては、Amazon SNS 23 日間にわたって 100,015 回まで配信を再試行する (そうなんだ。。。)
    • カスタマー管理のエンドポイント (HTTP、SMTP、SMS、モバイルプッシュなど) では、SMTP、SMS、およびモバイルプッシュエンドポイントに対して、内部配信再試行ポリシーを 6 時間にわたって 50 回に設定する。
  • デッドレターキューのしくみ

  • メッセージをデッドレターキューから移動する方法

    • Amazon SQS コンシューマロジックの作成を避ける
      • デッドレターキューをイベントソースとして Lambda 関数に設定して、デッドレターキューを吸い出します。
    • Amazon SQS コンシューマロジックを作成する
      • Amazon SQS APIAWS SDK、または AWS CLI を使用して、デッドレターキュー内のメッセージのポーリング、処理、削除を行うカスタムコンシューマーロジックを記述します。
  • デッドレターキューのモニタリングとログ記録方法

メッセージのアーカイブ、リプレイ、および分析

coming soon

メッセージ属性

coming soon

メッセージのフィルター処理

coming soon

メッセージセキュリティ

coming soon

【Cypress】cy.get()とcy.contains()の違い

前提

  • Cypress: 13.0.2

  • 以下のコードの違いは何でしょうか?
cy.get('tr:contains(User 1)')
cy.contains('tr', 'User 1')
  • こんな違いがある

    • cy.get()は一つ以上のDOM Elementを取得する
    • cy.contians()は一つのDOM Elementを取得する
  • つまり、以下のようになる。

cy.get('tr:contains(User 1)') // User 1を含む,table要素のtrを全て取得する
cy.contains('tr', 'User 1') // User 1を含む,tableからUser 1 の trを一件取得する

実際の挙動の確認や、なぜこのような動きになっているかの検証、じゃあ使い分けはどうすんの?な話は気が向いた時にやります🙏

【ネットワーク】SessionとCookieについて

What is this?

Sessionと Cookieについて言語化して整理したもの。メモ書き。

assumption

HTTP通信における話に焦点が当たりがち

  • Webブラウザに保存されたデータのこと
  • CookieはサーバーからのHTTPレスポンスのSet-Cookieヘッダーを使用してWebブラウザに送られ、テキストファイル形式で保存される
  • 保存されたCookieはクライアントからサーバーにリクエストするたびに自動送信される
  • 有効期限が設定されていないCookieは、Webブラウザが閉じられると一緒に削除される(「セッションCookie」とも言う)
  • 有効期限が設定されたCookieは、期限が過ぎるまではWebブラウザを閉じても削除されない
  • 「クッキー名=値」の形(1つのクッキーは4KBまで)
  • HTML DOMの一部としてアクセスできる
  • Session IDをCookieに格納する用途で使用されることが多い

Session

  • 一連の処理の始まりから終わりまでを表す概念(HTTP通信においては通信の確立から遮断までを指す)
  • セッション情報はサーバーに保存されることが多い
  • セッションはWebブラウザを閉じるまで保存する
  • リンクなどでページを移動しても内容を保持することができる

HTTPにおけるSessionとCookie

CookieにSession IDを格納することで、HTTPにステートフルな性質を持たせることを実現している。 HTTPはサーバーが一連の処理の状態などを記憶しないという性質(ステートレス)を持っているため、ログイン情報を記憶させる、ショッピングカートの商品情報を記憶させることが出来ない。

Sessionがそれらの情報を記憶して、CookieにSession IDを格納することでHTTP通信においてサーバーが一連の処理の状態などを記憶する性質(ステートフル)を付与することができる。

セキュリティ

  • セッションハイジャック:Session IDを第三者が傍受することで、Sessionが保持している認証情報などを使ってなりすますことができる
  • ラッキング・クッキー:Cookieはそのユーザからの他の要求と関連付けることができる。インターネット広告の配信において、バナー広告は、業者のサーバ(サードパーティー)へのリンクを介して画像を取得する形式が一般的である。クッキーはHTMLに限らず、画像にも設定することができる。HTTPではリンク元のURL情報も送信することが一般的なので、結果として広告業者は、同社を利用するすべてのサイトを対象としてそのユーザのアクセス履歴を把握することが可能になる。

参考

【DB】インデックスについて

What is this?

達人に学ぶDB設計徹底指南書を参考にインデックス、Explainによる実行計画の調査方法などをメモ的にまとめたもの

assumption

インデックスとは?

まず、DBのパフォーマンスを決める要素は主に以下の二つが存在する。

  • インデックス
  • 統計情報

その中でも、DBのパフォーマンス改善の手法としてインデックスが用いられることが最もポピュラー

インデックスは * 探すレコードを識別するデータの項目

  • 対象レコードの格納位置を示すポインタ

で構成されており、これを利用してデータの格納位置を特定し、その位置を直接アクセスする事で、表の検索速度を上げることが出来るもの。

インデックスがない場合は、検索を先頭の行から順に行うのでデータ量が多くなるほど検索に時間がかかる事がある。

【理由】

  • アプリケーションのコードに影響を与えない

  • テーブルのデータに影響を与えない

  • 性能改善の効果が高くコスパが良い

さらに、その中でもB-treeインデックスが最も基本(この他にもビットマップインデックス、ハッシュインデックスなどがある)なので、今回はB-treeインデックスを深堀する。

B-treeインデックスについて

特徴

下記の項目において、バランスが良く汎用性が高い

  1. 均一性:各キー値の間で検索速度にバラツキが少ない。
  2. 持続性:データ量の増加に比してパフォーマンス低下が少ない
  3. 処理汎用性:検索、挿入、更新、削除のいずれの処理もそこそこ速い。
  4. 非等値性:等号(=)に限らず、不等号(<、>、<=、>=)を使ってもそこそこ速い。
  5. 親ソート性:GROUPBY、ORDERBY、COUNT/MAX/MINなどなどソートが必要な処理を高速化できる。

引用:達人に学ぶDB設計徹底指南書

均一性

  • B-treeインデックスはどのリーフからもルートへの距離が均一の平衡木構造のため、検索を同じ計算量で行える
  • 更新削除などで平衡木構造が崩れることがあるので、常に検索の速度が一定となる訳ではないので注意が必要

持続性

  • 平衡木の高さは平均的に3〜4と平たい構造のため、データ量が増えても更新や検索にかかる時間や負荷は上がりにくいと言う性質

引用:達人に学ぶDB設計徹底指南書

処理汎用性

  • 検索、挿入、更新、削除いずれの処理もデータ量が増えても処理コストの差が少ないと言う性質

非等値性

  • =のみでなく>=やBETWEENのような範囲検索においても高速に行える性質
    • B-treeインデックスではキー値が必ずソートされるため、範囲検索では特定のノードよりも左というように探索範囲を絞り込むことが可能のため
  • <>などの否定条件による絞り込みは、特定のリーフ以外というような場合があるので非等値性の恩恵は受けられないので注意が必要

親ソート性

  • B-treeインデックスのキーを使ってソートを行うことでソート処理をスキップすることが出来る性質
  • RDBMSにおいてソート処理は別メモリが確保されるほどコストの高い処理という前提

B-treeインデックスの使いところ

  1. 規模の大きなテーブルに付与する
  2. カーディナリティ(列の値がどの程度の種類を持つか。例えば営業日など)の高い列に付与する:基準は特定のキーを指定して、5%程度に絞り込めること
  3. SQL文でWHERE句の選択条件、結合条件に使用されている列に作成する

ユニークインデックスについて

表内のデータの 2 つの行が同一のキー値を持たないようにすることによりデータ整合性の維持に貢献する索引

主キーとユニークインデックスの違い

  • 主キー(primary key)
    • テーブルのレコードを一意(ユニーク)に決定するための列名の組み合わせ
    • テーブルに一つしか持てない
    • 主キーは内部的にユニークインデックスが貼られる
  • ユニークインデックス(UNIQUE INDEX)
    • テーブルのレコードを一意(ユニーク)に決定するための列名の組み合わせ
    • テーブルの列(の組み合わせ)何箇所も持てる

EXPLAINでの調査について

SQLの実行計画(どのインデックスを使ってクエリを取得するかなど)を取得するためのステートメント

インデックスが正しく使われているか、クエリを効率的に処理出来ているかを確認する際に用いる

<見方>

pending....

【DB × Rails】トランザクション、排他制御について 時々 Rails

What is this?

一般的なトランザクション排他制御に関するまとめとそれをRailsで実現するためのメモ書き

Assumption

  • RDBSにおける話
  • Railsを使う前提

トランザクションについて

> ITの分野では、取引記録などの意味の他に、ソフトウェアの処理方式の一つで、互いに関連・依存する複数の処理をまとめ、一体不可分の処理単位として扱うことを指す場合が多い。
  • 要するに、相互に関係する処理をこれ以上分割できない一つのまとまりとして捉えたもの

    例)銀行口座の送金処理(出金と入金処理が不可分一体となっている)

  • トランザクションにおいてはACID特性が保たれる必要がある

ACID特性について

排他制御について

  • 代表的な例
    • ロック: 共有資源(DBやファイル)にロックをかけて同時にアクセスさせない方式
    • ミューテックス:「未使用」と「使用中」で判断し、共有資源を同時にアクセスさせない方式
    • セマフォ:同時にアクセスできる数を管理し、その人数までしか共有資源に対して同時にアクセスさせない方式。

今回取り扱うのはロックに限ります。

  • 代表的なロック
    • 楽観的ロック
    • 悲観的ロック
    • 共有ロック
    • 排他ロック

今回は、特によく使われる(印象の)悲観ロックと楽観ロックについてまとめます。(Active Recordに備わっているロック機構もこの二種類なので)

悲観ロックと楽観ロックについて

  • 悲観ロック

    • 前提:他者が同時更新は頻繁に起きる
    • 方法:SELECT 〜 FOR UPDATEなど
    • デメリット:ロックの解放漏れがあるとツラい(多分最近のFWはこの辺りもよしなにやってくれているので、意識しなくてもいいことが多いような気がする)
    • 備考:一般的に採用される。ECサイトのセールような決まった時間に同時多発的にアクセスが集中するような場合が典型的な気がする。
  • 楽観ロック

    • 前提:他者との同時更新は滅多に起きない
    • 方法:資源そのものにロックはかけずに、更新対象のデータがデータ取得時と同じ状態かを確認してから更新を行う
    • デメリット:更新されている場合に処理が全てロールバックされるため、処理待ちや処理のやり直しの負荷が高まる。
    • 備考:採用されるシーンはあまり多くない。同時アクセスが起こりづらいがデータの整合性は保たれねばならない場合に使う。例えば経理の管理画面など?

Railsにおける排他制御

楽観ロック

  • テーブルにlock_versionという名前のinteger型カラムを作成する
  • Active Recordは、レコードが更新されるたびにlock_versionカラムの値を1ずつ増やす
  • 更新リクエストが発生したときのlock_versionの値がデータベース上のlock_versionカラムの値よりも小さい場合、更新リクエストは失敗し、ActiveRecord::StaleObjectErrorエラーが発生する(例外処理が必要
  • ActiveRecord::Base.lock_optimistically = falseを設定するとこの動作をオフにできる
  • ActiveRecord::Baseには、lock_versionカラム名を上書きするためのlocking_column属性が用意されている

悲観ロック

  • リレーションの構築時にlockを使うと、選択した行に対する排他的ロックを取得できる
  • lockを用いているリレーションは、デッドロック(互いの処理がロックされて処理が進まなくなった状態)条件を回避するために通常トランザクションの内側にラップされる
例

Book.transaction do
  book = Book.lock.first
  book.title = 'Algorithms, second edition'
  book.save!
end
Mysql

SQL (0.2ms)   BEGIN
Book Load (0.3ms)   SELECT * FROM `books` LIMIT 1 FOR UPDATE
Book Update (0.4ms)   UPDATE `books` SET `updated_at` = '2009-02-07 18:05:56', `title` = 'Algorithms, second edition' WHERE `id` = 1
SQL (0.8ms)   COMMIT

SELECT 〜 FOR UPDATEが内部的に走ってるんですね

Railsガイドには他のロックを実装する方法も乗っているので折に触れてそちらも確認して行こうと思います。

参考

【DB】木構造

what is this?

テーブル設計の際に、木構造のデータを表現する方法をメモとしてまとめたもの

assumption

木構造とは?

こんなやつ

  • ノード 木の結節点
  • ルートノード 木の始点となるノード(treeはルートノードを一つしか持たない)
  • リーフノード 自分よりも下位のノードを持たない「終着点」のノード
  • 内部ノード 中間に位置するノード
  • 経路(path) ノードからノードへの道筋

隣接リストモデル(ナイーブツリー)

  • ノードのレコードに親ノードの情報(ポインタ)を持たせようとするもの
  • SQL木構造を表現する最も古くポピュラー
  • 更新・検索のクエリが複雑になりパフォーマンスが悪化する 例)

入れ子集合モデル

  • ノードを点ではなく、円として捉える
  • 座標を持たせる
  • 座標の絶対値が重要ではなく、包含関係であるという相対的な関係性が表現されていればよい
  • 検索が得意
  • 更新が苦手

検索

  • ルートノードを取得するクエリ
SELECT
*
FROM
role_relation AS rr
WHERE
rr.left_end = 1
;

  • リーフノードを取得するクエリ
SELECT
*
FROM
role_relation AS nleaf
WHERE NOT EXISTS
    (SELECT 
        * 
     FROM role_relation AS leaf
     WHERE 
        leaf.left_end > nleaf.left_end
     AND
        leaf.right_end < nleaf.right_end
    )
;

  • ツリーの深さを求めるクエリ
SELECT 
 children.`role`, COUNT(parent.`role`) AS 深さ
FROM
role_relation AS parent 
INNER JOIN role_relation AS children
ON children.left_end BETWEEN parent.left_end AND parent.right_end
GROUP BY 
children.`role`
;

更新

  • 円の数が増えれば増えるほど、更新する機会が多ければ多いほど負荷が高まる
  • 削除する場合はデータが歯抜けになっていても、包含関係が表現されていれば良いので比較的楽
  • 座標の値を実数まで含めれば更新の際に座標をずらす必要がなくなる(入れ子区間モデル)

上記画像の問題は、下記画像のように実数を用いることで整数と整数の間に無限にノードを追加することができる。 つまり、ノードを追加するたびに隣接するノードの座標をずらす必要がなくなる。

ただし、DBの制約上無限ではないため、いづれリソースは枯渇する。

DBの性能向上によってこの制約を過度に意識する必要がなくなれば、入れ子区間モデルを採用するのが木構造RDBで表現するのに最も良いのでは?

閉包テーブルモデル(クロージャーテーブルモデル)

pending...

経路列挙モデル

pending....

参考