SQSのdeduplication Idについてよくわかっていなかったのでメモ

deduplication Idの指定にFIFOキューである必要はあるか?

概要

  • deduplication Idの指定というのは、ContentBaseDeduplicationの機能の一部
  • ContentBaseDeduplicationは、FIFOキューでなければ有効にならない。

つまりContentBaseDeduplicationでデフォルトはメッセージボディ全体でSHA-256がかかるが、その入力値を指定できるという機能。

MessageDeduplicationId

This parameter applies only to FIFO (first-in-first-out) queues.

If you aren't able to provide a MessageDeduplicationId and you enable ContentBasedDeduplication for your queue, Amazon SQS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html

詳細

実際に動かしてみる。

前準備

awscliが必要。少し調べてみたところこれはversion 1のものらしい。現在preview段階でversion 2が作られているらしい。

$ pip install awscli

まぁそのあたりは適当に読み替えてもらうということで。

作成

キューを作成(FIFOである必要がある。ContentBaseDeduplicationもtrue)

$ aws sqs create-queue --queue-name hmm-test-test.fifo --attributes file://attr.json
{
    "Attributes": {
        "QueueArn": "arn:aws:sqs:ap-northeast-1:875885049010:hmm-test-test.fifo",
        "ApproximateNumberOfMessages": "0",
        "ApproximateNumberOfMessagesNotVisible": "0",
        "ApproximateNumberOfMessagesDelayed": "0",
        "CreatedTimestamp": "1579249134",
        "LastModifiedTimestamp": "1579249575",
        "VisibilityTimeout": "1",
        "MaximumMessageSize": "262144",
        "MessageRetentionPeriod": "345600",
        "DelaySeconds": "0",
        "ReceiveMessageWaitTimeSeconds": "0",
        "FifoQueue": "true",
        "ContentBasedDeduplication": "true"
    }
}

attr.json

{
  "ContentBasedDeduplication": "true",
  "FifoQueue": "true",
  "VisibilityTimeout": "1"
}

エラー

指定をミスってタイポなどしたときにはこういうメッセージ。

An error occurred (InvalidAttributeName) when calling the SetQueueAttributes operation: Unknown Attribute contentBaseDeduplication.

FIFOじゃないキューの場合、これも属性が存在しないというメッセージになる。

aws sqs set-queue-attributes --queue-url $(make -s get-url) --attributes VisibilityTimeout=60,ContentBasedDeduplication=true

An error occurred (InvalidAttributeName) when calling the SetQueueAttributes operation: Unknown Attribute ContentBasedDeduplication.

実際の実行

実際に実行してみる。はじめはdeduplication Idを指定しないもの。次は指定したもの。 最後にpurge queueを呼んで上げるとまっさらな状態で試せる。

deduplication Idの指定なし

普通にsendするとbody全体でdeduplicationIDは計算される。つまり2個sendしたら2個receiveできる。

aws sqs send-message --queue-url $(make -s get-url) --message-body file://data.json --message-group-id xxx
{
    "MD5OfMessageBody": "ae0db7789084c03784774df52fef6e9c",
    "MessageId": "cfc69b42-d98f-409e-b786-50f1c044d192",
    "SequenceNumber": "18851031995790575616"
}
aws sqs send-message --queue-url $(make -s get-url) --message-body file://data2.json --message-group-id xxx
{
    "MD5OfMessageBody": "86d5a3290cf61524f71b015752eb0a48",
    "MessageId": "110713fb-b36e-485b-99c3-1829bb5ff013",
    "SequenceNumber": "18851031996249583616"
}
aws sqs receive-message --queue-url $(make -s get-url) --message-attribute-names All --max-number-of-messages 10
{
    "Messages": [
        {
            "MessageId": "cfc69b42-d98f-409e-b786-50f1c044d192",
            "ReceiptHandle": "AQEBMmRPGvnTnpFn5Es2+a5N+JhGAsH7OkvoAr3CxBMzF+1Y0LQCtx52HpdY0FINte4Xcn2gj3gq+OWwmv84KdaNuLkXqOOoxeVCtZtBisa10+PlGgEVoT2/C+Qb/emFlt8K9JTGCCr6dGkWgaJ+treb1HRQ3tIOk+cD2xqWOdILWl4c3So0yLHkO9m6PK2i/zt31DZjUBXHgz+bwgpEMpsy19+wPTCASWNEK4AtVPpFlKAYjvoNiW3mBv4bDy7AnleckJaXX9Vs4cPORjSS/5Zs5/o+7LZhRzTOSWVH7Y+Ca14=",
            "MD5OfBody": "ae0db7789084c03784774df52fef6e9c",
            "Body": "{\n  \"message\": \"hello\",\n  \"name\": \"foo\"\n}\n"
        },
        {
            "MessageId": "110713fb-b36e-485b-99c3-1829bb5ff013",
            "ReceiptHandle": "AQEBMY/Ji/xn65xpgXNlEHVZuaeIwM2ivjA9oI/AiRJLNkxKaXujICFU9t7+g+YcZDjxZxYPxMHF8qfdyX0igS291NFhFrZLfjolJpSvj/PDx9SrdMBS+7FeM/tgL5/xMpmkC7zQW6JhnOLEjlplWechb769iCO3wyOi20jnww44KWlVS0t/LCX46iIGPiISijqQI4B9ELRWTCBfWeS27TirZ++PxCXmDXy2jkVcskbYZ93l/KZrUsdroGyLjFHzMbTGFUIphIByVzcSB9t5Xzl5tFAQytJmkezsbYIQT6lOCiM=",
            "MD5OfBody": "86d5a3290cf61524f71b015752eb0a48",
            "Body": "{\n  \"message\": \"byebye\",\n  \"name\": \"foo\"\n}\n"
        }
    ]
}
aws sqs purge-queue --queue-url $(make -s get-url)

