Data storage parallelization in .NET Core - multithreading

I am a little lost in this task. There is a requirement for our caching solution to split a large data dictionary into partitions and perform operations on them in separate threads.
The scenario is: We have a large pool of data that is to be kept in memory (40m rows), the chosen strategy is first to have a Dictionary with int key. This dictionary contains a subset of 16 dictionaries that are keyed by guid and contain a data class.
The number 16 is calculated on startup and indicates CPU core count * 4.
The data class contains a byte[] which is basically a translated set of properties and their values, int pointer to metadata dictionary and checksum.
Then there is a set of control functions that takes care of locking and assigns/retrieves Guid keyed data based on a division of the first segment of guid (8 hex numbers) by divider. This divider is just FFFFFFFF / 16. This way each key will have a corresponding partition assigned.
Now I need to figure out how to perform operations (key lookup, iterations and writes) on these dictionaries in separate threads in parallel? Will I just wrap these operations using Tasks? Or will it be better to load these behemoth dictionaries into separate threads whole?
I have a rough idea how to implement data collectors, that will be the easy part I guess.
Also, is using Dictionaries a good approach? Their size is limited to 3mil rows per partition and if one is full, the control mechanism tries to insert on another server that is using the exact same mechanism.
Is .NET actually a good language to implement this solution?
Any help will be extremely appreciated.

Okay, so I implemented ReaderWriterLockSlim and implemented concurrent access through System.Threading.Tasks. I also managed to exclude any dataClass object from the storage, now it is only a dictionary of byte[]s.
It's able to store all 40 million rows taking just under 4GB of RAM and through some careful SIMD optimized manipulations performs EQUALS, <, > and SUM operation iterations in under 20ms, so I guess this issue is solved.
Also the concurrency throughput is quite good.
I just wanted to post this in case anybody faces similar issue in the future.

Related

Storing arrays in Cassandra

I have lots of fast incoming data that is organised thusly;
Lots of 1D arrays, one per logical object, where the position of each element in the array is important and each element is calculated and produced individually in parallel, and so not necessarily in order.
The data arrays themselves are not necessarily written in order.
The length of the arrays may vary.
The data is either read as an entire array at a time so makes sense to store the entire thing together.
The way I see it, the issue is primarily caused by the way the data is made available for writing. If it was all available together I'd just store the entire lot together at the same time and be done with it.
For smaller data loads I can get away with the postgres array datatype. One row per logical object with a key and an array column. This allows me to scale by having one writer per array, writing the elements in any order without blocking any other writer. This is limited by the rate of a single postgres node.
In Cassandra/Scylla it looks like I have the options of either:
Storing each element as its own row which would be very fast for writing, reads would be more cumbersome but doable and involve potentially lots of very wide scans,
or converting the array to json/string, reading the cell, tweaking the value then re-writing it which would be horribly slow and lead to lots of compaction overhead
or having the writer buffer until it receives all the array values and then writing the array in one go, except the writer won't know how long the array should be and will need a timeout to write down whatever it has by this time which ultimately means I'll need to update it at some point in the future if the late data turns up.
What other options do I have?
Thanks
Option 1, seems to be a good match:
I assume each logical object have an unique id (or better uuid)
In such a case, you can create something like
CREATE TABLE tbl (id uuid, ord int, v text, PRIMARY KEY (id, ord));
Where uuid is the partition key, and ord is the clustering (ordering) key, strong each "array" as a partition and each value as a row.
This allows
fast retrieve of the entire "array", even a big one, using paging
fast retrieve of an index in an array

Is it guaranteed that sequence numbers will increment by 1 EventHub?

I'm consuming from a single Azure EventHub partition, using the PartitionReceiver class in Java. I'm trying to understand the x-opt-sequence-number SystemProperty that is available in each EventData object that I receive.
Is it guaranteed that the sequence numbers increment by 1 per EventData consumed and that each possible sequence number exists in the partition? For example if I've consumed an Event with sequence number 5 and another with 10, based on this must there exist events with sequence numbers 6-9?
Thanks!
Corrected Context
My understanding was incorrect. It has been confirmed by the Event Hubs team that sequence numbers are contiguous within the scope of a single partition.
Original Answer
As I understand it, sequence numbers are not guaranteed to be sequential in the scope of a partition, though they often are. The only strict guarantee is that they will always be in increasing order with respect to when an event was enqueued to a specific partition. Sequence numbers are specific to a partition and shouldn't be compared across partitions.
If you need to ensure that you're sequencing with a strict and specific increment, your best bet is likely to be adding a custom bit of metadata for your application domain's sequence number in the user properties collection. Of course, that does get tricky when coordinating across publishers on multiple machines and like likely to surface performance trade-offs.

