TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

System design hack: Postgres is a great pub/sub and job server

852 点作者 colinchartier超过 5 年前

33 条评论

nostrademons超过 5 年前
Another neat hack is to use Postgres as a quick &amp; dirty replacement for Hadoop&#x2F;MapReduce if you have a job that has big (100T+) input data but small (~1G) output data. A lot of common tasks fall into this category: generating aggregate statistics from large log files, searching Common Crawl for relevant webpages, identifying abusive users or transactions, etc.<p>The architecture is to stick a list of your input shards in a Postgres table, have a state flag that goes PENDING-&gt;WORKING-&gt;FINISHED-&gt;(ERROR?), and then spin up a bunch of worker processes as EC2 spot instances that check for the next PENDING task, mark it as WORKING, pull it, process it, mark it as FINISHED, and repeat. They write their output back to the DB in a transaction; there&#x27;s an assumption that aggregation can happen in-process and then get merged in a relatively cheap transaction. If the worker fails or gets pre-empted, it retries (or marks as ERROR) any shards it was previously working on.<p>Postgres basically functions as the MapReduce Master &amp; Reducer, the worker functions as the Mapper and Combiner, and there&#x27;s no need for a shuffle phase because output &lt;&lt;&lt; input. Almost all the actual complexity in MapReduce&#x2F;Hadoop is in the shuffle, so if you don&#x27;t need that, the remaining stuff takes &lt; 1 hour to implement and can be done without any frameworks.
评论 #21487005 未加载
评论 #21487186 未加载
评论 #21489719 未加载
评论 #21491907 未加载
评论 #21487421 未加载
评论 #21491941 未加载
评论 #21488512 未加载
davidw超过 5 年前
&gt; It&#x27;s rarely a mistake to start with Postgres and then switch out the most performance critical parts of your system when the time comes.<p>This is pretty good advice in general.
评论 #21491999 未加载
评论 #21487954 未加载
pjungwir超过 5 年前
I&#x27;ve done this before with good results.<p>I was pleased to see they are using `SELECT FOR UPDATE SKIP LOCKED`. That is what this 2nd Quadrant article recommends, which I think is required reading if you want to implement this yourself:<p><a href="https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;what-is-select-skip-locked-for-in-postgresql-9-5&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;what-is-select-skip-lock...</a><p>It goes into more detail about wrong ways to implement a queue and what the downsides are for its preferred approach.
jordic超过 5 年前
We use a lot this kind of tooling.. say, you need to check 20k URLs and you want to rate limit them.. add them to a Pg table (with state and result fields). A single thread worker that just takes a row (marks it as pending) and later updates it. With select for update and skip tricks you can horitzontal scale it to the number of workers you need.<p>I had seen it also for soft that sends massmail (our case around 100k&#x2F;day).. it&#x27;s state is a postgres queue.<p>We also use Pg for transactional mail. We insert it on a table. (There is a process that sends the row mails).. the so nice part is that the mail is joining the dB transaction for free.. (all or nothing)
evv超过 5 年前
Excellent design hack. If anybody in the Node&#x2F;TypeScript ecosystem is looking for this capability in a neat and supported library, it looks like the graphile folks have you covered:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;graphile&#x2F;worker" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;graphile&#x2F;worker</a>
评论 #21489347 未加载
zitterbewegung超过 5 年前
Postgres is an acceptable relational database &#x2F; nosql database &#x2F; pub&#x2F; sub&#x2F; job server &#x2F; blockchain.
评论 #21486436 未加载
评论 #21489471 未加载
zrail超过 5 年前
If you&#x27;re working with Ruby I have had good experiences with Que[1], which implements a pattern similar to the OP using advisory locks.<p>[1]: <a href="https:&#x2F;&#x2F;github.com&#x2F;que-rb&#x2F;que" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;que-rb&#x2F;que</a>
评论 #21485823 未加载
评论 #21485549 未加载
评论 #21485796 未加载
评论 #21489918 未加载
soumyadeb超过 5 年前
Geat post!! At Rudder (open-source segment), we used Postgres as our streaming layer in a similar fashion. It has been super stable in production, very easy to setup and we easily get to &gt; 10K events&#x2F;sec insertion performance.<p>The code is open-sourced here in case anyone wants to re-use<p><a href="https:&#x2F;&#x2F;github.com&#x2F;rudderlabs&#x2F;rudder-server&#x2F;blob&#x2F;master&#x2F;jobsdb&#x2F;jobsdb.go" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;rudderlabs&#x2F;rudder-server&#x2F;blob&#x2F;master&#x2F;jobs...</a><p>We had to built additional logic to clean-up old jobs (similar to Level merges in similar queing systems)
fizwhiz超过 5 年前
Isn&#x27;t hijacking a DB as a &quot;distributed&quot; message queue a pretty well trodden path? Enterprises have been doing this for decades.
评论 #21485250 未加载
评论 #21485255 未加载
silasdavis超过 5 年前
The postgres module for node is quite unreliable when holding open a connection to listen on a channel. This helped: <a href="https:&#x2F;&#x2F;github.com&#x2F;andywer&#x2F;pg-listen&#x2F;blob&#x2F;master&#x2F;README.md" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;andywer&#x2F;pg-listen&#x2F;blob&#x2F;master&#x2F;README.md</a><p>But we still see issues.
cle超过 5 年前
At the scale I operate at, I wouldn&#x27;t consider this a viable option. What&#x27;s the backpressure like on NOTIFY&#x2F;LISTEN? (Docs mention a maximum backlog of 8GB on the message queue, is that configurable? Monitorable?) Tons of constant churn on a table means we have to worry about vacuuming right? Now I have to monitor that too to make sure it&#x27;s keeping up. Not to mention all the usual operational issues with running relational databases.<p>No thanks, I&#x27;ll stick with GCP PubSub or AWS SQS, which are explicitly designed for this use case, and for which I have to setup <i>no</i> infrastructure.
评论 #21488627 未加载
评论 #21488217 未加载
评论 #21487011 未加载
stephenr超过 5 年前
I&#x27;m not sure I quite follow this statement:<p>&gt; In the list above, I skipped things similar to pub&#x2F;sub servers called &quot;job queues&quot; - they only let one &quot;subscriber&quot; watch for new &quot;events&quot; at a time, and keep a queue of unprocessed events:<p>If your job queue only allows one single worker (even per named queue), I&#x27;d argue it&#x27;s a shit job queue.
评论 #21490660 未加载
fyp超过 5 年前
Can someone share their experience with scaling pg&#x27;s NOTIFY and LISTEN?<p>The use case I have in mind has a lot of logically separate queues. Is it better for each queue to have its own channel (so subscribers can listen to only the queue they need) or have all queues notify a global channel (and have subscribers filter for messages relevant to them). I am mainly confused about whether I need a dedicated db connection per LISTEN query and also how many channels is too much.
评论 #21489706 未加载
评论 #21485666 未加载
londons_explore超过 5 年前
Hacks like this work at first, but long running transactions and postgres don&#x27;t do well together.<p>After a few weeks of running on a multi-TB table, you&#x27;ll find the dead tuples massively outnumber the live tuples, and database performance is dropping faster than the Vacuum can keep up. Vacuum is inherently single-threaded, while your processes making dead tuples as part of queries are multi-threaded, so it&#x27;s obviously the vacuum that fails first if most queries are long running and touch most rows. Your statistics will get old because they&#x27;re also generated by the vacuum process, making everything yet slower.<p>Even if you can live with gradually dropping performance, eventually the whole thing will fail when your txids wrap around and the whole database goes read-only.
评论 #21490314 未加载
directionless超过 5 年前
Postgres generally has a fairly low maximum connections. If you&#x27;re running your own servers, you can adjust this, but in the cloud you may not be able to. For example, Google CloudSQL maxes at 1000, Heroku at 500.<p>At that point, people usually start looking at the connection pooling tools. Depending on how much work you need from the DB, connections pools can be a win. Anyone know how connection pooling works with listeners?<p>A
评论 #21486497 未加载
评论 #21488911 未加载
评论 #21487075 未加载
z3t4超过 5 年前
With today&#x27;s hardware I argue you most likely do not need a pub&#x2F;sub service. Considering the extra work needed in a distributed system, you could save a lot of time by keeping it simple.
luord超过 5 年前
Postgres is now pretty much the ultimate nearly-all purpose backend, it seems. At this point, I won&#x27;t need to use anything else.<p>And I&#x27;m more than perfectly fine with that.
zyngaro超过 5 年前
Keep in mind that a notify performed when nobody is listening is lost. The workers need then to catch up.
评论 #21486729 未加载
anonu超过 5 年前
How do you performance tune PostgreSQL on AWS and still keep it running under a reasonable cost?
评论 #21489499 未加载
Iv超过 5 年前
I&#x27;ll soon have to do a pub&#x2F;sub for an application that&#x27;s close to a multiplayer video game.<p>Most advices I have seen say that I&#x27;ll probably want to code it myself, but I was wondering about the latency of that solution? I&#x27;ll likely have a SQL store and that would be a good argument to use postgres...
评论 #21489353 未加载
评论 #21489470 未加载
评论 #21506435 未加载
评论 #21489200 未加载
2bitencryption超过 5 年前
I&#x27;m curious if the same holds true if you drop in Sqlite&#x2F;MS Sql Server&#x2F;Mysql.<p>I.e. is this good advice because Postgres in particular is a great implementation of sql, or because sql in general is good enough to solve this problem, or a mix of the two?
评论 #21486244 未加载
评论 #21486215 未加载
tapirl超过 5 年前
Should the &quot;ci_job_status&quot; in the line be &quot;ci_jobs&quot; instead?<p><pre><code> INSERT INTO ci_job_status(repositor ... </code></pre> BTW, it looks Go becomes so popular that many tutorials are using Go for examples. ;D
namanyayg超过 5 年前
I&#x27;ve simply been using MySQL&#x2F;Maria everywhere and am meaning to switch, but I&#x27;m not sure what makes Postgres this much better.<p>Can this hack not be achieved by a mariadb table too?
评论 #21490533 未加载
aarbor989超过 5 年前
I did something very similar with MySQL since that was the DB we already had setup for data (not my choice). Basically any database that has atomic operations can do this. It definitely is way more convenient and cheaper to do use your existing infra for pub&#x2F;sub and then only scale out to other services once performance becomes subpar. Although if you already have a messaging service up and running, it’s probably better to use that
klagermkii超过 5 年前
Thanks, seeing that atomic fetch in action is very useful.
webscalist超过 5 年前
if you use Postgres on AWS, you&#x27;ll easily exhaust IOPS with this and hell breaks
DevKoala超过 5 年前
I agree. I have prototyped this in the past, but our current pub&#x2F;sub was not painful enough for us to go full steam ahead with PG.<p>However, my design was more bare bones. I was picking jobs by chaining CTE&#x27;s that did the status update as they returned the first element of the queue.
rco8786超过 5 年前
Interesting enough, but I’m not sure why this is called a hack. It’s a fully supported feature of Pg
xmly超过 5 年前
Kinesis is based on DynamoDB...<p>Key-value stores could do a lot of things theoretically.
评论 #21487443 未加载
rantwasp超过 5 年前
<a href="http:&#x2F;&#x2F;mikehadlow.blogspot.com&#x2F;2012&#x2F;04&#x2F;database-as-queue-anti-pattern.html" rel="nofollow">http:&#x2F;&#x2F;mikehadlow.blogspot.com&#x2F;2012&#x2F;04&#x2F;database-as-queue-ant...</a>
评论 #21488991 未加载
fouc超过 5 年前
Another neat hack would be to use Postgres as a graph db
评论 #21491796 未加载
foou超过 5 年前
How do you manage the bloat?
评论 #21489017 未加载
ubu7737超过 5 年前
Used the &quot;FOR UPDATE SKIP LOCKED LIMIT 1&quot; trick to implement a job server in PG a few years ago for the first time.<p>It&#x27;s a great solution.
评论 #21485872 未加载
评论 #21486537 未加载
评论 #21486160 未加载
评论 #21488598 未加载