はい。

この時のファイルは以下

data.json

{
  "message": "hello",
  "name": "foo"
}

data2.json

{
  "message": "byebye",
  "name": "foo"
}

はい。

deduplication Idの指定あり

deduplication Idを指定した場合にはそれが使われる。したがって2個sendしても1個だけ。 --message-deduplication-idで指定できる。

aws sqs send-message --queue-url $(make -s get-url) --message-body file://data.json --message-group-id xxx --message-deduplication-id same-id
{
    "MD5OfMessageBody": "ae0db7789084c03784774df52fef6e9c",
    "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137",
    "SequenceNumber": "18851032041886447872"
}
aws sqs send-message --queue-url $(make -s get-url) --message-body file://data2.json --message-group-id xxx --message-deduplication-id same-id
{
    "MD5OfMessageBody": "86d5a3290cf61524f71b015752eb0a48",
    "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137",
    "SequenceNumber": "18851032041886447872"
}

aws sqs receive-message --queue-url $(make -s get-url) --message-attribute-names All --max-number-of-messages 10
{
    "Messages": [
        {
            "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137",
            "ReceiptHandle": "AQEBTwnYAaCVQlHPMwMAIz/Yuq5O+xuWyDSscaVzS7EvDHt+k+anTOI2NqpNRmdijvCmEqYHBmGSLvisSo2ouSt6x0Db3Y7I69Fr63VDY38l7KaKl2wIRj8gLKp8z/wSa8a/O8pIxR+eVMxMXyHIRNmxq+QnaQf7io+91wKb0AGhXY+uxMEhYIa+Nsd31Rk/BwARUwdO0b4ndRsF4+YyO1pFM6pTcLOWoEPnFj3rOBASBtchF5EeKyVIYeHuAz0uBmowXzNNwL6cFoKdT1xeMMWOy2HWc7Yn9xV94Id9N4DRBoY=",
            "MD5OfBody": "ae0db7789084c03784774df52fef6e9c",
            "Body": "{\n  \"message\": \"hello\",\n  \"name\": \"foo\"\n}\n"
        }
    ]
}
aws sqs purge-queue --queue-url $(make -s get-url)

Makefile

実験に使ったMakefile

Makefile

include ../env.mk
.DEFAULT_GOAL := list

# WARNING : 実際に作成する (write権限)
NAME ?= hmm-test-test.fifo

# NOTE:
#
# ContentBaseDeduplication=trueにするとdeduplicationが有効になる
# (これにはFIFOである必要がある)
# defaultはbodyをハッシュ関数にかける(SHA-256)
# MessageDeduplicationIdを指定するとそれが使われる
#
# - FIFOキューへのsendにはgroupIdの指定が必要

# 作成
00:
  $(MAKE) create
# 属性の表示
01:
  $(MAKE) get
# deduplication idなしでsend
02:
  $(MAKE) send
  $(MAKE) receive
  $(MAKE) purge
# deduplication idありでsend
03:
  $(MAKE) send2
  $(MAKE) receive
  $(MAKE) purge
# clean
04:
  $(MAKE) clean

get:
  aws sqs get-queue-attributes --queue-url $$(make -s get-url) --attribute-names All
create:
  aws sqs create-queue --queue-name ${NAME} --attributes file://attr.json

# 素朴にsend
send:
  aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data.json --message-group-id xxx
  aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data2.json --message-group-id xxx

purge:
  aws sqs purge-queue --queue-url $$(make -s get-url)

# 同じdeduplicationIDを指定してsend
send2:
  aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data.json --message-group-id xxx --message-deduplication-id same-id
  aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data2.json --message-group-id xxx --message-deduplication-id same-id

receive:
  aws sqs receive-message --queue-url $$(make -s get-url) --message-attribute-names All --max-number-of-messages 10

# usage

help:
  aws sqs help
list:
  aws sqs list-queues
get-url:
  aws sqs get-queue-url --queue-name ${NAME} | jqfpy 'get("QueueUrl")' -r
delete:
  aws sqs delete-queue --queue-url $$(make -s get-url)
clean:
  $(MAKE) purge
  $(MAKE) delete

aws sqs helpを注意深く読むとわかるけれど。実験も大切。 💫 そしてドキュメントを辿るよりもawscliのヘルプを先に見るのが一番手軽かもしれない。

misc

VisibilityTimeout

VisibilityTimeoutは他のreceiveで取得されない期間のこと

MessageGroupId

並行で処理したい場合にまじめにつけると良い。この単位でgroupingされる。

create, delete

同名のキューを作成したり削除したりを繰り返していたところ、同名のキューの作成は削除後60秒ほど待たないといけないらしい。

gist