SnowFlake Stored Procedure Multi Threading

Being new to Snowflake I am trying to understand how to write JavaScript based Stored Procedures (SP) to take advantage of multi-thread/parallel processing.
My background is SQL Server and writing SP, taking advantage of performance feature such as degrees of parallelism, worker threads, indexing, column store segment elimination.
I am started to get accustomed to setting up the storage and using clustering keys, micro partitioning, and any other performance feature available, but I don't get how Snowflake SPs break down a given SQL statement into parallel streams. I am struggling to find any documentation to explain the internal workings.
My concern is producing SPs that serialise everything on one thread and become bottlenecks.
I am wondering if I am applying the correct technique/ need a different mindset to developing SPs.
I hope I have explained my concern sufficiently. In essence I am building a PoC to migrate an on-premise SQL Server DWH ETL solution to Snowflake/Matillion ELT solution, one aspect being evaluating the compute virtual warehouse size I need.
stateless UDF will run in parallel by default, this what I observed when do large amount of binary data importing via base64 encoding.
stateful UDF's run in parallel on the date as controlled by the PARTITION BY and ORDER BY clauses used on the data. The only trick to remember is to always force initialize your data, as the javascript instance can be used on subsequent PARTITON BY batches, thus don't rely on check for undefined to know if it's the first row.

Cassandra counter usage

I am finding some difficulties in the data modeling of an application which may involve the use of counters.
The app is basically a messaging app. Messages are bounded for free users, hence the initial plan of using a counter column to keep track of the total count.
I've discovered that batches (logged or not) cannot contain operations on both standard tables and counter ones. How do I ensure correctness if I cannot batch the operation I am trying to perform and the counter update together? Is the counter type really needed if there's basically no race condition on the column, being that associated to each individual user?
My second idea would be to use a standard int column to use only inside batches. Is this a viable option?
Thank you
If you can absolutely guarantee that each user will produce only one update at time then you could rely on plain ints to perform the job.
The problem however is that you will need to perform a read-before-write anti-pattern. You could solve this as well, eg skipping the read part by caching your ints and performing in-memory updates followed by writes only. This is viable by coupling your system with a caching server (e.g. Redis).
And thinking about it, you should still need to read these counters at some point, because if the number of messages a free user can send is bound to some value then you need to perform a check when they login/try to send a new message/look at the dashboard/etc and block their action.
Another option (if you store the messages sent by each user somewhere and don't want to add complexity to your system) could be to directly count them with a SELECT COUNT... type query, even if this could be become pretty inefficient very soon in the Cassandra world.

Lock Less Key Value data structure

I need a data structure to store 500k keys, each one with some associated data. 150 Threads will be running concurrently & accessing the keys. Once in a day I need to update the data structure since there may be some manipulation operation, say the key is deleted, new key is added or the data is changed.
When the data structure updation is in progress I can not block any of the 150 threads from accessing it.
I don't want to use current hash implementations like memcache or redis since the number of keys may grow in future & I want in-memory access for faster lookup?
Instead will prefer some data structure implementation in C/C++.
The Userspace RCU library contains a set of concurrent data structures implemented with the help of RCU. Among those a lock-free resizable hash table based on the articles
Ori Shalev and Nir Shavit. Split-ordered lists: Lock-free
extensible hash tables. J. ACM 53, 3 (May 2006), 379-405.
Michael, M. M. High performance dynamic lock-free hash tables
and list-based sets. In Proceedings of the fourteenth annual ACM
symposium on Parallel algorithms and architectures, ACM Press,
(2002), 73-82.
For more information you can see the comments in the implementation at http://git.lttng.org/?p=userspace-rcu.git;a=blob;f=rculfhash.c
LMDB can handle this http://symas.com/mdb/ Since it uses MVCC, writers don't block readers. You can update whatever/whenever and your 150 reader threads will run just fine. LMDB reads perform no blocking operations whatsoever, and scale perfectly linearly across any number of CPUs.
(Disclaimer: I am the author of LMDB)

Resources