{"id":33179209,"url":"https://github.com/allengeorge/libraft","last_synced_at":"2025-11-30T13:04:41.400Z","repository":{"id":57735790,"uuid":"12204684","full_name":"allengeorge/libraft","owner":"allengeorge","description":"Raft distributed consensus protocol in Java","archived":true,"fork":false,"pushed_at":"2015-11-23T16:54:36.000Z","size":4838,"stargazers_count":98,"open_issues_count":23,"forks_count":28,"subscribers_count":16,"default_branch":"master","last_synced_at":"2023-07-04T15:13:34.179Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://libraft.io","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/allengeorge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-19T01:24:25.000Z","updated_at":"2023-01-28T19:28:35.000Z","dependencies_parsed_at":"2022-08-24T11:20:46.113Z","dependency_job_id":null,"html_url":"https://github.com/allengeorge/libraft","commit_stats":null,"previous_names":[],"tags_count":2,"template":null,"template_full_name":null,"purl":"pkg:github/allengeorge/libraft","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allengeorge%2Flibraft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allengeorge%2Flibraft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allengeorge%2Flibraft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allengeorge%2Flibraft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/allengeorge","download_url":"https://codeload.github.com/allengeorge/libraft/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allengeorge%2Flibraft/sbom","scorecard":{"id":185311,"data":{"date":"2025-08-11","repo":{"name":"github.com/allengeorge/libraft","commit":"00d68bb5e68d4020af59df3c8a9a14380108ac89"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/16 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T19:42:39.436Z","repository_id":57735790,"created_at":"2025-08-16T19:42:39.436Z","updated_at":"2025-08-16T19:42:39.436Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27392797,"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","status":"online","status_checked_at":"2025-11-30T02:00:05.582Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-11-16T03:00:36.826Z","updated_at":"2025-11-30T13:04:41.393Z","avatar_url":"https://github.com/allengeorge.png","language":"Java","funding_links":[],"categories":["分布式开发"],"sub_categories":[],"readme":"# libraft [![Build Status](https://travis-ci.org/allengeorge/libraft.png?branch=master)](https://travis-ci.org/allengeorge/libraft) [![Coverage Status](https://coveralls.io/repos/allengeorge/libraft/badge.png?branch=master)](https://coveralls.io/r/allengeorge/libraft?branch=master)\n\nlibraft is a Java library that implements the [Raft distributed consensus protocol]\n(https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf \"In Search of an Understandable Consensus Algorithm\").\n\n## Release History\n\n* **0.1.0**: Initial release. (11 Dec, 2013)\n* **0.1.1**: Bug-fix release. (25 Jan, 2014)\n\nFor more information check the detailed [release history] (https://github.com/allengeorge/libraft/wiki/Release-History \"libraft release history\").\n\n## Features\n\nlibraft **completely** implements all checked features below. Unchecked features are\nplanned but do not have an implementation timeline.\n\n- [x] Leader election\n- [x] Log replication\n- [o] Log compaction (snapshots)\n- [o] Online cluster reconfiguration\n\n## Overview\n\nlibraft consists of 2 components:\n\n* libraft-core\n* libraft-agent\n\nCorrectness, safety, and understandability were major factors during design\nand implementation. Performance was an explicit non-goal.\n\n### libraft-core\n\nlibraft-core contains an implementation of the Raft algorithm. It also defines interfaces\nfor the components (such as timers, packet senders, log and metadata storage, *etc*.) it needs\nto operate. These interfaces make very few demands on the underlying implementation and should\nbe easy to integrate into an existing stack.\n\n### libraft-agent\n\nlibraft-agent:\n\n1. Provides reference implementations for the interfaces defined in libraft-core.\n2. Provides a facade over libraft-core that can be instantiated to provide consensus services.\n\nIt uses JDBC for persistence, TCP connections for networking, and json for the\nwire format. It wires these implementations up to the algorithm classes from libraft-core.\nlibraft-agent also defines a simple [json configuration format] (#configuring-libraft \"Configuring libraft\")\nwith which users can configure their cluster. Finally, it provides a single class - `RaftAgent` - with\nwhich applications can control the lifecycle of a Raft server and interact with the Raft cluster.\n\n### Samples\n\nlibraft also comes with a fully-implemented sample application in `libraft-samples/kayvee`. *KayVee*\nis a distributed, consistent, key-value store that uses `RaftAgent` to durably replicate key-value\npairs to a cluster. It demonstrates how libraft can be integrated into an application to provide consensus services.\n\n## Getting libraft\n\nThe simplest way to use libraft is through Gradle or Maven - simply\nadd `libraft-agent` as a dependency. Replace `${libraft.version.latest}`\nin the code below with the latest version on Maven Central.\n\n### Gradle\n\n```groovy\ndependencies {\n    compile 'io.libraft:libraft-agent:${libraft.version.latest}'\n}\n```\n\n### Maven\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.libraft\u003c/groupId\u003e\n        \u003cartifactId\u003elibraft-agent\u003c/artifactId\u003e\n        \u003cversion\u003e${libraft.version.latest}\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\nAlternatively, if you only want the algorithm components and\nintend to build your own implementations for its interfaces, only `libraft-core` is necessary.\nSimply add `libraft-core` as a dependency, and replace `${libraft.version.latest}`\nin the code below with the latest version on Maven Central.\n\n### Gradle\n\n```groovy\ndependencies {\n    compile 'io.libraft:libraft-core:${libraft.version.latest}'\n}\n```\n\n### Maven\n\n```xml\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.libraft\u003c/groupId\u003e\n        \u003cartifactId\u003elibraft-core\u003c/artifactId\u003e\n        \u003cversion\u003e${libraft.version.latest}\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n## Configuring libraft\n\n`RaftAgent` can be configured in one of two ways:\n\n1. A json configuration file.\n2. A `RaftConfiguration` instance.\n\nBoth methods are equivalent and have the same properties.\n\n### Properties\n\n`libraft-agent` exposes the following configuration properties. **bolded** properties are **required**.\n\n* `minElectionTimeout`: minimum election timeout for a Raft server\n* `additionalElectionTimeoutRange`: maximum additional time added to `minElectionTimeout` to get the applied election timeout.\n                                    Election timeout is defined using the following formula: `electionTimeout = minElectionTimeout + randomInRange(0, additionalElectionTimeoutRange)`.\n* `rpcTimeout`: maximum time a Raft server will wait for a response to an RPC request\n* `heartbeatInterval`: maximum time between messages from a Raft leader\n* `connectTimeout`: maximum time a Raft server will wait to establish a connection to another Raft server\n* `minReconnectInterval`: minimum interval a Raft server will wait before reconnecting to another Raft server\n* `additionalReconnectIntervalRange`: maximum additional time added to `minReconnectInterval` to get the applied reconnect interval.\n                                      Reconnect interval is defined using the following formula: `reconnectInterval = minReconnectInterval + randomInRange(0, additionalReconnectIntervalRange)`.\n* **`database`**: Raft database configuration block\n    * **`driverClass`**: fully-qualified class name of the JDBC driver\n    * **`url`**: JDBC connection URL\n    * **`user`**: database user id\n    * **`password`**: database password (may be empty or omitted)\n* **`cluster`**: Raft cluster configuration block\n    * **`self`**: unique id of the *local* Raft server\n    * **`members`**: Raft cluster configuration. Defines *all* the members in the cluster, *including* the local server.\n        * **`id`**: unique id of the Raft server\n        * **`endpoint`**: address - in \"host:port\" format - at which this server can be reached\n\n### Sample\n\nA sample configuration file for a 5-server Raft cluster is given below. Note that\n`self` is `S_00`, indicating that this is the configuration file for server `S_00` in the cluster.\nThis file includes *all* fields, both required and optional.\n\n```json\n{\n    \"minElectionTimeout\": 180,\n    \"additionalElectionTimeoutRange\": 120,\n    \"rpcTimeout\": 30,\n    \"heartbeatInterval\": 15,\n    \"connectTimeout\": 5000,\n    \"minReconnectInterval\": 10000,\n    \"additionalReconnectIntervalRange\": 1000,\n\n    \"database\": {\n        \"driverClass\": \"org.h2.Driver\",\n        \"url\": \"jdbc:h2:test_db\",\n        \"user\": \"test\",\n        \"password\": \"test\"\n    },\n\n    \"cluster\": {\n        \"self\": \"S_00\",\n        \"members\": [\n            {\n                \"id\": \"S_00\",\n                \"endpoint\": \"192.168.1.100:9990\"\n            },\n            {\n                \"id\": \"S_01\",\n                \"endpoint\": \"192.168.1.100:9991\"\n            },\n            {\n                \"id\": \"S_02\",\n                \"endpoint\": \"192.168.1.100:9992\"\n            },\n            {\n                \"id\": \"S_03\",\n                \"endpoint\": \"192.168.1.100:9993\"\n            },\n            {\n                \"id\": \"S_04\",\n                \"endpoint\": \"192.168.1.100:9994\"\n            }\n        ]\n    }\n}\n```\n\n## Using libraft\n\nThe simplest way to use libraft is to instantiate a `RaftAgent` within an application\nnode (such as a server). This `RaftAgent` will allow the node to participate in a Raft cluster:\nit can become a leader or follower and will be notified of leadership changes as well as\napplied (i.e. committed) commands.\n\nCreating a `RaftAgent` requires:\n\n1. A valid [configuration file or object] (#configuring-libraft \"Configuring libraft\").\n2. A specialization of `Command` for the application commands that will be committed to the Raft cluster.\n3. A specialization of `RaftListener` that will be notified of leadership changes and applied commands.\n\nSample json configuration file (\"agent.config\"):\n\n```json\n{\n    \"database\": {\n        \"driverClass\": \"org.h2.Driver\",\n        \"url\": \"jdbc:h2:test_db\",\n        \"user\": \"test\",\n        \"password\": \"test\"\n    },\n\n    \"cluster\": {\n        \"self\": \"agent0\",\n        \"members\": [\n            {\n                \"id\": \"agent2\",\n                \"endpoint\": \"192.168.1.100:9990\"\n            },\n            {\n                \"id\": \"agent1\",\n                \"endpoint\": \"192.168.1.100:9991\"\n            },\n            {\n                \"id\": \"agent0\",\n                \"endpoint\": \"192.168.1.100:9992\"\n            }\n        ]\n    }\n}\n```\n\nSample java code:\n\n```java\n\n//\n// Command to be replicated to the Raft cluster\n//\n\npublic class MyCommand implements Command {\n\n    enum CommandType {\n        GET,\n        SET\n    }\n\n    @JsonProperty\n    CommandType commandType;\n\n    @JsonProperty\n    String key;\n\n    @JsonProperty\n    String value;\n\n    // constructor, getters, and setters follow...\n}\n\n//\n// Listener that will be notified of events in the Raft cluster\n//\n\npublic class MyRaftListener implements RaftListener {\n\n    @Override\n    public void onLeadershipChange(@Nullable String leader) {\n        //...\n    }\n\n    @Override\n    public void applyCommitted(long index, Command command) {\n        //...\n    }\n}\n\n//\n// Application code\n//\n\n// create the listener that will be tied to the RaftAgent\nRaftListener raftListener = new MyRaftListener();\n\n// create the RaftAgent using the configuration in \"agent.config.json\"\n// the listener created above of leadership changes and applied commands\nRaftAgent raftAgent = RaftAgent.fromConfigurationFile(\"agent.config\", raftListener);\n\n// indicate that the application command uses Jackson annotations\n// RaftAgent has special support for this\nraftAgent.setupJacksonAnnotatedCommandSerializationAndDeserialization(MyCommand.class);\n\n// initialize the RaftAgent\n// (sets up state, but does not connect to any servers, start any timers, etc.)\n// this allows the application to assume that it has sole access to resources\n// allowing it to perform verification and bootstrap tasks in single-threaded mode\nraftAgent.initialize();\n\n// start the RaftAgent (this starts the internal server/client, timers, etc.)\nraftAgent.start();\n\n// submit commands (if leader)\nif (raftListener.isLeader()) {\n    raftAgent.submitCommand(new MyCommand(MyCommand.CommandType.SET, \"key0\", \"val0\"));\n    raftAgent.submitCommand(new MyCommand(MyCommand.CommandType.SET, \"key1\", \"val1\"));\n    // more work...\n} else {\n    // more work...\n}\n\n// stop the agent (stops the internal server/clients, timers, etc.)\nraftAgent.stop();\n```\n\n`RaftAgent` supports more than what is outlined here (non-Jackson-annotated command serialization, *etc.*)\nFor more examples, see `KayVee.java` in `libraft-samples/kayvee` and `RaftAgentTest.java` in `libraft-agent`.\n\n## Building libraft\n\nlibraft requires java 1.6 and gradle 1.10+ to build.\n\nTo build and install into the local maven cache, run `gradle` from the repository root.\n\n```shell\ngradle build\ngradle install\n```\n\nlibraft also ships with a gradle wrapper, which allows the code to be built without\nprior installation of gradle. To use gradle wrapper run `gradlew` from the repository root.\n\n```shell\n./gradlew build\n./gradlew install\n```\n\nTo clean build artifacts run `gradle clean` or `gradlew clean` from the repository root.\n\n## Issues\n\nThe full list of issues can be seen at\n[Github Issues] (https://github.com/allengeorge/libraft/issues \"libraft issues\").\n\nThere are no known safety issues.\n\n## Reporting Issues\n\nPlease submit all code or documentation issues, comments and concerns or feature requests to\n[Github Issues] (https://github.com/allengeorge/libraft/issues \"libraft issues\").\n\nIf you have other libraft or Raft questions, please post to the\n[raft-dev] (https://groups.google.com/forum/#!forum/raft-dev \"raft-dev\")\nmailing list.\n\n## Thanks!\n\nlibraft stands on the shoulders of others. This implementation would not be possible\nwithout the very detailed (and clear!) paper published by Diego Ongaro and John Ousterhout.\nMoreover, this library was built on a huge host of open-source software - many thanks to the teams behind them!\n\nJust *some* of the open-source software libraft uses include:\n\n* [guava-libraries] (https://code.google.com/p/guava-libraries/ \"Google Core Libraries for Java 1.6+\")\n* [junit] (http://www.junit.org \"A programmer-oriented testing framework for Java\")\n* [mockito] (https://code.google.com/p/mockito/ \"Simpler \u0026 better mocking\")\n* [hamcrest] (https://code.google.com/p/hamcrest/ \"Hamcrest - Library of Matchers for Building Test Expressions\")\n* [logback] (http://logback.qos.ch/ \"The Generic, Reliable Fast \u0026 Flexible Logging Framework\")\n* [jacoco] (http://www.eclemma.org/jacoco/ \"JaCoCo Java Code Coverage Library\")\n* [netty] (http://www.netty.io \"netty\")\n* [jackson] (https://github.com/FasterXML/jackson \"FasterXML/Jackson\")\n* [hibernate validator] (http://www.hibernate.org/subprojects/validator.html \"Bean Validation Reference Implementation\")\n* [h2] (http://www.h2database.com \"H2 Database Engine\")\n* [dropwizard] (http://www.dropwizard.io \"Dropwizard - Production Ready out of the Box\")\n* [jersey] (https://jersey.java.net/ \"Jersey - RESTful Web Services In Java\")\n* [jetty] (http://www.eclipse.org/jetty/ \"Jetty - Servlet Engine and HTTP Server\")\n* [jdbi] (http://www.jdbi.org \"JDBI\")\n* [sqlite-jdbc (xerial)] (https://bitbucket.org/xerial/sqlite-jdbc \"SQLite JDBC Driver\")\n* [gradle] (http://www.gradle.org \"Gradle - Build Automation Evolved\")\n* [coveralls-gradle-plugin] (https://github.com/kt3k/coveralls-gradle-plugin \"Coveralls Gradle Plugin\")\n\nIt's this - and much, much more! - that makes libraft possible.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallengeorge%2Flibraft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fallengeorge%2Flibraft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallengeorge%2Flibraft/lists"}