Getting Started
Installing GoshawkDB server
Linux
Downloads are available for
binaries in deb
, rpm
and tarball
formats.
If you wish to compile from source then you'll need to install Go which is packaged in all major Linux distributions. You will also need to install LMDB:
- Under Debian-based Linux systems, the packages to
install are
liblmdb0
andliblmdb-dev
. - On RPM-based Linux systems, the packages are often
called
lmdb-libs
andlmdb-devel
.
With these compile-time dependencies installed, the server is go gettable so it should just be a matter of:
> go get goshawkdb.io/server/cmd/goshawkdb
OS X
There is a Homebrew Tap available for GoshawkDB. You should be able to fetch and build with:
> brew install goshawkdb/goshawkdb/goshawkdb-server
Windows
Go and LMDB also work under Windows. Currently I do not have access to Windows machines so cannot prepare builds of GoshawkDB for this platform, but I believe it should be possible to compile from source: you'll need to install Go and LMDB, but once that's done, the server is go gettable so it should just be a matter of:
> go get goshawkdb.io/server/cmd/goshawkdb
Docker
There is a Docker image available for GoshawkDB.
Running
Once you have GoshawkDB installed, you should be able to start it:
> goshawkdb
GoshawkDB 2016/01/10 09:52:26.467248 [goshawkdb]
GoshawkDB 2016/01/10 09:52:26.467334 No certificate supplied (missing -cert parameter). Use -gen-cluster-cert to create cluster certificate
>
Success! GoshawkDB is able to start up, but we've not supplied enough parameters, so it shut down again.
GoshawkDB is designed for use on SSDs or faster storage devices. It will perform poorly when storing data on traditional rotating hard drives.
Command line parameters
Adding a -h
will show us some help:
> goshawkdb -h
GoshawkDB 2016/01/10 09:42:00.286354 [goshawkdb -h]
Usage of goshawkdb:
-cert Path
Path to cluster certificate and key file
-config Path
Path to configuration file
-dir Path
Path to data directory
-gen-client-cert
Generate client certificate key pair
-gen-cluster-cert
Generate new cluster certificate key pair
-port int
Port to listen on (default 7894)
-version
Display version and exit
>
Certificates
GoshawkDB uses X509 certificates for authentication of both servers and clients. First we need to generate the cluster certificate and key pair. The same cluster certificate and key pair must be supplied to every node in the cluster.
> goshawkdb -gen-cluster-cert > ./clusterCert.pem
GoshawkDB 2016/01/10 09:46:33.177542 [goshawkdb -gen-cluster-cert]
>
The file clusterCert.pem
now contains the
cluster certificate and key pair in PEM format. Clients
are also authenticated using X509 certificates. To
generate a suitable client certificate and key pair:
> goshawkdb -cert ./clusterCert.pem -gen-client-cert > ./user1.pem
GoshawkDB 2016/01/10 09:50:11.982124 [goshawkdb -cert ./clusterCert.pem -gen-client-cert]
GoshawkDB 2016/01/10 09:50:11.986663 Fingerprint: 34b1c780a4756a5cbc4c69a111188f641eed20aa825cb0b2fecd31cf28d643cb
>
The file user1.pem
now contains a client
certificate and key pair in PEM format. The fingerprint of
the certificate needs to be added to our configuration
file to allow this certificate to be accepted.
Configuration
The configuration file
is covered in
detail in its own guide so for now we'll just create
the simplest possible configuration file. Create a file
called config.json
and add the following to
it:
{
"ClusterId": "MyFirstGoshawkDBCluster",
"Version": 1,
"Hosts": ["localhost"],
"F": 0,
"MaxRMCount": 5,
"ClientCertificateFingerprints": {
"34b1c780a4756a5cbc4c69a111188f641eed20aa825cb0b2fecd31cf28d643cb": {
"myRoot": {
"Read": true,
"Write": true
}
}
}
}
This specifies a cluster of just one node, which will have
no ability to withstand any failure. The fingerprint of
the client certificate we created above appears in
the ClientCertificateFingerprints
section.
We specify there is one root object
called myRoot
and we specify that our one
client account will be able to both read and write that
root object.
Launch!
Finally, we'll want to tell GoshawkDB where it can write
data to disk, and should we stop and restart GoshawkDB,
where it will be able to recover and load data back in
from disk. This is the -dir
parameter.
> goshawkdb -config ./config.json -cert ./clusterCert.pem -dir /tmp/goshawkdb
GoshawkDB 2016/05/01 10:46:40.050297 [goshawkdb -config ./config.json -cert ./clusterCert.pem -dir /tmp/goshawkdb]
GoshawkDB 2016/05/01 10:46:40.064531 Loaded 0 acceptors from disk
GoshawkDB 2016/05/01 10:46:40.064716 Loaded 0 proposers from disk
GoshawkDB 2016/05/01 10:46:40.065089 Topology: Ensuring local topology.
GoshawkDB 2016/05/01 10:46:40.070231 Topology: task completed.
GoshawkDB 2016/05/01 10:46:40.070314 Topology: Attempting to join cluster with configuration: Next Configuration:
AllHosts: [];
NewRMIds: [];
SurvivingRMIds: [];
LostRMIds: [];
InstalledOnNew: false;
BarrierReached1: [];
BarrierReached2: [];
Pending:;
Configuration: Configuration{ClusterId: MyFirstGoshawkDBCluster, Version: 1, Hosts: [localhost:7894], F: 0, MaxRMCount: 5, NoSync: false, RMs: [], Removed: map[]}
GoshawkDB 2016/05/01 10:46:40.108593 Topology: Requesting help from existing cluster members for topology change.
GoshawkDB 2016/05/01 10:46:40.108609 Topology: task completed.
GoshawkDB 2016/05/01 10:46:40.108932 >==> We are localhost:7894 (RM:e4cabf7e) <==<
And it's up, ready for work! To shut down GoshawkDB,
either Ctl-c
it, or send it
either SIGTERM
or SIGINT
.
GoshawkDB refers to nodes within the cluster by
their RM
Id. RM
stands
for Resource Manager which is a traditional term
for the nodes that make up a database that you'll come
across in lots of database literature. The RM
Id is created when a GoshawkDB node is started for the
first time and is then stored so that when GoshawkDB
restarts, its RM
Id doesn't change. It is
just a random number: the RM
Ids you see will
be different to those here.
When a GoshawkDB node starts for the first time, it also
stores a copy of the configuration. This is necessary so
that it can detect when the configuration changes and can
calculate what's changed. As we've successfully started
GoshawkDB, if we shut it down and restart it, we can now
leave off the -config
parameter and GoshawkDB
will use whatever configuration it took a copy of:
> goshawkdb -cert ./clusterCert.pem -dir /tmp/goshawkdb
GoshawkDB 2016/05/01 10:48:58.736960 [goshawkdb -cert ./clusterCert.pem -dir /tmp/goshawkdb]
GoshawkDB 2016/05/01 10:48:58.741711 Loaded 0 acceptors from disk
GoshawkDB 2016/05/01 10:48:58.742119 Loaded 0 proposers from disk
GoshawkDB 2016/05/01 10:48:58.742557 Topology: Ensuring local topology.
GoshawkDB 2016/05/01 10:48:58.754004 Topology: task completed.
GoshawkDB 2016/05/01 10:48:58.755198 >==> We are localhost:7894 (RM:e4cabf7e) <==<
A bigger cluster
A GoshawkDB cluster has a minimum size determined by
the F
parameter in the configuration
file. F
is the number of failures that
GoshawkDB will withstand: if no more than F
nodes are unreachable then GoshawkDB will continue working
just fine. If more than F
nodes are
unreachable then a transaction submitted to GoshawkDB may
block (not return any answer) or error until enough nodes
recover so that no more than F
nodes are
unreachable. The minimum number of nodes in a cluster
is 2*F + 1
. So if F = 1
then 2*F + 1 = 3
. So let's create a cluster
of three nodes and set F = 1
.
For the time being, we're going to have all three nodes
running on the same machine. This is not recommended: by
sharing a disk they will suffer from poorer performance,
but for the purposes of getting started, this doesn't
matter. Change the config.json
file to:
{
"ClusterId": "MySecondGoshawkDBCluster",
"Version": 1,
"Hosts": [
"localhost:10001",
"localhost:10002",
"localhost:10003"
],
"F": 1,
"MaxRMCount": 5,
"ClientCertificateFingerprints": {
"34b1c780a4756a5cbc4c69a111188f641eed20aa825cb0b2fecd31cf28d643cb": {
"myRoot": {
"Read": true,
"Write": true
}
}
}
}
The intention here is to have our three nodes on different
ports, that way they won't interfere with each other. To
specify the port to listen on, use the -port
command line parameter. We must also give each node a
different location to write to disk. All three nodes must
be provided with the same cluster certificate and key
pair, and the same configuration when they start for the
first time. They will connect to each other and verify
they've all been configured the same way.
First node:
> goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb1 -port 10001
GoshawkDB 2016/05/01 10:57:30.205813 [goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb1 -port 10001]
GoshawkDB 2016/05/01 10:57:30.218516 Loaded 0 acceptors from disk
GoshawkDB 2016/05/01 10:57:30.218909 Loaded 0 proposers from disk
GoshawkDB 2016/05/01 10:57:30.219124 Topology: Ensuring local topology.
GoshawkDB 2016/05/01 10:57:30.225774 Topology: task completed.
GoshawkDB 2016/05/01 10:57:30.225834 Topology: Attempting to join cluster with configuration: Next Configuration:
AllHosts: [];
NewRMIds: [];
SurvivingRMIds: [];
LostRMIds: [];
InstalledOnNew: false;
BarrierReached1: [];
BarrierReached2: [];
Pending:;
Configuration: Configuration{ClusterId: MySecondGoshawkDBCluster, Version: 1, Hosts: [localhost:10001 localhost:10002 localhost:10003], F: 1, MaxRMCount: 5, NoSync: false, RMs: [], Removed: map[]}
GoshawkDB 2016/05/01 10:59:01.205650 Connection established to localhost:10002 (RM:25e17bfc)
GoshawkDB 2016/05/01 11:01:28.147197 Connection established to localhost:10003 (RM:8dfb10db)
GoshawkDB 2016/05/01 11:01:28.197996 Topology: Config transition to version 1 already in progress.
GoshawkDB 2016/05/01 11:01:28.198823 Topology: Requesting help from existing cluster members for topology change.
GoshawkDB 2016/05/01 11:01:28.198836 Topology: task completed.
GoshawkDB 2016/05/01 11:01:28.199142 >==> We are localhost:10001 (RM:6b8f34b0) <==<
Second node:
> goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb2 -port 10002
GoshawkDB 2016/05/01 10:59:01.164249 [goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb2 -port 10002]
GoshawkDB 2016/05/01 10:59:01.176136 Loaded 0 acceptors from disk
GoshawkDB 2016/05/01 10:59:01.176326 Loaded 0 proposers from disk
GoshawkDB 2016/05/01 10:59:01.176734 Topology: Ensuring local topology.
GoshawkDB 2016/05/01 10:59:01.182387 Topology: task completed.
GoshawkDB 2016/05/01 10:59:01.182444 Topology: Attempting to join cluster with configuration: Next Configuration:
AllHosts: [];
NewRMIds: [];
SurvivingRMIds: [];
LostRMIds: [];
InstalledOnNew: false;
BarrierReached1: [];
BarrierReached2: [];
Pending:;
Configuration: Configuration{ClusterId: MySecondGoshawkDBCluster, Version: 1, Hosts: [localhost:10001 localhost:10002 localhost:10003], F: 1, MaxRMCount: 5, NoSync: false, RMs: [], Removed: map[]}
GoshawkDB 2016/05/01 10:59:01.205650 Connection established to localhost:10001 (RM:6b8f34b0)
GoshawkDB 2016/05/01 11:01:28.143714 Connection established to localhost:10003 (RM:8dfb10db)
GoshawkDB 2016/05/01 11:01:28.144094 Topology: Config transition to version 1 already in progress.
GoshawkDB 2016/05/01 11:01:28.144210 Connection terminated
GoshawkDB 2016/05/01 11:01:28.179411 Topology: Requesting help from existing cluster members for topology change.
GoshawkDB 2016/05/01 11:01:28.179429 Topology: task completed.
GoshawkDB 2016/05/01 11:01:28.179711 >==> We are localhost:10002 (RM:25e17bfc) <==<
Third node:
> goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb3 -port 10003
GoshawkDB 2016/05/01 11:01:28.081993 [goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb3 -port 10003]
GoshawkDB 2016/05/01 11:01:28.113301 Loaded 0 acceptors from disk
GoshawkDB 2016/05/01 11:01:28.113541 Loaded 0 proposers from disk
GoshawkDB 2016/05/01 11:01:28.113942 Topology: Ensuring local topology.
GoshawkDB 2016/05/01 11:01:28.119103 Topology: task completed.
GoshawkDB 2016/05/01 11:01:28.119213 Topology: Attempting to join cluster with configuration: Next Configuration:
AllHosts: [];
NewRMIds: [];
SurvivingRMIds: [];
LostRMIds: [];
InstalledOnNew: false;
BarrierReached1: [];
BarrierReached2: [];
Pending:;
Configuration: Configuration{ClusterId: MySecondGoshawkDBCluster, Version: 1, Hosts: [localhost:10001 localhost:10002 localhost:10003], F: 1, MaxRMCount: 5, NoSync: false, RMs: [], Removed: map[]}
GoshawkDB 2016/05/01 11:01:28.143750 Connection established to localhost:10002 (RM:25e17bfc)
GoshawkDB 2016/05/01 11:01:28.145167 Topology: Config transition to version 1 already in progress.
GoshawkDB 2016/05/01 11:01:28.147184 Connection established to localhost:10001 (RM:6b8f34b0)
GoshawkDB 2016/05/01 11:01:28.198190 Topology: Config transition to version 1 already in progress.
GoshawkDB 2016/05/01 11:01:28.199006 Topology: Requesting help from existing cluster members for topology change.
GoshawkDB 2016/05/01 11:01:28.199016 Topology: task completed.
GoshawkDB 2016/05/01 11:01:28.199902 >==> We are localhost:10003 (RM:8dfb10db) <==<
And that's it: the cluster is fully connected and running.
Try killing one of the nodes and restarting it. See how the cluster reforms. Whenever a node becomes unreachable, other nodes will periodically attempt to reconnect to it and recover automatically. Try generating a new cluster certificate and key pair and (re)starting one of the nodes with the "wrong" certificate: the cluster will refuse to form.
Monitoring GoshawkDB
Currently, GoshawkDB has only limited forms of monitoring
built in, but this is something that will be addressed in
an upcoming release: see the road
map. If you send it a SIGUSR1
then it
will print out a detailed set of diagnostics of each of
GoshawkDB's various subsystems. On an active busy node,
this can be a large amount of information, but on an idle
server it is not overwhelming. With the cluster we created
above still running:
> ps ax | grep [g]oshawk | grep 'port 10003'
22701 pts/10 Sl+ 0:00 goshawkdb -cert ./clusterCert.pem -config ./config.json -dir /tmp/goshawkdb3 -port 10003
> kill -USR1 22701
On the terminal running the third node, something like the following should have appeared:
GoshawkDB 2016/05/01 11:05:58.121559 System Status for RM:8dfb10db
Configuration File: ./config.json
Data Directory: /tmp/goshawkdb3
Port: 10003
Address: localhost:10003
Boot Count: 2
Current Topology: Topology{Configuration{ClusterId: MySecondGoshawkDBCluster, Version: 1, Hosts: [localhost:10001 localhost:10002 localhost:10003], F: 1, MaxRMCount: 5, NoSync: false, RMs: [RM:6b8f34b0 RM:25e17bfc RM:8dfb10db], Removed: map[]}, F+1: 2, 2F+1: 3, DBVersion: TxnId:0000000000000001-00000000-00000001-25e17bfc, Root: VarUUId:0000000000000000000000000000000125e17bfc@[0 1 2 3 4]}
ServerConnectionSubscribers: 10
TopologySubscribers: [4 4 4 3 1 0]
Active Server RMIds: [RM:8dfb10db RM:25e17bfc RM:6b8f34b0]
Active Server Connections: [localhost:10001 localhost:10002 localhost:10003]
Desired Server Connections: [localhost:10001 localhost:10002]
Connection to localhost:10001 (RM:6b8f34b0, 1)
- Current State: ConnectionRun
- IsServer? true
- IsClient? false
Connection to localhost:10002 (RM:25e17bfc, 1)
- Current State: ConnectionRun
- IsServer? true
- IsClient? false
Client Connection Count: 1
LocalConnection
SimpleTxnSubmitter: live TxnIds: []
Vars
Var Manager 0
- Active Vars: 1
- Callbacks: 0
- Beater live? false
- Roll allowed? true
VarUUId:0000000000000000000000000000000000000000
- Positions: unknown
- CurFrame:
VarUUId:0000000000000000000000000000000000000000 Frame TxnId:0000000000000001-00000000-00000001-25e17bfc (1) rVC:map[VarUUId:0000000000000000000000000000000000000000:3] (cached cap? false) w<nil>
- Read Count: 0 [0 0 0 0]
- Uncommitted Read Count: 0
- Learnt future reads: 0
- Write Count: 0 [0 0 0 0]
- Uncommitted Write Count: 0
- RW Present: false
- Mask: VC:map[] (cached cap? false)
- Current State: frameOpen
- Locked? false
- Roll scheduled/active? false/false
- DescendentOnDisk? false
- Child == nil? true
- Parent == nil? true
- Subscribers: 1
- Idle? false
- IsOnDisk? true
Var Manager 1
- Active Vars: 0
- Callbacks: 0
- Beater live? false
- Roll allowed? true
Var Manager 2
- Active Vars: 0
- Callbacks: 0
- Beater live? false
- Roll allowed? true
Var Manager 3
- Active Vars: 0
- Callbacks: 0
- Beater live? false
- Roll allowed? true
Proposers
Proposer Manager 0
Live proposers: 0
Live proposals: 0
Proposer Manager 1
Live proposers: 0
Live proposals: 0
Proposer Manager 2
Live proposers: 0
Live proposals: 0
Proposer Manager 3
Live proposers: 0
Live proposals: 0
Acceptors
Acceptor Manager 0
- Live Instances: 0
- Acceptors: 0
Acceptor Manager 1
- Live Instances: 0
- Acceptors: 0
Acceptor Manager 2
- Live Instances: 0
- Acceptors: 0
Acceptor Manager 3
- Live Instances: 0
- Acceptors: 0
Status End
Because this cluster is currently idle, various subsystems of GoshawkDB are idle and so don't display anything. Whenever a GoshawkDB server is idle, it should return to a similar state to this, with no Proposers and no Acceptors. The first section of these diagnostics show connections to other servers and to clients and shows details about the configuration of the cluster.
If you encounter a problem and get in touch and it's thought there may be a bug in the server, it's very likely you'll be asked to provide these diagnostics.
In addition to responding to SIGUSR1
,
GoshawkDB also responds to SIGQUIT
. When
GoshawkDB receives a SIGQUIT
it will print
out the current stack trace of all Go routines.
What's next?
That's everything for creating and running a GoshawkDB cluster.
- More details on configuration of the server
- An introduction to the data-model that GoshawkDB presents and how you can best approach storing your objects and their state within GoshawkDB.
- For getting started with the Go client, there's a guide and several example applications to help get you going.
- For getting started with the Java client, there's a guide.