{"id":13656515,"url":"https://github.com/ktoso/akka-raft","last_synced_at":"2025-03-28T18:32:19.268Z","repository":{"id":13313977,"uuid":"16000527","full_name":"ktoso/akka-raft","owner":"ktoso","description":"A toy project implementing RAFT on top of Akka Cluster (not prod ready)","archived":true,"fork":false,"pushed_at":"2016-08-09T14:53:59.000Z","size":355,"stargazers_count":280,"open_issues_count":57,"forks_count":42,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-03-19T22:17:08.359Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://blog.project13.pl","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ktoso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-17T13:38:10.000Z","updated_at":"2024-11-12T04:28:18.000Z","dependencies_parsed_at":"2022-08-19T13:40:53.132Z","dependency_job_id":null,"html_url":"https://github.com/ktoso/akka-raft","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktoso%2Fakka-raft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktoso%2Fakka-raft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktoso%2Fakka-raft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktoso%2Fakka-raft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ktoso","download_url":"https://codeload.github.com/ktoso/akka-raft/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246080894,"owners_count":20720608,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T05:00:22.404Z","updated_at":"2025-03-28T18:32:18.545Z","avatar_url":"https://github.com/ktoso.png","language":"Scala","funding_links":[],"categories":["CRDT","分布式开发"],"sub_categories":["微服务框架"],"readme":"akka-raft\n=========\n\n\u003ca href=\"https://travis-ci.org/ktoso/akka-raft\"\u003e\u003cimg src=\"https://travis-ci.org/ktoso/akka-raft.svg\"/\u003e\u003c/a\u003e\n\nThis is an akka based implementation of the **Raft consensus algorithm**.\nIt is generic enough that you can build your own replicated state machines on top of it (with raft keeping track of the consensus part of it).\n\nThis implementation is **akka-cluster aware**, so it can be easily deployed on multiple machines.\nImplementation wise, all parts of the raft whitepaper are covered:\n\n* Leader election\n* Dynamic membership changes (with transitioning periods implemented as Joint Consensus)\n* Deployment across multiple nodes\n* Log compaction, via snapshotting\n\nDisclaimer\n----------\n\n:boom: :boom:\n\n**This project is a side-project of mine and is still work in progress (treat it as EARLY PREVIEW) and has a number of known protocol bugs (see [Issues](https://github.com/ktoso/akka-raft/issues)). It is NOT recommended to be used in production, however it's a great project to play around with implementing and discussing the Raft protocol.** \n\n:boom: :boom:\n\nIn other words: Use at own risk, best not on any production-like environments (for now).\n\nBasic info\n----------\n\nRaft is a distributed consensus algorithm, much like Paxos (but simpler).\nThis implementation is fully akka (and akka-cluster) based, and can be used to deploy a replicated state machine on top of akka clusters.\n\n**THIS API IS STILL SUBJECT TO CHANGE**\n\n```scala\nclass WordConcatRaftActor extends RaftActor {\n\n  type Command = Cmnd\n\n  var words = Vector[String]()\n\n  /** \n   * Called when a command is determined by Raft to be safe to apply; \n   * Application results are sent back to the client issuing the command.\n   */\n  def apply = { \n    case AppendWord(word) =\u003e\n      words +: word\n      log.info(\"Applied command [{}], full words is: {}\", command, words)\n\n      word // will be sent back to original actor, who sent the AppendWord command\n\n    case GetWords =\u003e\n      val res = words.toList\n      log.info(\"Replying with {}\", res)\n      res\n  }\n}\n\n// ...\n\nval members = (1 to 3) map { i =\u003e system.actorOf(Props[WordConcatRaftActor], name = s\"raft-member-$i\") }\nval clusterConfiguration = ClusterConfiguration(raftConfiguration.members + additionalActor) // 0, 1\n\nmembers foreach { _ ! ChangeConfiguration(clusterConfiguration)\n\n// todo implement re-routing if you send to a non-leader\n// then send messages to it; the state machine will only be applied when consensus has been reached about a value\nleader ! ClientRequest(AppendWord(\"I\"))\nleader ! ClientRequest(AppendWord(\"like\"))\nleader ! ClientRequest(AppendWord(\"capybaras\"))\n\n// ... after some time\nleader ! GetWords\n\nexpectMsg(List(\"I\", \"like\", \"capybaras\"))\n\n```\nAnd if you want to enable snapshotting support it's as simple as implementing one method and matching for `InstallSnapshot`\nin your Actor:\n\n```scala\nclass SnapshottingWordConcatRaftActor extends RaftActor {\n\n  type Command = Cmnd\n\n  var words = Vector[String]()\n\n  def apply = {\n    case AppendWord(word) =\u003e\n      words +: word\n      word\n\n    case GetWords =\u003e\n      val res = words.toList\n      log.info(\"Replying with {}\", res)\n      res\n\n    case InstallSnapshot(snapshot) =\u003e\n      words = snapshot.data.asInstanceOf[Vector[String]]\n  }\n\n  override def prepareSnapshot(meta: RaftSnapshotMetadata) =\n    Future.successful(Some(RaftSnapshot(meta, words)))\n}\n```\n\nRaftClientActor\n---------------\n\nIn the above examples, the **client** implementation is very naive, and assumes you have some way\nof finding out who the current Leader is (as this is a requirement to interact with any Raft cluster).\nThankfully, you can use the provided `RaftClientActor`, which works like a proxy that forwards all your messages\nto the current _Leader_, or stashes them if the cluster has no _Leader_ at the moment (is undergoing an election) and\nsends the messages once the Leader becomes available.\n\n\n\n\nLicense\n-------\n\nSimply: *Apache 2.0*\n\nIssues, Pull Requests as well as Tweets and Emails are more than welcome!\n\nLinks \u0026 kudos\n-------------\n\n* An excellent analysis using *fuzz testing of akka-raft, discovering a number of protocol bugs by @colin-scott*, blog post [Fuzzing Raft for Fun and Publication](https://colin-scott.github.io/blog/2015/10/07/fuzzing-raft-for-fun-and-profit/) and linked inside it the whitepaper draft.\n\n\n* [Raft - In Search of an Understandable Consensus Algorithm](https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf) whitepaper\n* See other implementations (many lanugages) on [raftconsensus.github.io](http://raftconsensus.github.io)\n* Docs on [akka-cluster](http://doc.akka.io/docs/akka/2.3.0-RC2/scala/cluster-usage.html) in *2.3.0-RC2*.\n\nWe have discussed this paper both in Kraków and London, on these _awesome_ reading clubs (drop by if you're into CS papers!):\n\n* [Software Craftsmanship Kraków - SCKRK.com](http://www.meetup.com/sc-krk/events/134500362/)\n* [Paper Cup - the reading club - London](http://www.meetup.com/Paper-Cup/events/153170202/)\n\n[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/ktoso/akka-raft/trend.png)](https://bitdeli.com/free \"Bitdeli Badge\")\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fktoso%2Fakka-raft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fktoso%2Fakka-raft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fktoso%2Fakka-raft/lists"}