Mordern Redis Cluster solution for easy operation.

Overview

undermoon logo

Undermoon Continuous Integration

Undermoon is a self-managed Redis clustering system based on Redis Cluster Protocol supporting:

  • Horizontal scalability and high availability
  • Cluster management through HTTP API
  • Automatic failover for both master and replica
  • Fast scaling

Any storage system implementing redis protocol could also somehow work with undermoon, such as KeyDB.

For more in-depth explanation of Redis Cluster Protocol and how Undermoon implement it, please refer to Redis Cluster Protocol.

Architecture

architecture

Metadata Storage

Metadata storage stores all the metadata of the whole undermoon cluster, including existing Redis instances, proxies, and exposed Redis clusters. Now it's an in-memory storage server called Memory Broker. When using undermoon-operator, this Memory Broker will change to use ConfigMap to store the data.

Coordinator

Coordinator will synchronize the metadata between broker and server proxy. It also actively checks the liveness of server proxy and initiates failover.

Storage Cluster

The storage cluster consists of server proxies and Redis instances. It serves just like the official Redis Cluster to the applications. A Redis Cluster Proxy could be added between it and applications so that applications don't need to upgrade their Redis clients to smart clients.

Chunk

Chunk is the smallest building block of every single exposed Redis Cluster. Each chunk consists of 4 Redis instances and 2 server proxies evenly distributed in two different physical machines. So the node number of each Redis cluster will be the multiples of 4 with half masters and half replicas.

The design of chunk makes it very easy to build a cluster with a good topology for workload balancing.

Getting Started

Run Undermoon in Kubernetes

Using undermoon-operator is the easiest way to create Redis clusters if you have Kubernetes.

helm install my-undermoon-operator undermoon-operator-
   
    .tgz

helm install \
    --set 'cluster.clusterName=my-cluster-name' \
    --set 'cluster.chunkNumber=2' \
    --set 'cluster.maxMemory=2048' \
    --set 'cluster.port=5299' \
    my-cluster \
    -n my-namespace \
    undermoon-cluster-
    
     .tgz

    
   

See the README.md of undermoon-operator for how to use it.

Run Undermoon Using Docker Compose

See docker compose example.

Setup Undermoon Manually

Or you can set them up without docker following this docs: setting up undermoon manually.

Development

undermoon tries to avoid unsafe and some calls that could crash like unwrap.

Run the following commands before committing your codes:

$ make lint
$ make test

See more in the development guide.

Documentation

API

