Skip to content

Commit b142a61

Browse files
PMM-12153: Async replication for Percona Server (#129) (#130)
* PMM-12153: Async replication for Percona Server (#129) * PMM-12153: Split group replication * PMM-12153: Split group replication * PMM-12153: Split group replication * PMM-12153: Correct pmm server port * PMM-12153: Refactor * PMM-7: download percona release and print client version * PMM-7: download percona release and print client version * PMM-7: reorder steps * PMM-7: reorder steps * PMM-7: reorder steps * PMM-7: reorder steps * Update pmm_qa/percona_server/percona-server-setup.yml Co-authored-by: Alex Demidoff <[email protected]> * Update pmm_qa/pmm-framework.py Co-authored-by: Alex Demidoff <[email protected]> --------- Co-authored-by: Alex Demidoff <[email protected]>
1 parent e32fa0f commit b142a61

8 files changed

+404
-158
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Create replication user and grant necessary privileges
2+
SET SQL_LOG_BIN=0;
3+
CREATE USER '{{ replication_user }}'@'%' IDENTIFIED WITH 'caching_sha2_password' BY '{{ replication_password }}' REQUIRE NONE;
4+
GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'%';
5+
GRANT CONNECTION_ADMIN ON *.* TO '{{ replication_user }}'@'%';
6+
GRANT BACKUP_ADMIN ON *.* TO '{{ replication_user }}'@'%';
7+
FLUSH PRIVILEGES;
8+
SET SQL_LOG_BIN=1;
9+
10+
{% if item == 1 %}
11+
-- Primary server: enable binary logging for replication
12+
FLUSH BINARY LOGS;
13+
{% endif %}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[mysqld]
2+
# General server configuration
3+
server_id={{ item }}
4+
bind-address=0.0.0.0
5+
port={{ mysql_listen_port }}
6+
7+
# Authentication settings for caching_sha2_password
8+
caching_sha2_password_auto_generate_rsa_keys=ON
9+
# The following two parameters tell MySQL where to store the RSA key pair
10+
caching_sha2_password_private_key_path=private_key.pem
11+
caching_sha2_password_public_key_path=public_key.pem
12+
13+
# Replication settings
14+
gtid_mode=ON
15+
enforce_gtid_consistency=ON
16+
log_bin=binlog
17+
log_replica_updates=ON
18+
sync_binlog=1
19+
binlog_checksum=NONE
20+
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
21+
# MacOS-specific, where table names are case-sensitive
22+
lower_case_table_names=2
23+
24+
# MySQL 8.4 compatibility settings
25+
report_host=ps_pmm_{{ ps_version }}_{{ item }}
26+
27+
# Replica configuration - applies to all nodes except primary (they'll be able to become replicas)
28+
{% if item != 1 %}
29+
# Replica specific settings
30+
replica_parallel_workers=4
31+
replica_parallel_type=LOGICAL_CLOCK
32+
replica_preserve_commit_order=1
33+
{% endif %}
34+
35+
# Crash-safe replication settings
36+
relay-log=ps_pmm_{{ ps_version }}_{{ item }}-relay-bin
37+
relay_log_recovery=ON
38+
relay_log_purge=ON
39+
40+
# Performance and connection settings
41+
max_connections=1000
42+
innodb_buffer_pool_size=256M

pmm_qa/percona_server/percona-server-setup.yml

Lines changed: 56 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,19 @@
2222
admin_password: "{{ lookup('vars', 'extra_admin_password', default=lookup('env','ADMIN_PASSWORD') | default('admin', true) ) }}"
2323
query_source: "{{ lookup('env', 'QUERY_SOURCE') | default('perfschema', true) }}"
2424
setup_type: "{{ lookup('env', 'SETUP_TYPE') }}"
25+
random_service_name_value: ""
2526

2627
tasks:
28+
- name: Mofidy the node count for group replication
29+
set_fact:
30+
nodes_count: 3
31+
when: nodes_count | int < 3 and setup_type == "gr"
32+
33+
- name: Chance to correct nodes count for async replication
34+
set_fact:
35+
nodes_count: 2
36+
when: nodes_count | int < 2 and setup_type == "replication"
37+
2738
- name: Create Docker network
2839
community.docker.docker_network:
2940
name: "{{ network_name }}"
@@ -40,20 +51,6 @@
4051
mode: '0755'
4152
loop: "{{ range(1, nodes_count | int + 1) | list }}"
4253

43-
- name: Generate my.cnf for each node
44-
template:
45-
src: my.cnf.j2
46-
dest: "{{ data_dir }}/node{{ item }}/my.cnf"
47-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
48-
when: setup_type == "gr"
49-
50-
- name: Create initialization script for each node
51-
template:
52-
src: init.sql.j2
53-
dest: "{{ data_dir }}/node{{ item }}/init.sql"
54-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
55-
when: setup_type == "gr"
56-
5754
- name: Remove old percona server containers
5855
community.docker.docker_container:
5956
name: "ps_pmm_{{ ps_version }}_{{ item }}"
@@ -67,64 +64,17 @@
6764
shell: "sudo chown -R 1001:1001 {{ data_dir }}/node{{ item }}/data"
6865
loop: "{{ range(1, nodes_count | int + 1) | list }}"
6966

70-
- name: Start Percona Server containers with group replication
71-
community.docker.docker_container:
72-
name: "ps_pmm_{{ ps_version }}_{{ item }}"
73-
image: "percona/percona-server:{{ ps_version }}"
74-
restart_policy: always
75-
state: started
76-
networks:
77-
- name: "{{ network_name }}"
78-
env:
79-
MYSQL_ROOT_PASSWORD: "{{ root_password }}"
80-
ports:
81-
- "{{ mysql_port + item - 1 }}:{{ mysql_listen_port }}"
82-
- "{{ group_seeds_port + item - 1 }}:{{ group_seeds_port }}"
83-
volumes:
84-
- "{{ data_dir }}/node{{ item }}/data:/var/lib/mysql"
85-
- "{{ data_dir }}/node{{ item }}/my.cnf:/etc/mysql/my.cnf"
86-
- "{{ data_dir }}/node{{ item }}/init.sql:/docker-entrypoint-initdb.d/init.sql"
87-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
67+
- name: Setup Percona Server group replication
68+
include_tasks: ./tasks/percona-server-group-replication-setup.yml
8869
when: setup_type == "gr"
8970

90-
- name: Start Percona Server containers
91-
community.docker.docker_container:
92-
name: "ps_pmm_{{ ps_version }}_{{ item }}"
93-
image: "percona/percona-server:{{ ps_version }}"
94-
restart_policy: always
95-
state: started
96-
networks:
97-
- name: "{{ network_name }}"
98-
env:
99-
MYSQL_ROOT_PASSWORD: "{{ root_password }}"
100-
ports:
101-
- "{{ mysql_port + item - 1 }}:{{ mysql_listen_port }}"
102-
- "{{ group_seeds_port + item - 1 }}:{{ group_seeds_port }}"
103-
volumes:
104-
- "{{ data_dir }}/node{{ item }}/data:/var/lib/mysql"
105-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
106-
when: setup_type != "gr"
71+
- name: Setup Percona Server with async replication
72+
include_tasks: ./tasks/percona-server-async-replication-setup.yml
73+
when: setup_type == "replication"
10774

108-
- name: Wait for MySQL to be available
109-
wait_for:
110-
host: localhost
111-
port: "{{ mysql_port + item - 1 }}"
112-
delay: 10
113-
timeout: 300
114-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
115-
116-
- name: Reset configuration for all nodes
117-
community.docker.docker_container_exec:
118-
container: "ps_pmm_{{ ps_version }}_{{ item }}"
119-
command: >
120-
mysql -uroot -p{{ root_password }} -e "
121-
RESET BINARY LOGS AND GTIDS;
122-
RESET REPLICA ALL;
123-
SET GLOBAL gtid_purged='';
124-
"
125-
loop: "{{ range(1, nodes_count | int + 1) | list }}"
126-
ignore_errors: yes
127-
when: setup_type == "gr"
75+
- name: Setup Percona Server
76+
include_tasks: ./tasks/percona-server-setup.yml
77+
when: setup_type != "gr" and setup_type != "replication"
12878

12979
- name: Create slowlog configuration for mysql nodes
13080
community.docker.docker_container_exec:
@@ -139,110 +89,59 @@
13989
loop: "{{ range(1, nodes_count | int + 1) | list }}"
14090
when: query_source == "slowlog"
14191

142-
- name: Bootstrap first node in the cluster
92+
- name: Install and add pmm client.
93+
include_tasks: ../tasks/install_pmm_client_centos.yml
94+
vars:
95+
container_name: "ps_pmm_{{ ps_version }}_{{ item }}"
96+
loop: "{{ range(1, nodes_count | int + 1) | list }}"
97+
98+
- name: Get already connected services to pmm server
14399
community.docker.docker_container_exec:
144100
container: "ps_pmm_{{ ps_version }}_1"
145101
command: >
146-
mysql -uroot -p{{ root_password }} -e "
147-
SET GLOBAL group_replication_bootstrap_group=ON;
148-
START GROUP_REPLICATION;
149-
SET GLOBAL group_replication_bootstrap_group=OFF;"
150-
when: setup_type == "gr"
151-
retries: 5
152-
delay: 10
153-
154-
- name: Wait 5 seconds for bootstrap to complete
155-
pause:
156-
seconds: 5
157-
when: setup_type == "gr"
102+
sh -c 'curl --location --insecure -u"admin:{{ admin_password }}" -s --request GET "http://{{ pmm_server_ip }}:{{ '80' if pmm_server_ip is ansible.utils.ipv4 else '8080' }}/v1/management/services" | jq -r ".services[].service_name"'
103+
register: pmm_server_services
158104

159-
- name: Start group replication on other nodes
160-
community.docker.docker_container_exec:
161-
container: "ps_pmm_{{ ps_version }}_{{ item }}"
162-
command: mysql -uroot -p{{ root_password }} -e "START GROUP_REPLICATION;"
163-
loop: "{{ range(2, nodes_count | int + 1) | list }}"
164-
ignore_errors: yes
165-
when: setup_type == "gr"
105+
- name: Display already connected services to pmm server
106+
debug:
107+
msg: "{{ pmm_server_services.stdout | split('\n') }}"
166108

167-
- name: Wait 10 seconds for the other nodes to join
168-
pause:
169-
seconds: 10
170-
when: setup_type == "gr"
109+
- name: Find out if service is already connected to pmm server
110+
block:
111+
- name: Loop through percona servers
112+
set_fact:
113+
random_service_name_value: "_{{ 9999 | random + 1 }}"
114+
loop: "{{ range(1, nodes_count | int + 1) | list }}"
115+
when: "('ps_pmm_' ~ ps_version ~ '_' ~ item) in pmm_server_services.stdout"
171116

172-
- name: Create and seed a test database on primary
117+
- name: Add service to pmm server
173118
community.docker.docker_container_exec:
174-
container: "ps_pmm_{{ ps_version }}_1"
175-
command: >
176-
mysql -uroot -p{{ root_password}} -e "
177-
CREATE DATABASE testdb;
178-
USE testdb;
179-
CREATE TABLE testdb (id INT PRIMARY KEY, data VARCHAR(100));
180-
INSERT INTO testdb VALUES (1, 'Initial data from node mysql1');"
119+
container: "ps_pmm_{{ ps_version }}_{{ item }}"
120+
command: pmm-admin add mysql --query-source={{ query_source }} --username=root --password={{ root_password }} --environment=ps-gr-dev --cluster=ps-gr-dev-cluster --replication-set=ps-gr-replication ps_pmm_{{ ps_version }}_{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:3306
121+
loop: "{{ range(1, nodes_count | int + 1) | list }}"
181122
when: setup_type == "gr"
182123

183-
- name: Check replication status on first node
124+
- name: Add service to pmm server
184125
community.docker.docker_container_exec:
185-
container: "ps_pmm_{{ ps_version }}_1"
186-
command: mysql -uroot -p{{ root_password }} -e "SELECT * FROM performance_schema.replication_group_members;"
187-
register: replication_status
188-
when: setup_type == "gr"
189-
190-
- name: Display replication status
191-
debug:
192-
var: replication_status.stdout
193-
when: setup_type == "gr"
126+
container: "ps_pmm_{{ ps_version }}_{{ item }}"
127+
command: pmm-admin add mysql --query-source={{ query_source }} --username=root --password={{ root_password }} --environment=ps-replication-dev --cluster=ps-replication-dev-cluster --replication-set=ps-async-replication ps_pmm_{{ ps_version }}_{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:3306
128+
loop: "{{ range(1, nodes_count | int + 1) | list }}"
129+
when: setup_type == "replication"
194130

195-
- name: Check replication group members count
131+
- name: Add service to pmm server
196132
community.docker.docker_container_exec:
197-
container: "ps_pmm_{{ ps_version }}_1"
198-
command: mysql -uroot -p{{ root_password }} -e "SELECT COUNT(*) AS count FROM performance_schema.replication_group_members;"
199-
register: member_count
200-
when: setup_type == "gr"
201-
202-
- name: Display member count
203-
debug:
204-
var: member_count.stdout
205-
when: setup_type == "gr"
206-
207-
- name: Set verification instructions
208-
set_fact:
209-
verification_msg: |
210-
MySQL Cluster setup complete!
211-
212-
To verify replication is working:
213-
1. Connect to the first node:
214-
docker exec -it ps_pmm_{{ ps_version }}_1 mysql -uroot -p{{ root_password }}
215-
216-
2. Insert data in the test database:
217-
USE testdb;
218-
INSERT INTO testdb VALUES (100, 'Test replication');
219-
220-
3. Connect to other nodes and verify data is replicated:
221-
docker exec -it ps_pmm_{{ ps_version }}_2 mysql -uroot -p{{ root_password }}
222-
USE testdb;
223-
SELECT * FROM testdb;
224-
when: setup_type == "gr"
225-
226-
- name: Display verification instructions
227-
debug:
228-
msg: "{{ verification_msg | split('\n') }}"
229-
when: setup_type == "gr"
230-
231-
- name: Install pmm client and connect to pmm server
232-
include_tasks: ../tasks/add_mysql_to_pmm_server.yml
233-
vars:
234-
container_name: "ps_pmm_{{ ps_version }}_{{ item }}"
133+
container: "ps_pmm_{{ ps_version }}_{{ item }}"
134+
command: pmm-admin add mysql --query-source={{ query_source }} --username=root --password={{ root_password }} --environment=ps-dev ps_pmm_{{ ps_version }}_{{ item }}{{ random_service_name_value }} --debug 127.0.0.1:3306
235135
loop: "{{ range(1, nodes_count | int + 1) | list }}"
236-
237-
136+
when: setup_type != "gr" and setup_type != "replication"
238137

239138
- name: Install sysbench inside of all percona server nodes
240139
community.docker.docker_container_exec:
241140
container: "ps_pmm_{{ ps_version }}_{{ item }}"
242141
user: "root"
243142
command: >
244143
/bin/sh -c "
245-
wget -O epel-release.rpm -nv https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm &&
144+
wget -O epel-release.rpm --progress=dot:giga https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm &&
246145
rpm -i epel-release.rpm &&
247146
microdnf install -y sysbench
248147
"
@@ -271,7 +170,7 @@
271170
FLUSH PRIVILEGES;
272171
"
273172
loop: "{{ range(1, nodes_count | int + 1) | list }}"
274-
when: setup_type != "gr"
173+
when: setup_type != "gr" and setup_type != "replication"
275174

276175
- name: Prepare sysbench inside of all percona server nodes
277176
community.docker.docker_container_exec:
@@ -285,7 +184,7 @@
285184
GRANT ALL PRIVILEGES ON *.* TO 'sbtest'@'127.0.0.1';
286185
FLUSH PRIVILEGES;
287186
"
288-
when: setup_type == "gr"
187+
when: setup_type == "gr" or setup_type == "replication"
289188

290189
- name: Prepare data for sysbench inside of all percona server nodes
291190
community.docker.docker_container_exec:
@@ -300,7 +199,7 @@
300199
--tables=10
301200
--table-size=100000
302201
prepare
303-
when: setup_type != "gr"
202+
when: setup_type != "gr" and setup_type != "replication"
304203
loop: "{{ range(1, nodes_count | int + 1) | list }}"
305204

306205
- name: Prepare data for sysbench inside of first percona server nodes
@@ -316,7 +215,7 @@
316215
--tables=10
317216
--table-size=100000
318217
prepare
319-
when: setup_type == "gr"
218+
when: setup_type == "gr" or setup_type == "replication"
320219

321220
- name: Run load for sysbench inside of all percona server nodes
322221
community.docker.docker_container_exec:

0 commit comments

Comments
 (0)