{"action":"created","comment":{"url":"https://api.github.com/repos/open-guides/og-aws/pulls/comments/83542930","pull_request_review_id":4381525,"id":83542930,"diff_hunk":"@@ -1289,6 +1291,33 @@ EMR\n -\t💸❗**EMR costs** can pile up quickly since it involves lots of instances, efficiency can be poor depending on cluster configuration and choice of workload, and accidents like hung jobs are costly. See the [section on EC2 cost management](#ec2-cost-management), especially the tips there about Spot instances and avoiding hourly billing. [This blog post](http://engineering.bloomreach.com/strategies-for-reducing-your-amazon-emr-costs/) has additional tips.\n -\t💸 Beware of “double-dipping”. With EMR, you pay for the EC2 capacity and the service fees. In addition, EMR syncs task logs to S3, which means you pay for the storage and **PUT requests** at [S3 standard rates](https://aws.amazon.com/s3/pricing/#Request_Pricing). While the log files tend to be relatively small, every Hadoop job, depending on the size, generates thousands of log files that can quickly add up to thousands of dollars on the AWS bill. YARN's [log aggregation](http://hortonworks.com/blog/simplifying-user-logs-management-and-access-in-yarn/) is not available on EMR.\n \n+Kinesis Streams\n+---\n+\n+### Kinesis Streams Basics\n+\n+-\t📒 [Homepage](https://aws.amazon.com/kinesis/streams/) ∙ [Developer guide](https://docs.aws.amazon.com/streams/latest/dev/introduction.html) ∙ [FAQ](https://aws.amazon.com/kinesis/streams/faqs/) ∙ [Pricing](https://aws.amazon.com/kinesis/streams/pricing/)\n+-\t**Kinesis Streams** (which used to be only called Kinesis, before Kinesis Firehose and Kinesis Analytics were launched) is a service that allows you to injest high-throughput data streams for immediate or delayed processing by other AWS services\n+- Kinesis Streams' subcomponents are called [Shards](https://docs.aws.amazon.com/streams/latest/dev/key-concepts.html). Each shard provides 1MB/s of write capacity and 2MB/s of read capacity at a maximum of 5 reads per second. A stream can have its Shards programatically increased or decreased based on a variety of metrics\n+- All records entered into a Kinesis Stream are assigned a unique Sequence Number as they are captured. The records in a Stream are ordered by this number, so any time-ordering is preserved.\n+\n+### Kinesis Streams Alternatives and Lock-in\n+\n+-\t⛓Kinesis is most closely compared to [Apache Kafka](https://kafka.apache.org/), an open-source data injestion solution. It is possible to set up a Kafka cluster hosted on [EC2 instances](#ec2) (or any other VPS), however you are responsible for managing and maintaining both Zookeeper and the Kafka brokers in a highly availible configuration. Confluent have a good blog post on their recommendations on doing this [here](http://www.confluent.io/blog/design-and-deployment-considerations-for-deploying-apache-kafka-on-aws/), which has links on the bottom to several other blogs they have written on the subject.\n+-   Kinesis uses very AWS-specific APIs and terms (e.g. Shards), so you should be aware of the potential future costs of migrating away from it, should you choose to use it.\n+\n+### Kinesis Streams Tips\n+\n+-\tThe [KCL](https://docs.aws.amazon.com/streams/latest/dev/developing-consumers-with-kcl.html) (Kinesis Client Library) is a very useful Java program (wrapped in a Multi-Language Daemon that makes it useable in Java, Node, Python, Ruby and .NET programs) that provides very simple interfaces for clients to use when consuming data from a Kinesis Stream. It provides the skeleton for 3 basic functions - ```intitialise```, ```process-records```, and ```shutdown```. As a developer, all you need to do is set up the config file to point at the correct Kinesis Stream, and fill out the provided functions in order to start consuming data from Kinesis.\n+\t- The KCL uses a DynamoDB table to keep track of which records have been processed by the KCL. This ensures that all records are processed 'at least once'. It is up to the developer to ensure that the program can handle doubly-processed records.\n+\t- The KCL also uses DynamoDB to keep track of other KCL 'workers'. It automatically shares the available Kinesis Shards across all the workers as equally as possible.\n+\n+### Kinesis Streams Gotchas and Limitations\n+-\t💸❗**Kinesis Streams are not included in the free tier!** Make sure if you do any experimentation with it on a personal account, you shut down the stream, or you can run up unexpected costs (~$11 per shard-month)\n+-  Kinesis Streams' shards each only permit 5 reads per second. If you are using ```n``` shards in a particular stream, and evenly distributing your data across all of them, you will end up with a total of 5 reads per second. This is because a consumer cannot know which shard will contain new data, and will therefore need to check every single one. This means that there is a hard limit on the number of consumers you can have per stream, for any given latency.\n+\t- If you wish to have 5 consumers all reading data from one Stream with 5 shards, with a maximum permitted latency of 0.5 seconds, you will need to either split your data across two streams, or reduce your latency requirements - with the setup described above, each consumer will need to poll each shard once every 0.5 seconds, meaning each Shard will need to be queried 10 times a second - a value in excess of the maximum.\n+\t- There is a good blog by Brandur, an engineer at Stripe, that discusses the performance and limitations of Kinesis in production [here](https://brandur.org/kinesis-in-production).","path":"README.md","position":41,"original_position":41,"commit_id":"90437fc5529f073ea756c4c9a3897859be3ca8e9","original_commit_id":"90437fc5529f073ea756c4c9a3897859be3ca8e9","user":{"login":"jlevy","id":2058167,"avatar_url":"https://avatars.githubusercontent.com/u/2058167?v=3","gravatar_id":"","url":"https://api.github.com/users/jlevy","html_url":"https://github.com/jlevy","followers_url":"https://api.github.com/users/jlevy/followers","following_url":"https://api.github.com/users/jlevy/following{/other_user}","gists_url":"https://api.github.com/users/jlevy/gists{/gist_id}","starred_url":"https://api.github.com/users/jlevy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jlevy/subscriptions","organizations_url":"https://api.github.com/users/jlevy/orgs","repos_url":"https://api.github.com/users/jlevy/repos","events_url":"https://api.github.com/users/jlevy/events{/privacy}","received_events_url":"https://api.github.com/users/jlevy/received_events","type":"User","site_admin":false},"body":"Minor:\r\n- [This blog](https://brandur.org/kinesis-in-production) (by an engineer at Stripe) elaborates on the performance and limitations of Kinesis in production.","created_at":"2016-10-16T00:57:14Z","updated_at":"2016-10-16T00:59:15Z","html_url":"https://github.com/open-guides/og-aws/pull/193#discussion_r83542930","pull_request_url":"https://api.github.com/repos/open-guides/og-aws/pulls/193","_links":{"self":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/comments/83542930"},"html":{"href":"https://github.com/open-guides/og-aws/pull/193#discussion_r83542930"},"pull_request":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/193"}}},"pull_request":{"url":"https://api.github.com/repos/open-guides/og-aws/pulls/193","id":89198592,"html_url":"https://github.com/open-guides/og-aws/pull/193","diff_url":"https://github.com/open-guides/og-aws/pull/193.diff","patch_url":"https://github.com/open-guides/og-aws/pull/193.patch","issue_url":"https://api.github.com/repos/open-guides/og-aws/issues/193","number":193,"state":"closed","locked":false,"title":"Added v1 of information on Kinesis","user":{"login":"KrishanBhasin","id":8904718,"avatar_url":"https://avatars.githubusercontent.com/u/8904718?v=3","gravatar_id":"","url":"https://api.github.com/users/KrishanBhasin","html_url":"https://github.com/KrishanBhasin","followers_url":"https://api.github.com/users/KrishanBhasin/followers","following_url":"https://api.github.com/users/KrishanBhasin/following{/other_user}","gists_url":"https://api.github.com/users/KrishanBhasin/gists{/gist_id}","starred_url":"https://api.github.com/users/KrishanBhasin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KrishanBhasin/subscriptions","organizations_url":"https://api.github.com/users/KrishanBhasin/orgs","repos_url":"https://api.github.com/users/KrishanBhasin/repos","events_url":"https://api.github.com/users/KrishanBhasin/events{/privacy}","received_events_url":"https://api.github.com/users/KrishanBhasin/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-10-13T13:09:14Z","updated_at":"2016-10-16T00:59:15Z","closed_at":"2016-10-15T23:04:18Z","merged_at":"2016-10-15T23:04:18Z","merge_commit_sha":"0711c3f9b8758d63d04288f7c28041506e9574be","assignee":{"login":"KrishanBhasin","id":8904718,"avatar_url":"https://avatars.githubusercontent.com/u/8904718?v=3","gravatar_id":"","url":"https://api.github.com/users/KrishanBhasin","html_url":"https://github.com/KrishanBhasin","followers_url":"https://api.github.com/users/KrishanBhasin/followers","following_url":"https://api.github.com/users/KrishanBhasin/following{/other_user}","gists_url":"https://api.github.com/users/KrishanBhasin/gists{/gist_id}","starred_url":"https://api.github.com/users/KrishanBhasin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KrishanBhasin/subscriptions","organizations_url":"https://api.github.com/users/KrishanBhasin/orgs","repos_url":"https://api.github.com/users/KrishanBhasin/repos","events_url":"https://api.github.com/users/KrishanBhasin/events{/privacy}","received_events_url":"https://api.github.com/users/KrishanBhasin/received_events","type":"User","site_admin":false},"assignees":[{"login":"KrishanBhasin","id":8904718,"avatar_url":"https://avatars.githubusercontent.com/u/8904718?v=3","gravatar_id":"","url":"https://api.github.com/users/KrishanBhasin","html_url":"https://github.com/KrishanBhasin","followers_url":"https://api.github.com/users/KrishanBhasin/followers","following_url":"https://api.github.com/users/KrishanBhasin/following{/other_user}","gists_url":"https://api.github.com/users/KrishanBhasin/gists{/gist_id}","starred_url":"https://api.github.com/users/KrishanBhasin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KrishanBhasin/subscriptions","organizations_url":"https://api.github.com/users/KrishanBhasin/orgs","repos_url":"https://api.github.com/users/KrishanBhasin/repos","events_url":"https://api.github.com/users/KrishanBhasin/events{/privacy}","received_events_url":"https://api.github.com/users/KrishanBhasin/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/open-guides/og-aws/pulls/193/commits","review_comments_url":"https://api.github.com/repos/open-guides/og-aws/pulls/193/comments","review_comment_url":"https://api.github.com/repos/open-guides/og-aws/pulls/comments{/number}","comments_url":"https://api.github.com/repos/open-guides/og-aws/issues/193/comments","statuses_url":"https://api.github.com/repos/open-guides/og-aws/statuses/90437fc5529f073ea756c4c9a3897859be3ca8e9","head":{"label":"KrishanBhasin:master","ref":"master","sha":"90437fc5529f073ea756c4c9a3897859be3ca8e9","user":{"login":"KrishanBhasin","id":8904718,"avatar_url":"https://avatars.githubusercontent.com/u/8904718?v=3","gravatar_id":"","url":"https://api.github.com/users/KrishanBhasin","html_url":"https://github.com/KrishanBhasin","followers_url":"https://api.github.com/users/KrishanBhasin/followers","following_url":"https://api.github.com/users/KrishanBhasin/following{/other_user}","gists_url":"https://api.github.com/users/KrishanBhasin/gists{/gist_id}","starred_url":"https://api.github.com/users/KrishanBhasin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KrishanBhasin/subscriptions","organizations_url":"https://api.github.com/users/KrishanBhasin/orgs","repos_url":"https://api.github.com/users/KrishanBhasin/repos","events_url":"https://api.github.com/users/KrishanBhasin/events{/privacy}","received_events_url":"https://api.github.com/users/KrishanBhasin/received_events","type":"User","site_admin":false},"repo":{"id":70802522,"name":"og-aws","full_name":"KrishanBhasin/og-aws","owner":{"login":"KrishanBhasin","id":8904718,"avatar_url":"https://avatars.githubusercontent.com/u/8904718?v=3","gravatar_id":"","url":"https://api.github.com/users/KrishanBhasin","html_url":"https://github.com/KrishanBhasin","followers_url":"https://api.github.com/users/KrishanBhasin/followers","following_url":"https://api.github.com/users/KrishanBhasin/following{/other_user}","gists_url":"https://api.github.com/users/KrishanBhasin/gists{/gist_id}","starred_url":"https://api.github.com/users/KrishanBhasin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KrishanBhasin/subscriptions","organizations_url":"https://api.github.com/users/KrishanBhasin/orgs","repos_url":"https://api.github.com/users/KrishanBhasin/repos","events_url":"https://api.github.com/users/KrishanBhasin/events{/privacy}","received_events_url":"https://api.github.com/users/KrishanBhasin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/KrishanBhasin/og-aws","description":"📙 Amazon Web Services — a practical guide","fork":true,"url":"https://api.github.com/repos/KrishanBhasin/og-aws","forks_url":"https://api.github.com/repos/KrishanBhasin/og-aws/forks","keys_url":"https://api.github.com/repos/KrishanBhasin/og-aws/keys{/key_id}","collaborators_url":"https://api.github.com/repos/KrishanBhasin/og-aws/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/KrishanBhasin/og-aws/teams","hooks_url":"https://api.github.com/repos/KrishanBhasin/og-aws/hooks","issue_events_url":"https://api.github.com/repos/KrishanBhasin/og-aws/issues/events{/number}","events_url":"https://api.github.com/repos/KrishanBhasin/og-aws/events","assignees_url":"https://api.github.com/repos/KrishanBhasin/og-aws/assignees{/user}","branches_url":"https://api.github.com/repos/KrishanBhasin/og-aws/branches{/branch}","tags_url":"https://api.github.com/repos/KrishanBhasin/og-aws/tags","blobs_url":"https://api.github.com/repos/KrishanBhasin/og-aws/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/KrishanBhasin/og-aws/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/KrishanBhasin/og-aws/git/refs{/sha}","trees_url":"https://api.github.com/repos/KrishanBhasin/og-aws/git/trees{/sha}","statuses_url":"https://api.github.com/repos/KrishanBhasin/og-aws/statuses/{sha}","languages_url":"https://api.github.com/repos/KrishanBhasin/og-aws/languages","stargazers_url":"https://api.github.com/repos/KrishanBhasin/og-aws/stargazers","contributors_url":"https://api.github.com/repos/KrishanBhasin/og-aws/contributors","subscribers_url":"https://api.github.com/repos/KrishanBhasin/og-aws/subscribers","subscription_url":"https://api.github.com/repos/KrishanBhasin/og-aws/subscription","commits_url":"https://api.github.com/repos/KrishanBhasin/og-aws/commits{/sha}","git_commits_url":"https://api.github.com/repos/KrishanBhasin/og-aws/git/commits{/sha}","comments_url":"https://api.github.com/repos/KrishanBhasin/og-aws/comments{/number}","issue_comment_url":"https://api.github.com/repos/KrishanBhasin/og-aws/issues/comments{/number}","contents_url":"https://api.github.com/repos/KrishanBhasin/og-aws/contents/{+path}","compare_url":"https://api.github.com/repos/KrishanBhasin/og-aws/compare/{base}...{head}","merges_url":"https://api.github.com/repos/KrishanBhasin/og-aws/merges","archive_url":"https://api.github.com/repos/KrishanBhasin/og-aws/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/KrishanBhasin/og-aws/downloads","issues_url":"https://api.github.com/repos/KrishanBhasin/og-aws/issues{/number}","pulls_url":"https://api.github.com/repos/KrishanBhasin/og-aws/pulls{/number}","milestones_url":"https://api.github.com/repos/KrishanBhasin/og-aws/milestones{/number}","notifications_url":"https://api.github.com/repos/KrishanBhasin/og-aws/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/KrishanBhasin/og-aws/labels{/name}","releases_url":"https://api.github.com/repos/KrishanBhasin/og-aws/releases{/id}","deployments_url":"https://api.github.com/repos/KrishanBhasin/og-aws/deployments","created_at":"2016-10-13T12:07:29Z","updated_at":"2016-10-13T12:07:30Z","pushed_at":"2016-10-15T23:32:15Z","git_url":"git://github.com/KrishanBhasin/og-aws.git","ssh_url":"git@github.com:KrishanBhasin/og-aws.git","clone_url":"https://github.com/KrishanBhasin/og-aws.git","svn_url":"https://github.com/KrishanBhasin/og-aws","homepage":"","size":3499,"stargazers_count":0,"watchers_count":0,"language":"Shell","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"open-guides:master","ref":"master","sha":"dd8975c486020214d1bede662c8625771adf50e0","user":{"login":"open-guides","id":17152571,"avatar_url":"https://avatars.githubusercontent.com/u/17152571?v=3","gravatar_id":"","url":"https://api.github.com/users/open-guides","html_url":"https://github.com/open-guides","followers_url":"https://api.github.com/users/open-guides/followers","following_url":"https://api.github.com/users/open-guides/following{/other_user}","gists_url":"https://api.github.com/users/open-guides/gists{/gist_id}","starred_url":"https://api.github.com/users/open-guides/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-guides/subscriptions","organizations_url":"https://api.github.com/users/open-guides/orgs","repos_url":"https://api.github.com/users/open-guides/repos","events_url":"https://api.github.com/users/open-guides/events{/privacy}","received_events_url":"https://api.github.com/users/open-guides/received_events","type":"Organization","site_admin":false},"repo":{"id":63266213,"name":"og-aws","full_name":"open-guides/og-aws","owner":{"login":"open-guides","id":17152571,"avatar_url":"https://avatars.githubusercontent.com/u/17152571?v=3","gravatar_id":"","url":"https://api.github.com/users/open-guides","html_url":"https://github.com/open-guides","followers_url":"https://api.github.com/users/open-guides/followers","following_url":"https://api.github.com/users/open-guides/following{/other_user}","gists_url":"https://api.github.com/users/open-guides/gists{/gist_id}","starred_url":"https://api.github.com/users/open-guides/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-guides/subscriptions","organizations_url":"https://api.github.com/users/open-guides/orgs","repos_url":"https://api.github.com/users/open-guides/repos","events_url":"https://api.github.com/users/open-guides/events{/privacy}","received_events_url":"https://api.github.com/users/open-guides/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-guides/og-aws","description":"📙 Amazon Web Services — a practical guide","fork":false,"url":"https://api.github.com/repos/open-guides/og-aws","forks_url":"https://api.github.com/repos/open-guides/og-aws/forks","keys_url":"https://api.github.com/repos/open-guides/og-aws/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-guides/og-aws/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-guides/og-aws/teams","hooks_url":"https://api.github.com/repos/open-guides/og-aws/hooks","issue_events_url":"https://api.github.com/repos/open-guides/og-aws/issues/events{/number}","events_url":"https://api.github.com/repos/open-guides/og-aws/events","assignees_url":"https://api.github.com/repos/open-guides/og-aws/assignees{/user}","branches_url":"https://api.github.com/repos/open-guides/og-aws/branches{/branch}","tags_url":"https://api.github.com/repos/open-guides/og-aws/tags","blobs_url":"https://api.github.com/repos/open-guides/og-aws/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-guides/og-aws/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-guides/og-aws/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-guides/og-aws/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-guides/og-aws/statuses/{sha}","languages_url":"https://api.github.com/repos/open-guides/og-aws/languages","stargazers_url":"https://api.github.com/repos/open-guides/og-aws/stargazers","contributors_url":"https://api.github.com/repos/open-guides/og-aws/contributors","subscribers_url":"https://api.github.com/repos/open-guides/og-aws/subscribers","subscription_url":"https://api.github.com/repos/open-guides/og-aws/subscription","commits_url":"https://api.github.com/repos/open-guides/og-aws/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-guides/og-aws/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-guides/og-aws/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-guides/og-aws/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-guides/og-aws/contents/{+path}","compare_url":"https://api.github.com/repos/open-guides/og-aws/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-guides/og-aws/merges","archive_url":"https://api.github.com/repos/open-guides/og-aws/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-guides/og-aws/downloads","issues_url":"https://api.github.com/repos/open-guides/og-aws/issues{/number}","pulls_url":"https://api.github.com/repos/open-guides/og-aws/pulls{/number}","milestones_url":"https://api.github.com/repos/open-guides/og-aws/milestones{/number}","notifications_url":"https://api.github.com/repos/open-guides/og-aws/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-guides/og-aws/labels{/name}","releases_url":"https://api.github.com/repos/open-guides/og-aws/releases{/id}","deployments_url":"https://api.github.com/repos/open-guides/og-aws/deployments","created_at":"2016-07-13T17:30:16Z","updated_at":"2016-10-16T00:58:35Z","pushed_at":"2016-10-15T23:39:16Z","git_url":"git://github.com/open-guides/og-aws.git","ssh_url":"git@github.com:open-guides/og-aws.git","clone_url":"https://github.com/open-guides/og-aws.git","svn_url":"https://github.com/open-guides/og-aws","homepage":"","size":4927,"stargazers_count":11360,"watchers_count":11360,"language":"Shell","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":560,"mirror_url":null,"open_issues_count":93,"forks":560,"open_issues":93,"watchers":11360,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/193"},"html":{"href":"https://github.com/open-guides/og-aws/pull/193"},"issue":{"href":"https://api.github.com/repos/open-guides/og-aws/issues/193"},"comments":{"href":"https://api.github.com/repos/open-guides/og-aws/issues/193/comments"},"review_comments":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/193/comments"},"review_comment":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/open-guides/og-aws/pulls/193/commits"},"statuses":{"href":"https://api.github.com/repos/open-guides/og-aws/statuses/90437fc5529f073ea756c4c9a3897859be3ca8e9"}}}}
{"actor":{"display_login":"jlevy"}}