Comments
  • Optimization

    Optimization

    • [x] Change RwLock on server proxy meta to
      • (1) use mutex lock on write operation and use atomic pointer for read and write
      • (2) or Use CAS with https://github.com/vorner/arc-swap
    • [x] Batch sendto syscall.
    • [x] Optimize memory copy
    • [x] Let Resp objects just store the index of the Redis packet to reduce memory allocation.
    opened by doyoubi 2
  • Bump regex from 1.5.4 to 1.5.6

    Bump regex from 1.5.4 to 1.5.6

    Bumps regex from 1.5.4 to 1.5.6.

    Changelog

    Sourced from regex's changelog.

    1.5.6 (2022-05-20)

    This release includes a few bug fixes, including a bug that produced incorrect matches when a non-greedy ? operator was used.

    1.5.5 (2022-03-08)

    This releases fixes a security bug in the regex compiler. This bug permits a vector for a denial-of-service attack in cases where the regex being compiled is untrusted. There are no known problems where the regex is itself trusted, including in cases of untrusted haystacks.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies rust 
    opened by dependabot[bot] 1
  • Bump tokio from 1.8.1 to 1.8.4

    Bump tokio from 1.8.1 to 1.8.4

    Bumps tokio from 1.8.1 to 1.8.4.

    Release notes

    Sourced from tokio's releases.

    Tokio v1.8.4

    1.8.4 (November 15, 2021)

    This release backports a bugfix for a data race when sending and receiving on a closed oneshot channel ([RUSTSEC-2021-0124]) from v1.13.1.

    Fixed

    • sync: fix a data race between oneshot::Sender::send and awaiting a oneshot::Receiver when the oneshot has been closed (#4226)

    Tokio v1.8.3

    1.8.3 (July 22, 2021)

    This release backports two fixes from 1.9.0

    Fixed

    • Fix leak if output of future panics on drop (#3967)
    • Fix leak in LocalSet (#3978)

    #3967: tokio-rs/tokio#3967 #3978: tokio-rs/tokio#3978

    Tokio 1.8.2

    Fixes a missed edge case from 1.8.1.

    Fixed

    • runtime: drop canceled future on next poll (#3965)
    Commits
    • 2273eb1 chore: fix CI on master (#4008)
    • 249f05c chore: fix output of macro after new rustc release (#4189)
    • 2bf6132 macros: fix type resolution error in #[tokio::main] (#4176)
    • c9228bf macros: make tokio-macros attributes more IDE friendly (#4162)
    • 441427c macros: fix wrong error messages (#4067)
    • cc7d9e1 chore: explicitly relaxed clippy lint for runtime entry macro (#4030)
    • f49b7fc tokio-macros: compat with clippy::unwrap_used (#3926)
    • ea87e4e net: fix the uds_datagram tests with the latest nightly stdlib (#3952)
    • e2e7b5e examples: replace time crate with httpdate (#4169)
    • 9a58f7f tests: update Nix to 0.22.0 (#3951)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies rust 
    opened by dependabot[bot] 1
  • Bump crossbeam-deque from 0.7.3 to 0.7.4

    Bump crossbeam-deque from 0.7.3 to 0.7.4

    Bumps crossbeam-deque from 0.7.3 to 0.7.4.

    Changelog

    Sourced from crossbeam-deque's changelog.

    Version 0.8.1

    • Support targets that do not have atomic CAS on stable Rust (#698)

    Version 0.8.0

    • Bump the minimum supported Rust version to 1.36.
    • Bump crossbeam-channel to 0.5.
    • Bump crossbeam-deque to 0.8.
    • Bump crossbeam-epoch to 0.9.
    • Bump crossbeam-queue to 0.3.
    • Bump crossbeam-utils to 0.8.
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies rust 
    opened by dependabot[bot] 1
  • Resolve peer host for SLAVEOF each time

    Resolve peer host for SLAVEOF each time

    Now the replicator module only resolves the hostname at the beginning. This may result in

    • outdated IP in k8s.
    • InvalidAddress error in k8s if the first resolve failed.
    bug 
    opened by doyoubi 1
  • Work around bug in pooled redis client

    Work around bug in pooled redis client

    The pooled Redis client could result in getting the reply of the last request in server proxy. I still have no idea why. But replacing the pooled Redis client with a non-pooled one could fix the problem. This will not have any performance impact on server proxy because the server proxy has already used some caching strategy.

    opened by doyoubi 1
  • Support moving slots around

    Support moving slots around

    The current migration protocol only supports double scale which is not flexible for large clusters. We need to support moving the slot around just like native Redis Cluster.

    issue: https://github.com/doyoubi/undermoon/issues/54

    This PR implements the migration protocol described in https://github.com/doyoubi/undermoon/issues/54#issuecomment-569629973

    opened by doyoubi 1
  • New Migration Process through SCAN command

    New Migration Process through SCAN command

    Recent Migration Limitations

    There are two drawbacks for the current migration process based on the current approach - trigger replication between the source Redis and destination Redis:

    • We can only perform a double scale because multiple FULL SYNC to a Redis node can't preserve all the data - the latter one will remove some of the right data transferred by the formers.
    • We have to wait for a fixed long time to HOPE that the replication between two Redis nodes is done because there's no way to know it. (Well, actually we can perform a block and check method).

    Solutions

    There are two solutions:

    • (1) Implement the Redis Replication Protocol which consists of two parts:
      • RDB parsing (hard and time-consuming to maintain)
      • Replication Network Protocol (not that hard but feasible)
    • (2) Use SCAN, DUMP, RESTORE to mimic the replication.

    I don't want to use the first solution since there are just too many works for the RDB parsing. And we need to keep updating the codes as the RDB format changes.

    The second one should be able to be compatible with the future versions of Redis.

    The SCAN command has a great property that it can guarantee that all the keys set before the first SCAN command will finally be returned, for multiple times sometimes though. We can perform a 3 stage migration to mimic the replication.

    • Wait for all the commands to be finished by Redis.
    • Start the scanning and forward the data to peer Redis.
    • Redirect all the write operation after the first SCAN to peer Redis.

    But it also has some problems:

    • It will have some impacts on the latency while scanning the data. But that could be tunable.
    • If a large collection type key gets updated frequently, we need to store the large data from DUMP again and again, which could result in a large amount of memory.

    Detailed Steps for Scanning

    • Redirect all the later commands to Queue_block1.
    • Wait for all the existing commands to be finished. We can maintain a counter for running commands to achieve that.
    • Start to send SCAN, DUMP to get the data and add RESTORE command to Queue1. When SCAN is done, mark the Queue1 as SENT_FINISHED.
    • When the first SCAN command gets the reply, release all the commands in Queue_block1.
    • Let all the commands in Queue_block1 and the commands after the first SCAN to another send function which for all the write requests, do the following with Lua script to support atomic:
      • apply the write operation
      • get the latest version of the key by DUMP and forward the new data to Queue2
    • Forward all the RESTORE commands in Queue1. Once the Queue1 is set SENT_FINISHED and is empty, start to forward the RESTORE commands in Queue2.
    • When Queue1 is set SENT_FINISHED and is empty, start to block the commands in Queue_block2, wait for all the commands in Queue2 to be sent.
    • Migration source proxy commits the process with destination proxy. Destination starts to handle new slots. Source proxy starts to redirect the migrated slots to destination proxy.
    • Release the commands in Queue_block2. Redirect all the keys inside migrated slots to destination proxy.
    • INFOMGR starts to return success.
    • Wait for the Coordinator to commit the migration.
    • Delete the migrated out data in source proxy.
    enhancement 
    opened by doyoubi 1
  • AUTH not cleaned up when recreating new cluster.

    AUTH not cleaned up when recreating new cluster.

    When a server_proxy deleted an old cluster and create a new one, the existing connections are still tagged the old cluster name, which results in db not found error.

    enhancement 
    opened by doyoubi 1
  • Rename Host to Proxy

    Rename Host to Proxy

    At the first time, I think we will only deploy one proxy per host. So host and proxy are the same and are used interchangeably in the codes and API. Now to support some clients and redis cluster proxies which do not support AUTH command for the backend clusters, we need to deploy multiple proxies in the same machine to support multiple tenants. I have changed the API in https://github.com/doyoubi/undermoon/pull/21. Later we need to change the host in code to proxy.

    opened by doyoubi 1
  • Bump version to 0.6.2

    Bump version to 0.6.2

    opened by doyoubi 0
  • v0.6 Road map

    v0.6 Road map

    Undermoon v0.6 will come with some breaking changes and further improvements on migration during scaling.

    Data Migration

    Reliability

    • [ ] Implement a new checker in Golang in place of the checker in undermoon-operator
      • Related issue: https://github.com/doyoubi/undermoon-operator/issues/33
    opened by doyoubi 0
  • Persistency?

    Persistency?

    Hi Do you have plan to add persistency data to your implementation? (or already implemented?) If I turn off all nodes and run them again, will there be a redis data loss?

    opened by sanarena 2
  • v0.5 Road Map

    v0.5 Road Map

    v0.5 Road Map

    While v0.4 was focusing on working with undermoon-operator to support undermoon in kubernetes, v0.5 will focus on accessibility for users and contributors from the open-source community.

    The key part here is to be compatible with some popular Redis Cluster clients.

    opened by doyoubi 0
Releases(v0.6.2)
Owner
null
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
RCProxy - a lightweight, fast but powerful Redis Cluster Proxy written in Rust

RCProxy - a lightweight, fast but powerful Redis Cluster Proxy written in Rust

Cris Liao 16 Dec 4, 2022
A Redis module that provides rate limiting in Redis as a single command.

redis-cell A Redis module that provides rate limiting in Redis as a single command. Implements the fairly sophisticated generic cell rate algorithm (G

Brandur Leach 1.1k Jan 6, 2023
rust-jsonnet - The Google Jsonnet( operation data template language) for rust

rust-jsonnet ==== Crate rust-jsonnet - The Google Jsonnet( operation data template language) for rust Google jsonnet documet: (http://google.github.io

Qihoo 360 24 Dec 1, 2022
A html document syntax and operation library written in Rust, use APIs similar to jQuery.

Visdom A server-side html document syntax and operation library written in Rust, it uses apis similar to jQuery, left off the parts thoes only worked

轩子 80 Dec 21, 2022
An i386 operation system written in pure rust for fun and no profit.

OrustS An i386 operation system written in pure rust (for fun and no profit). This operation system is under active developing. Checklist implement a

M4tsuri 10 Aug 12, 2022
Image operation rust library

Image operation rust library

LongYinan 166 Dec 20, 2022
Detects orphan configmaps and secrets in a Kubernetes cluster

KubExplorer Warning: Proof of concept. Feedback is much welcome. Discovers and prints out any Configmaps and Secrets not linked to any of the followin

Pavel Pscheidl 56 Oct 21, 2022
Zenith substitutes PostgreSQL storage layer and redistributes data across a cluster of nodes

Zenith substitutes PostgreSQL storage layer and redistributes data across a cluster of nodes

null 5.7k Jan 6, 2023
Gossip-based cluster membership discovery (SWIM)

Foca: Cluster membership discovery on your terms Foca is a building block for your gossip-based cluster discovery. It's a small no_std + alloc crate t

null 43 Jan 3, 2023
Visually cluster your emails by sender, domain, and more to identify waste

Postsack A high level visual overview of swaths of email TLDR! A web demo that shows how Postsack clusters a set of 10.000 fake emails Do you have man

Benedikt Terhechte 298 Dec 26, 2022
Northstar is a horizontally scalable and multi-tenant Kubernetes cluster provisioner and orchestrator

Northstar Northstar is a horizontally scalable and multi-tenant Kubernetes cluster provisioner and orchestrator. Explore the docs » View Demo · Report

Lucas Clerisse 1 Jan 22, 2022
One-Stop Solution for all boilerplate needs!

One Stop Solution for all boilerplate needs! Consider leaving a ⭐ if you found the project helpful. Templa-rs Templa-rs is a one-of-a-kind TUI tool wr

IEEE VIT Student Chapter 27 Aug 28, 2022
Stylist is a CSS-in-Rust styling solution for WebAssembly Applications.

Stylist Stylist is a CSS-in-Rust styling solution for WebAssembly Applications. This is a fork of css-in-rust. Install Add the following to your Cargo

Kaede Hoshikawa 190 Dec 30, 2022
My solution for the advent of code 2021, mainly written in Rust

Advent-of-Code-2021 My solution for the advent of code 2021, written in Rust Error Handle NOPE!!! unwrap() everything everywhere Use To run all of the

Nguyen Le Duy 0 Jan 8, 2022
Aptos-core strives towards being the safest and most scalable layer one blockchain solution.

Aptos-core strives towards being the safest and most scalable layer one blockchain solution. Today, this powers the Aptos Devnet, tomorrow Mainnet in order to create universal and fair access to decentralized assets for billions of people.

Aptos Labs 4.7k Jan 6, 2023
Sanzu is a graphical remote desktop solution

Sanzu Sanzu is a graphical remote desktop solution. It is composed of: a server running on Unix or Windows which can stream a X11 or a Windows GUI env

CEA IT Security 95 Dec 23, 2022
GaiaX dynamic template engine is a lightweight cross-platform solution for pure native dynamic card.

GaiaX dynamic template engine is a lightweight cross-platform solution for pure native dynamic card, developed by Alibaba YouKu technology team GaiaX

Alibaba 774 Dec 22, 2022
A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms.

Crypto-rs A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms. This is a Rust implementation

houseme 4 Nov 28, 2022
🍹Branch and bound solution using Rust to calculate an optimal cocktail ingredient list of arbitrary length 🍸

Calculating an Optimal Cocktail Ingredient List Tom Explains the Problem You have 100 different ingredients You have 20 cocktails, each of which use 2

Stephan Hügel 7 Jan 9, 2023