MXS-2555 Add SmartRouter documentation

This commit is contained in:
Niclas Antti 2019-06-20 13:32:22 +03:00
parent f4e04f5c42
commit 3cb05813a0
3 changed files with 231 additions and 1 deletions

View File

@ -66,11 +66,12 @@ of their use.
- [Avrorouter](Routers/Avrorouter.md)
- [Binlogrouter](Routers/Binlogrouter.md)
- [Cat](Routers/Cat.md)
- [HintRouter](Routers/HintRouter.md)
- [Read Connection Router](Routers/ReadConnRoute.md)
- [Read Write Split](Routers/ReadWriteSplit.md)
- [Schemarouter](Routers/SchemaRouter.md)
- [Cat](Routers/Cat.md)
- [SmartRouter](Routers/SmartRouter.md)
The legacy diagnostic routing module MaxAdmin has been deprecated: avoid using
it.

View File

@ -0,0 +1,229 @@
# SmartRouter
[TOC]
## Overview
SmartRouter is the query router of the SmartQuery framework. Based on the type
of the query, each query is routed to the server or cluster that can best
handle it.
For workloads where both transactional and analytical queries are needed,
SmartRouter unites the Transactional (OLTP) and Analytical (OLAP) workloads into
a single entry point in MaxScale. This allows a MaxScale client to freely mix
transactional and analytical queries using the same connection. This is known
as Hybrid Transactional and Analytical Processing, HTAP.
## Configuration
SmartRouter is configured as a service that either routes to other MaxScale
routers or plain servers. Although one can configure SmartRouter to use a plain
server directly, we refer to the configured "servers" as clusters.
For details about the standard service parameters, refer to the
[Configuration Guide](../Getting-Started/Configuration-Guide.md).
### `master`
One of the clusters must be designated as the **`master`**. All writes go to the
master cluster, which for all practical purposes should be a master-slave
ReadWriteSplit. This document does not go into details about setting up
master-slave clusters, but suffice to say, that when setting up the ColumnStore
servers they should be configured to be slaves of a MariaDB server running an
InnoDB engine. The ReadWriteSplit [documentation](ReadWriteSplit.md) has more on
master-slave setup.
### Service as a Server
Currently the configuration for a router (service) can have a number of servers,
but not other routers (services). Suppose you have a cluster of servers that are
managed by ReadWriteSplit. In order for that cluster to be routed-to by
SmartRouter, the service must be exposed as a server. A server section in the
configuration file that exposes a service instead of defining an actual server,
is known as *Service as a Server*.
#### Example
![SR-config-layout](images/sr-config.png)
Suppose we have a service like
```
[RWS-Row]
type=service
router=readwritesplit
```
for which we have defined the listener
```
[RWS-Row-Listener]
type=listener
service=RWS-Row
socket=/tmp/rws-row.sock
```
That is, that service can be accessed using the socket `/tmp/rws-row.sock`.
A server section that would expose that service as a server, looks like this:
```
[RWS-Row-as-a-server]
type=server
socket=/tmp/rws-row.sock
```
Assuming we have defined `RWS-Column`, `RWS-Column-Listener` and
`RWS-Column-as-a-server` similarly, we can define the SmartQuery
service as follows:
```
[SmartQuery]
type = service
router = smartrouter
servers = RWS-Row-as-a-server, RWS-Column-as-a-server
master = RWS-Row-as-a-server
user = <user>
password = <password>
[SmartQuery-Listener]
type = listener
service = SmartQuery
protocol = mariadbclient
port = <port>
```
Note that the SmartQuery listener listens on a port, while the Service as a Server
listeners listen on a Unix domain socket. The reason is that there is a significant
performance benefit when SmartRouter accesses the services over a Unix domain socket
compared to accessing them over a TCP/IP socket.
Note that RWS-Row-as-a-server is designated as the master.
The RWS-Row-as-a-server looks like this:
```
[RWS-Row-Listener]
type = listener
service = RWS-Row
protocol = mariadbclient
socket = /tmp/rws-row.sock
[RWS-Row-as-a-server]
type = server
socket = /tmp/rws-row.sock
protocol = MariaDBBackend
```
A complete configuration example can be found at the end of this document.
## Cluster selection - how queries are routed
SmartRouter keeps track of the performance, or the execution time, of queries to
the clusters. Measurements are stored with the canonical of a query as the key.
The canonical of a query is the sql with all user-defined constants replaced with
question marks. When SmartRouter sees a read-query whose canonical has not been
seen before, it will send the query to all clusters. The first response from a
cluster will designate that cluster as the best one for that canonical. Also,
when the first response is received, the other queries are cancelled. The
response is sent to the client once all clusters have responded to the query
or the cancel.
There is obviously overhead when a new canonical is seen. This means that
queries after a MaxScale start will be slightly slower than normal. The
execution time of a query depends on the database engine, and on the contents
of the tables being queried. As a result, MaxScale will periodically re-measure
queries.
The performance behavior of queries under dynamic conditions, and their effect
on different storage engines is being studied at MariaDB. As we learn more, we
will be able to better categorize queries and move that knowledge into
SmartRouter.
## Limitations
* `LOAD DATA LOCAL INFILE` is not supported.
* The performance data is not persisted. The measurements have to be performed
anew after each startup.
## Complete configuration example
```
[maxscale]
[row_server_1]
type = server
address = <ip>
port = <port>
protocol = MariaDBBackend
[row_server_2]
type = server
address = <ip>
port = <port>
protocol = MariaDBBackend
[Row-Monitor]
type = monitor
module = mariadbmon
servers = row_server_1, row_server_2
user = <user>
password = <password>
monitor_interval = 2000ms
[column_server_1]
type = server
address = <ip>
port = <port>
protocol = MariaDBBackend
[Column-Monitor]
type = monitor
module = csmon
servers = column_server_1
user = <user>
password = <password>
monitor_interval = 2000ms
# Row Read write split
[RWS-Row]
type = service
router = readwritesplit
servers = row_server_1, row_server_2
user = <user>
password = <password>
[RWS-Row-Listener]
type = listener
service = RWS-Row
protocol = mariadbclient
socket = /tmp/rws-row.sock
# Columnstore Read write split
[RWS-Column]
type = service
router = readwritesplit
servers = column_server_1
user = <user>
password = <password>
[RWS-Column-Listener]
type = listener
service = RWS-Column
protocol = mariadbclient
socket = /tmp/rws-col.sock
[RWS-Row-as-a-server]
type = server
socket = /tmp/rws-row.sock
protocol = MariaDBBackend
[RWS-Column-as-a-server]
type = server
socket = /tmp/rws-col.sock
protocol = MariaDBBackend
# Smart Query router
[SmartQuery]
type = service
router = smartrouter
servers = RWS-Row-as-a-server, RWS-Column-as-a-server
master = RWS-Row-as-a-server
user = <user>
password = <password>
[SmartQuery-Listener]
type = listener
service = SmartQuery
protocol = mariadbclient
port = <port>
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB