使用sstableloader工具

一、准备数据

docker-compose.yaml

配置文件先无数据卷启动从容器复制到宿主机

version: '3'
services:
  cassandra:
    image: cassandra:latest
    container_name: cassandra
    restart: always
    privileged: true
    ports:
      - '9042:9042'
    volumes:
      - "/home/qiang/data/cassandra:/var/lib/cassandra"
      - "/home/qiang/data/cassandra/conf/cassandra.yaml:/etc/cassandra/cassandra.yaml"
      - "/home/qiang/data/cassandra/conf/jvm-server.options:/etc/cassandra/jvm-server.options"
# 进入容器
docker exec -it cassandra bash
# 登录数据库
cqlsh -u cassandra -p cassandra
# 创建键空间
CREATE KEYSPACE log_dev WITH REPLICATION = { 'class': 'SimpleStrategy',
'replication_factor': 1 };
# 键空间
use log_dev;
# 创建表
CREATE TABLE user1(
    id int PRIMARY KEY,
    name text
);
CREATE TABLE user2(
    id int PRIMARY KEY,
    name text
);
CREATE TABLE user3(
    id int PRIMARY KEY,
    name text
);
# 添加数据
insert into log_dev.user1 (id, name) VALUES (1, 'qiang1');
insert into log_dev.user1 (id, name) VALUES (2, 'qiang2');
insert into log_dev.user1 (id, name) VALUES (3, 'qiang3');

insert into log_dev.user2 (id, name) VALUES (1, 'qiang1');
insert into log_dev.user2 (id, name) VALUES (2, 'qiang2');
insert into log_dev.user2 (id, name) VALUES (3, 'qiang3');

insert into log_dev.user3 (id, name) VALUES (1, 'qiang1');
insert into log_dev.user3 (id, name) VALUES (2, 'qiang2');
insert into log_dev.user3 (id, name) VALUES (3, 'qiang3');
# 登出数据库
exit
# 创建备份的目录
mkdir -p /var/lib/cassandra/backup/log_dev

二、导出键空间的所有表结构

以下命令在容器中执行

# 导出键空间的所有表结构
cqlsh -k log_dev -u cassandra -p cassandra 127.0.0.1 9042 -e "describe keyspace log_dev" > /var/lib/cassandra/backup/log_dev/log_dev.cql

三、导出键空间的所有表数据

以下命令在容器中执行

# 创建备份的快照
nodetool snapshot -t 20211212 log_dev
# 退出容器
exit
# 查看快照
nodetool listsnapshots
# 删除快照
nodetool clearsnapshot -t 20211212

以下命令在容器外执行

# 编写脚本
vim /home/qiang/data/cassandra/backup/log_dev/backup.sh
# !/bin/bash

# 作者:吴多强
# 时间:2021-12-12
# 描述:复制cassandra键空间

# 要备份的版20211212
backupVersion=20211212
# 要备份的键空间目录
backupPath="/home/qiang/data/cassandra/data/log_dev"
# 备份到服务器的目录
localPath="/home/qiang/data/cassandra/backup/log_dev/log_dev"

# 判断备份到服务器的目录是否存在
if [ ! -x "$localPath" ];
then
    echo "备份到服务器的目录不存在,创建目录:"$localPath
    mkdir -p "$localPath"
fi

echo "=========================开始备份========================="
# 遍历键空间的所有表
for dir in `ls $backupPath`; do (
    currentTableName=${dir%%-*}
    echo "当前表名为:"$currentTableName
    tableSavePath=$localPath/$dir
    echo "表数据存放的目录为:"$tableSavePath
    if [ ! -x "$tableSavePath" ];
    then
		echo '表数据存放的目录为不存在,创建目录:'$tableSavePath
        mkdir -p $tableSavePath
    fi
    if [ ! -x "$backupPath/$dir/snapshots/$backupVersion" ];
    then
        echo '版本'$backupVersion'不存在,跳过复制'
    else
        cp -r $backupPath/$dir/snapshots/$backupVersion/* $tableSavePath
    fi
);
done
echo "=========================备份完成========================="
# 授权脚本
chmod +x /home/qiang/data/cassandra/backup/log_dev/backup.sh
# 执行命令-容器外
sh /home/qiang/data/cassandra/backup/log_dev/backup.sh

四、数据恢复

经过以上操作已经拿到键空间的表结构以及表数据,接下来在新的数据库上恢复数据.

# 表结构-文件
/home/qiang/data/cassandra/backup/log_dev/log_dev.cql
# 表数据-目录
/home/qiang/data/cassandra/backup/log_devlog_dev/
# 备份脚本
/home/qiang/data/cassandra/backup/log_dev/backup.sh

image-20211212104304262

五、导入键空间的所有表结构

以下命令在容器中执行

# 进入容器
docker exec -it cassandra bash
# 登录数据库
cqlsh -u cassandra -p cassandra
# 删除键空间
DROP KEYSPACE log_dev;
# 登出数据库
exit;
# 删除缓存
rm -rf /var/lib/cassandra/data/log_dev
# 导入键空间的所有表结构
cqlsh -u cassandra -p cassandra 127.0.0.1 9042 -f /var/lib/cassandra/backup/log_dev/log_dev.cql
# 退出容器
exit

六、导入键空间的所有表数据

以下命令在容器外执行

# 编写脚本
vim /home/qiang/data/cassandra/backup/log_dev/recovery.sh
# !/bin/bash

# 作者:吴多强
# 时间:2021-12-12
# 描述:恢复cassandra键空间

# 要恢复的版20211212
recoveryVersion=20211212
# 要恢复的键空间名称
keyspaceName=log_dev
# 恢复数据存放的目录,这里需要写容器内的目录,宿主机的目录/home/qiang/data/cassandra/backup/log_dev/log_dev
recoveryPath="/var/lib/cassandra/backup/log_dev/log_dev"
# cassandra的IP地址,cassandra.yaml的listen_address: x.x.x.x
ipAddress=172.21.0.2
# 账号
username=cassandra
# 密码
password=cassandra

echo "=========================开始恢复========================="
# 获取所有表名
for dir in `ls $recoveryPath`; do (
    if [ ! -x "$recoveryPath/$dir" ];
    then
        echo '版本'$recoveryVersion'的'$dir'不存在'
    else
        currentTableName=${dir%%-*}
        echo '\033[5;31m恢复'$recoveryVersion'版本'$dir'数据\033[0m'
        sstableloader -d $ipAddress -u $username -pw $password -t 100 $recoveryPath/$dir
    fi 
);
done
echo "=========================恢复完成========================="
# 授权脚本
chmod +x /home/qiang/data/cassandra/backup/log_dev/recovery.sh
# 授权目录
docker exec -it cassandra /bin/bash -c 'chown -R cassandra.cassandra /var/lib/cassandra/backup/log_dev/log_dev/*'
# 执行命令-容器外
docker exec -it cassandra /bin/bash -c 'sh /var/lib/cassandra/backup/log_dev/recovery.sh'