Global sequential number generator without using a relational database [closed]
I have an application. Suppose it's an invoice service. Each time a user creates an invoice I need to assign the next sequential number (I.e: ISequentialNumberGeneratorRepository.Next();
So essentially the invoice number must be unique despite having several instances of my application running (horizontal scalability is likely in the future).
In other words, I need a global sequential number generator.
Traditionally this problem is resolved by using a relational database such as SQL server, PostgreSQL, MySQL, etc. because these systems have the capability to generate sequential unique IDs on inserting a record and returning the generated id as part of the same atomic operation, so they're a perfect fit for a centralised sequential number generator.
But I don't have a relational database and I don't need one, so it's a bit brutal having to use one just for this tiny functionality.
I have, however, an EventStore available (EventStore.org) but I couldn't find out whether it has sequential number generation capability.
So my question is: Is there any available product out there which I could use to generate unique sequential numbers so that I can implement my Next();
repository's method with, and which would work well independently of how many instances of my client invoice application I have?
Note: Alternatively, if someone can think of a way to use EventStore for this purpose or how did they achieve this in a DDD/CQRS/ES environment it'd also be great.
c# database sequential event-store
closed as off-topic by Samuel Liew♦ Dec 2 '18 at 1:45
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Samuel Liew
|
show 7 more comments
I have an application. Suppose it's an invoice service. Each time a user creates an invoice I need to assign the next sequential number (I.e: ISequentialNumberGeneratorRepository.Next();
So essentially the invoice number must be unique despite having several instances of my application running (horizontal scalability is likely in the future).
In other words, I need a global sequential number generator.
Traditionally this problem is resolved by using a relational database such as SQL server, PostgreSQL, MySQL, etc. because these systems have the capability to generate sequential unique IDs on inserting a record and returning the generated id as part of the same atomic operation, so they're a perfect fit for a centralised sequential number generator.
But I don't have a relational database and I don't need one, so it's a bit brutal having to use one just for this tiny functionality.
I have, however, an EventStore available (EventStore.org) but I couldn't find out whether it has sequential number generation capability.
So my question is: Is there any available product out there which I could use to generate unique sequential numbers so that I can implement my Next();
repository's method with, and which would work well independently of how many instances of my client invoice application I have?
Note: Alternatively, if someone can think of a way to use EventStore for this purpose or how did they achieve this in a DDD/CQRS/ES environment it'd also be great.
c# database sequential event-store
closed as off-topic by Samuel Liew♦ Dec 2 '18 at 1:45
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Samuel Liew
4
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
3
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
1
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44
|
show 7 more comments
I have an application. Suppose it's an invoice service. Each time a user creates an invoice I need to assign the next sequential number (I.e: ISequentialNumberGeneratorRepository.Next();
So essentially the invoice number must be unique despite having several instances of my application running (horizontal scalability is likely in the future).
In other words, I need a global sequential number generator.
Traditionally this problem is resolved by using a relational database such as SQL server, PostgreSQL, MySQL, etc. because these systems have the capability to generate sequential unique IDs on inserting a record and returning the generated id as part of the same atomic operation, so they're a perfect fit for a centralised sequential number generator.
But I don't have a relational database and I don't need one, so it's a bit brutal having to use one just for this tiny functionality.
I have, however, an EventStore available (EventStore.org) but I couldn't find out whether it has sequential number generation capability.
So my question is: Is there any available product out there which I could use to generate unique sequential numbers so that I can implement my Next();
repository's method with, and which would work well independently of how many instances of my client invoice application I have?
Note: Alternatively, if someone can think of a way to use EventStore for this purpose or how did they achieve this in a DDD/CQRS/ES environment it'd also be great.
c# database sequential event-store
I have an application. Suppose it's an invoice service. Each time a user creates an invoice I need to assign the next sequential number (I.e: ISequentialNumberGeneratorRepository.Next();
So essentially the invoice number must be unique despite having several instances of my application running (horizontal scalability is likely in the future).
In other words, I need a global sequential number generator.
Traditionally this problem is resolved by using a relational database such as SQL server, PostgreSQL, MySQL, etc. because these systems have the capability to generate sequential unique IDs on inserting a record and returning the generated id as part of the same atomic operation, so they're a perfect fit for a centralised sequential number generator.
But I don't have a relational database and I don't need one, so it's a bit brutal having to use one just for this tiny functionality.
I have, however, an EventStore available (EventStore.org) but I couldn't find out whether it has sequential number generation capability.
So my question is: Is there any available product out there which I could use to generate unique sequential numbers so that I can implement my Next();
repository's method with, and which would work well independently of how many instances of my client invoice application I have?
Note: Alternatively, if someone can think of a way to use EventStore for this purpose or how did they achieve this in a DDD/CQRS/ES environment it'd also be great.
c# database sequential event-store
c# database sequential event-store
edited Nov 19 '18 at 23:02
iberodev
asked Nov 14 '18 at 15:02
iberodeviberodev
3,59933366
3,59933366
closed as off-topic by Samuel Liew♦ Dec 2 '18 at 1:45
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Samuel Liew
closed as off-topic by Samuel Liew♦ Dec 2 '18 at 1:45
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Samuel Liew
4
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
3
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
1
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44
|
show 7 more comments
4
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
3
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
1
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44
4
4
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
3
3
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
1
1
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44
|
show 7 more comments
3 Answers
3
active
oldest
votes
You have not stated the reasons(or presented any code) as to why you want this capability. I will assume the term sequential should be taken as monotonically increasing(sorting not looping).
I tend to agree with A.Chiesa, I would add timestamps to the list, although not applicable here.
Since your post does not indicate how the data is to be consumed, I purpose two solutions, the second preferred over the first, if possible; and for all later visitors, use a database solution instead.
The only way to guarantee numerical order across a horizontally scaled application without aggregation, is to utilize a central server to assign the numbers(using REST or RPCs or custom network code; not to mention an SQL server, as a side note). Due to concurrency, the application must wait it's turn for the next number and including network usage and delay, this delay limits the scalability of the application, and provides a single point of failure. These risks can be minimized by creating multiple instances of the central server and multiple application pools(You will lose the global sorting ability).
As an alternative, I would recommend the HI/LO Assigning method, combined with batch aggregation. Each instance has a four? digit identifier prefixed to an incrementing number per instance. Schedule an aggregation task on a central(or more than one, for redundancy) server(s) to pickup the data and assign a sequential unique id during aggregation. This process localizes the data(until pickup, which could be scheduled for (100, 500, 1000)? millisecond intervals if needed for coherence; minutes or more ,if not), and provides almost perfect horizontal scaling, with the drawback of increased vertical scaling requirements at the aggregation server(s).
Distributed computing is a balancing act, between processing, memory, and communication overhead. Where your computing/memory/network capacity boundaries lie cannot be determined from your post.
There is no single correct answer. I have provided you with two possibilities, but without specific requirements of the task at hand, I can go no further.
add a comment |
IMHO, your requirement is kinda flawed, because you have conflicting needs.
You want a unique id. The usual solutions use:
- guid. Can be generated centrally or locally. Really easy to implement. Kinda hard for a human reader, but YMMV. But you want incremental keys.
- centrally assigned key: you need a transactional system. But you want to do CQRS, and use Event Store. It seems to me that having a separate transactional system just to have an
IDENTITY_COLUMN
or aSEQUENCE
largely misses the point of doing CQRS. - use an HiLo generation approach. That is: every single client gets a unique seed (like 1 billion for the first client, 2 billions for the second, etc). So each client can generate locally a sequence. This sequence is distributed and uses sequential numbers, so there is no concurrency problems, but there is no global sorting for requests and you must ensure that no two clients get the same
Hi
value (relatively easy task). - use the id assigned by Event Store. I don't know the product, but every event sent to the queue gets a unique id. But (as I understand it) you require the id to be available BEFORE sending the event.
You can generally mix-and-match either of this solutions (especially the Hilo algorithm) with timestamps (like seconds from Unix Epoch, or something alike), in order to produce a (weak, non guaranteed) sortability. But generally I would avoid this, because if you generate ids on multiple sites, you introduce the risk of the clocks being unsynchronized, and generally other unsolved (or unsolvable) problems.
Probably I'm missing something, but this are the ones from the top of my head.
So, as far as i can tell, you are in an empasse. I would try really hard to put myself in one of the previous situations.
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
|
show 9 more comments
It is strange opinion
so it's a bit brutal having to use one just for this tiny
functionality.
Today SQLite is used as relational database even in mobile phones. It is simple, have small memory footprint and have binding for all popular programming languages. 20 years ago databases consumed many resources - today you can find database engine for all tasks. Also, if you need tiny key-pair store you can use BerkeleyDB.
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
You have not stated the reasons(or presented any code) as to why you want this capability. I will assume the term sequential should be taken as monotonically increasing(sorting not looping).
I tend to agree with A.Chiesa, I would add timestamps to the list, although not applicable here.
Since your post does not indicate how the data is to be consumed, I purpose two solutions, the second preferred over the first, if possible; and for all later visitors, use a database solution instead.
The only way to guarantee numerical order across a horizontally scaled application without aggregation, is to utilize a central server to assign the numbers(using REST or RPCs or custom network code; not to mention an SQL server, as a side note). Due to concurrency, the application must wait it's turn for the next number and including network usage and delay, this delay limits the scalability of the application, and provides a single point of failure. These risks can be minimized by creating multiple instances of the central server and multiple application pools(You will lose the global sorting ability).
As an alternative, I would recommend the HI/LO Assigning method, combined with batch aggregation. Each instance has a four? digit identifier prefixed to an incrementing number per instance. Schedule an aggregation task on a central(or more than one, for redundancy) server(s) to pickup the data and assign a sequential unique id during aggregation. This process localizes the data(until pickup, which could be scheduled for (100, 500, 1000)? millisecond intervals if needed for coherence; minutes or more ,if not), and provides almost perfect horizontal scaling, with the drawback of increased vertical scaling requirements at the aggregation server(s).
Distributed computing is a balancing act, between processing, memory, and communication overhead. Where your computing/memory/network capacity boundaries lie cannot be determined from your post.
There is no single correct answer. I have provided you with two possibilities, but without specific requirements of the task at hand, I can go no further.
add a comment |
You have not stated the reasons(or presented any code) as to why you want this capability. I will assume the term sequential should be taken as monotonically increasing(sorting not looping).
I tend to agree with A.Chiesa, I would add timestamps to the list, although not applicable here.
Since your post does not indicate how the data is to be consumed, I purpose two solutions, the second preferred over the first, if possible; and for all later visitors, use a database solution instead.
The only way to guarantee numerical order across a horizontally scaled application without aggregation, is to utilize a central server to assign the numbers(using REST or RPCs or custom network code; not to mention an SQL server, as a side note). Due to concurrency, the application must wait it's turn for the next number and including network usage and delay, this delay limits the scalability of the application, and provides a single point of failure. These risks can be minimized by creating multiple instances of the central server and multiple application pools(You will lose the global sorting ability).
As an alternative, I would recommend the HI/LO Assigning method, combined with batch aggregation. Each instance has a four? digit identifier prefixed to an incrementing number per instance. Schedule an aggregation task on a central(or more than one, for redundancy) server(s) to pickup the data and assign a sequential unique id during aggregation. This process localizes the data(until pickup, which could be scheduled for (100, 500, 1000)? millisecond intervals if needed for coherence; minutes or more ,if not), and provides almost perfect horizontal scaling, with the drawback of increased vertical scaling requirements at the aggregation server(s).
Distributed computing is a balancing act, between processing, memory, and communication overhead. Where your computing/memory/network capacity boundaries lie cannot be determined from your post.
There is no single correct answer. I have provided you with two possibilities, but without specific requirements of the task at hand, I can go no further.
add a comment |
You have not stated the reasons(or presented any code) as to why you want this capability. I will assume the term sequential should be taken as monotonically increasing(sorting not looping).
I tend to agree with A.Chiesa, I would add timestamps to the list, although not applicable here.
Since your post does not indicate how the data is to be consumed, I purpose two solutions, the second preferred over the first, if possible; and for all later visitors, use a database solution instead.
The only way to guarantee numerical order across a horizontally scaled application without aggregation, is to utilize a central server to assign the numbers(using REST or RPCs or custom network code; not to mention an SQL server, as a side note). Due to concurrency, the application must wait it's turn for the next number and including network usage and delay, this delay limits the scalability of the application, and provides a single point of failure. These risks can be minimized by creating multiple instances of the central server and multiple application pools(You will lose the global sorting ability).
As an alternative, I would recommend the HI/LO Assigning method, combined with batch aggregation. Each instance has a four? digit identifier prefixed to an incrementing number per instance. Schedule an aggregation task on a central(or more than one, for redundancy) server(s) to pickup the data and assign a sequential unique id during aggregation. This process localizes the data(until pickup, which could be scheduled for (100, 500, 1000)? millisecond intervals if needed for coherence; minutes or more ,if not), and provides almost perfect horizontal scaling, with the drawback of increased vertical scaling requirements at the aggregation server(s).
Distributed computing is a balancing act, between processing, memory, and communication overhead. Where your computing/memory/network capacity boundaries lie cannot be determined from your post.
There is no single correct answer. I have provided you with two possibilities, but without specific requirements of the task at hand, I can go no further.
You have not stated the reasons(or presented any code) as to why you want this capability. I will assume the term sequential should be taken as monotonically increasing(sorting not looping).
I tend to agree with A.Chiesa, I would add timestamps to the list, although not applicable here.
Since your post does not indicate how the data is to be consumed, I purpose two solutions, the second preferred over the first, if possible; and for all later visitors, use a database solution instead.
The only way to guarantee numerical order across a horizontally scaled application without aggregation, is to utilize a central server to assign the numbers(using REST or RPCs or custom network code; not to mention an SQL server, as a side note). Due to concurrency, the application must wait it's turn for the next number and including network usage and delay, this delay limits the scalability of the application, and provides a single point of failure. These risks can be minimized by creating multiple instances of the central server and multiple application pools(You will lose the global sorting ability).
As an alternative, I would recommend the HI/LO Assigning method, combined with batch aggregation. Each instance has a four? digit identifier prefixed to an incrementing number per instance. Schedule an aggregation task on a central(or more than one, for redundancy) server(s) to pickup the data and assign a sequential unique id during aggregation. This process localizes the data(until pickup, which could be scheduled for (100, 500, 1000)? millisecond intervals if needed for coherence; minutes or more ,if not), and provides almost perfect horizontal scaling, with the drawback of increased vertical scaling requirements at the aggregation server(s).
Distributed computing is a balancing act, between processing, memory, and communication overhead. Where your computing/memory/network capacity boundaries lie cannot be determined from your post.
There is no single correct answer. I have provided you with two possibilities, but without specific requirements of the task at hand, I can go no further.
answered Nov 21 '18 at 4:42
StromStrom
2,348423
2,348423
add a comment |
add a comment |
IMHO, your requirement is kinda flawed, because you have conflicting needs.
You want a unique id. The usual solutions use:
- guid. Can be generated centrally or locally. Really easy to implement. Kinda hard for a human reader, but YMMV. But you want incremental keys.
- centrally assigned key: you need a transactional system. But you want to do CQRS, and use Event Store. It seems to me that having a separate transactional system just to have an
IDENTITY_COLUMN
or aSEQUENCE
largely misses the point of doing CQRS. - use an HiLo generation approach. That is: every single client gets a unique seed (like 1 billion for the first client, 2 billions for the second, etc). So each client can generate locally a sequence. This sequence is distributed and uses sequential numbers, so there is no concurrency problems, but there is no global sorting for requests and you must ensure that no two clients get the same
Hi
value (relatively easy task). - use the id assigned by Event Store. I don't know the product, but every event sent to the queue gets a unique id. But (as I understand it) you require the id to be available BEFORE sending the event.
You can generally mix-and-match either of this solutions (especially the Hilo algorithm) with timestamps (like seconds from Unix Epoch, or something alike), in order to produce a (weak, non guaranteed) sortability. But generally I would avoid this, because if you generate ids on multiple sites, you introduce the risk of the clocks being unsynchronized, and generally other unsolved (or unsolvable) problems.
Probably I'm missing something, but this are the ones from the top of my head.
So, as far as i can tell, you are in an empasse. I would try really hard to put myself in one of the previous situations.
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
|
show 9 more comments
IMHO, your requirement is kinda flawed, because you have conflicting needs.
You want a unique id. The usual solutions use:
- guid. Can be generated centrally or locally. Really easy to implement. Kinda hard for a human reader, but YMMV. But you want incremental keys.
- centrally assigned key: you need a transactional system. But you want to do CQRS, and use Event Store. It seems to me that having a separate transactional system just to have an
IDENTITY_COLUMN
or aSEQUENCE
largely misses the point of doing CQRS. - use an HiLo generation approach. That is: every single client gets a unique seed (like 1 billion for the first client, 2 billions for the second, etc). So each client can generate locally a sequence. This sequence is distributed and uses sequential numbers, so there is no concurrency problems, but there is no global sorting for requests and you must ensure that no two clients get the same
Hi
value (relatively easy task). - use the id assigned by Event Store. I don't know the product, but every event sent to the queue gets a unique id. But (as I understand it) you require the id to be available BEFORE sending the event.
You can generally mix-and-match either of this solutions (especially the Hilo algorithm) with timestamps (like seconds from Unix Epoch, or something alike), in order to produce a (weak, non guaranteed) sortability. But generally I would avoid this, because if you generate ids on multiple sites, you introduce the risk of the clocks being unsynchronized, and generally other unsolved (or unsolvable) problems.
Probably I'm missing something, but this are the ones from the top of my head.
So, as far as i can tell, you are in an empasse. I would try really hard to put myself in one of the previous situations.
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
|
show 9 more comments
IMHO, your requirement is kinda flawed, because you have conflicting needs.
You want a unique id. The usual solutions use:
- guid. Can be generated centrally or locally. Really easy to implement. Kinda hard for a human reader, but YMMV. But you want incremental keys.
- centrally assigned key: you need a transactional system. But you want to do CQRS, and use Event Store. It seems to me that having a separate transactional system just to have an
IDENTITY_COLUMN
or aSEQUENCE
largely misses the point of doing CQRS. - use an HiLo generation approach. That is: every single client gets a unique seed (like 1 billion for the first client, 2 billions for the second, etc). So each client can generate locally a sequence. This sequence is distributed and uses sequential numbers, so there is no concurrency problems, but there is no global sorting for requests and you must ensure that no two clients get the same
Hi
value (relatively easy task). - use the id assigned by Event Store. I don't know the product, but every event sent to the queue gets a unique id. But (as I understand it) you require the id to be available BEFORE sending the event.
You can generally mix-and-match either of this solutions (especially the Hilo algorithm) with timestamps (like seconds from Unix Epoch, or something alike), in order to produce a (weak, non guaranteed) sortability. But generally I would avoid this, because if you generate ids on multiple sites, you introduce the risk of the clocks being unsynchronized, and generally other unsolved (or unsolvable) problems.
Probably I'm missing something, but this are the ones from the top of my head.
So, as far as i can tell, you are in an empasse. I would try really hard to put myself in one of the previous situations.
IMHO, your requirement is kinda flawed, because you have conflicting needs.
You want a unique id. The usual solutions use:
- guid. Can be generated centrally or locally. Really easy to implement. Kinda hard for a human reader, but YMMV. But you want incremental keys.
- centrally assigned key: you need a transactional system. But you want to do CQRS, and use Event Store. It seems to me that having a separate transactional system just to have an
IDENTITY_COLUMN
or aSEQUENCE
largely misses the point of doing CQRS. - use an HiLo generation approach. That is: every single client gets a unique seed (like 1 billion for the first client, 2 billions for the second, etc). So each client can generate locally a sequence. This sequence is distributed and uses sequential numbers, so there is no concurrency problems, but there is no global sorting for requests and you must ensure that no two clients get the same
Hi
value (relatively easy task). - use the id assigned by Event Store. I don't know the product, but every event sent to the queue gets a unique id. But (as I understand it) you require the id to be available BEFORE sending the event.
You can generally mix-and-match either of this solutions (especially the Hilo algorithm) with timestamps (like seconds from Unix Epoch, or something alike), in order to produce a (weak, non guaranteed) sortability. But generally I would avoid this, because if you generate ids on multiple sites, you introduce the risk of the clocks being unsynchronized, and generally other unsolved (or unsolvable) problems.
Probably I'm missing something, but this are the ones from the top of my head.
So, as far as i can tell, you are in an empasse. I would try really hard to put myself in one of the previous situations.
edited Nov 21 '18 at 8:11
answered Nov 19 '18 at 17:35
A. ChiesaA. Chiesa
3,33111231
3,33111231
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
|
show 9 more comments
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I don't see what's the conflicting need? I need a centralised sequential number generator independently of the number of client applications I have. And it must be unique as in two requests made at the same time from the same or different instances of my client application should generate different but sequential numbers. And that's all.
– iberodev
Nov 19 '18 at 21:47
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
I know usually relational databases are used for this purpose, but it just feels a bit too much to have a while DB relational engine for this purpose, so I was wondering whether there's another way maybe with an existing available product.
– iberodev
Nov 19 '18 at 21:49
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
And about using CQRS, it doesn't really matter. CQRS is about separating commands from queries in the system. I'm only talking here about business logic during the command phase. No read involved, just business logic and this "centralised sequential number generator" would simply be a repository implementation in my infrastructure layer.
– iberodev
Nov 19 '18 at 21:52
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
If CQRS is not relevant, you can omit it from your question. Because CQRS in its simplest form is only about separation of commands and queries. But usually CQRS lend itself to a very specific implementation, using an event queue to ingest commands, processed in a strictly asynchronous way, while the views are updates later. You're using Event Source and I'm assuming it's not by chance, so I assumed you need fast, asynchronous processing. This would rule out any centralized, transactional storage.If you don't, why are you using Event Store in the first plase? Just asking...
– A. Chiesa
Nov 19 '18 at 22:30
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
The Hilo generation approach seems interesting though. But without global sorting I'm afraid I wouldn't know how to make it work for my needs
– iberodev
Nov 19 '18 at 22:31
|
show 9 more comments
It is strange opinion
so it's a bit brutal having to use one just for this tiny
functionality.
Today SQLite is used as relational database even in mobile phones. It is simple, have small memory footprint and have binding for all popular programming languages. 20 years ago databases consumed many resources - today you can find database engine for all tasks. Also, if you need tiny key-pair store you can use BerkeleyDB.
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
add a comment |
It is strange opinion
so it's a bit brutal having to use one just for this tiny
functionality.
Today SQLite is used as relational database even in mobile phones. It is simple, have small memory footprint and have binding for all popular programming languages. 20 years ago databases consumed many resources - today you can find database engine for all tasks. Also, if you need tiny key-pair store you can use BerkeleyDB.
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
add a comment |
It is strange opinion
so it's a bit brutal having to use one just for this tiny
functionality.
Today SQLite is used as relational database even in mobile phones. It is simple, have small memory footprint and have binding for all popular programming languages. 20 years ago databases consumed many resources - today you can find database engine for all tasks. Also, if you need tiny key-pair store you can use BerkeleyDB.
It is strange opinion
so it's a bit brutal having to use one just for this tiny
functionality.
Today SQLite is used as relational database even in mobile phones. It is simple, have small memory footprint and have binding for all popular programming languages. 20 years ago databases consumed many resources - today you can find database engine for all tasks. Also, if you need tiny key-pair store you can use BerkeleyDB.
answered Nov 25 '18 at 0:52
Alexei ShcherbakovAlexei Shcherbakov
32726
32726
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
add a comment |
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
1
1
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
This adds a lot of overhead. Especially in a horizontal scaling situation where network overhead is an issue.
– Strom
Dec 1 '18 at 2:19
add a comment |
4
What should happen if something requests one of these numbers and then (for whatever reason) is unable to complete the rest of what it's trying to do and so the number ends up unused? (I.e. a "gap" is introduced in the sequence). If you cannot tolerate gaps then you have a massive synchronization convoy that's going to limit your scalability.
– Damien_The_Unbeliever
Nov 14 '18 at 15:22
3
I agree with Damien... the requirement for sequential numbers is typically a XY problem indication. It is much easier to apply sequential numbers to all existing data based on a non-sequential sorting condition than to correctly guess the correct sequence number for the future next entry in a parallel environment.
– grek40
Nov 14 '18 at 18:06
For the sake of this question, it won't happen. If the next sequence number is provided, nothing will prevent the logic from failing therefore there won't be any gaps. That scenario is out of scope.
– iberodev
Nov 14 '18 at 19:41
The scenario is the following. I'm using DDD with Event Sourcing. The next reference number available is requested in a domain service in order to generate an event with that reference number in it. The event will be produced. Even if it failed to be produced and he next sequential reference number is "wasted" it doesn't matter. The question remains, is there any product able to provide sequential numbers to multiple consumers without caring about what the consumers do with that reference number?
– iberodev
Nov 14 '18 at 19:42
1
There are two basic ways to do this. First, your dbase engine already knows how to do this and never gets it wrong regardless of how many apps add records. Google "sql identity column" for relevant hits. Second is to provide a unique finger print for the record that can serve as the primary key and a Date column for sequencing. A guid is good for that.
– Hans Passant
Nov 19 '18 at 14:44