0

How do you think Scala can help us to write a distributed memory service like Redis (but multi-thread)?

Scala programming encourages us to use immutable data in order to avoid shared data and race conditions, however in this kind of data storage immutable data can't help us (I think).

Blocking threads would be the solution?

3
  • Your question is too general. Please provide some detail: what are your aspects, what kind of data would you be storing, why isn't Redis or other frameworks good, what research have you done, etc....? And last but not least: blocking is never the solution :) Commented Dec 5, 2013 at 21:39
  • I'm not intended to create a new service, it's only curiosity :) Ofcourse I have a lot of doubts but the biggest is about concurrency. If I can't take advantage of immutable data, How can I handle multiple threads accessing to the same shared source? Commented Dec 5, 2013 at 21:51
  • In addition, we use Redis on production and we have some problems because it's single-thread. This means that if it has to do a long time operation, incoming requests will have to wait...(blocking) Commented Dec 5, 2013 at 21:54

1 Answer 1

3

Scala deals with immutable data and mutable data equally well.

Sure it's highly encouraged to use immutable data - for any data which can be shared across threads/actors.

But it's also highly encouraged to use mutable data dedicated to individual threads/actors - i.e. in a context which can never be shared across threads/actors.

A simple high-level concurrency pattern is:

  1. Make Mutable Data Private To Each Actor:
    • dedicate mutable types to individual actors
    • manipulate mutable data with your actor act/recieve/react methods
  2. Only Share Immutable Data Between Actors
    • send messages to other actors - but convert the mutable data to immutable data and only send the latter between actors.
  3. Never Send a reference to an Actor in a message to Another Actor
    • Due to (1), Actors themselves become mutable
    • Due to (2), they shouldn't be shared
    • This stops ActorA from invoking any methods on ActorB - all communication should be via messages (methods ! and !!)
  4. Identify long-running operations and make them asynchronous. Even simple operations that go beyond the CPU + L1 Cache + L2 Cache can can be 100,000s to 10,000,000s times slower than faster in-CPU operations, E.g. reading volumous data from memory, reading/writing to disk, reading/writing to the network - see table at end: http://norvig.com/21-days.html
  5. As a rule, don't block on asynchronous operations - it usually "takes out" a thread (consumes resources), if not carefully designed can lead to deadlock (runtime failure) and can always be handled in a non-blocking manner. If you need to process an asynchronous response, have the asynchronous request return a Future[T] as part of the initiation. Then specify response handling code via Future.onComplete (or even better via Future.flatMap/Map/withFilter/Recover and their for-comprehension equivalents - which are handy 'monadic'-wrappers around onComplete).
Sign up to request clarification or add additional context in comments.

3 Comments

the referenced table must be sort of outdated, as an i-7 of the previous generation allows main memory acess @ 29 ns. (must apply to the other components as well somehow). the relations tho might still hold true.
No doubt the precise figures are out of date. All of them should march lower together. But the relatives between the figures stand pretty well over time. Off-topic trivia: early generation computers took about a second to read all internal memory (little memory, slow reads) and the latest generation take about the same time (far more memory, far faster reads).
1 sec? haha :D awesome

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.