From 017a05b1996b9fca92f2a493b65167a6461d7eb8 Mon Sep 17 00:00:00 2001 From: Endial Fang Date: Tue, 7 Jul 2020 18:17:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=95=9C=E5=83=8F=E4=B8=BA?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=8C=96=E7=89=88=E6=9C=AC=EF=BC=9B=E5=AE=8C?= =?UTF-8?q?=E5=96=84README=E6=96=87=E4=BB=B6=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E8=AF=B4=E6=98=8E=EF=BC=9B=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?docker-compose=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 5.0/Dockerfile | 129 +- 5.0/alpine/.dockerignore | 4 - 5.0/alpine/Dockerfile | 95 -- 5.0/alpine/README.md | 125 -- 5.0/alpine/redis/default/redis.conf | 1378 ----------------- 5.0/alpine/redis/default/sentinel.conf | 244 --- 5.0/alpine/redis/entrypoint.sh | 59 - 5.0/entrypoint.sh | 99 -- 5.0/prebuilds/usr/local/bin/appcommon.sh | 477 ++++++ 5.0/prebuilds/usr/local/bin/entrypoint.sh | 90 ++ 5.0/prebuilds/usr/local/license/LICENSE | 21 + .../usr/local/overrides/overrides-5.0.8.sh | 17 + 5.0/prebuilds/usr/local/scripts/libcommon.sh | 135 ++ .../usr/local/scripts/libdownload.sh | 96 ++ 5.0/prebuilds/usr/local/scripts/libfile.sh | 74 + 5.0/prebuilds/usr/local/scripts/libfs.sh | 119 ++ 5.0/prebuilds/usr/local/scripts/liblog.sh | 65 + 5.0/prebuilds/usr/local/scripts/libnet.sh | 119 ++ 5.0/prebuilds/usr/local/scripts/libos.sh | 158 ++ 5.0/prebuilds/usr/local/scripts/libservice.sh | 131 ++ .../usr/local/scripts/libvalidations.sh | 228 +++ 5.0/redis/default/redis.conf | 1378 ----------------- 5.0/redis/default/sentinel.conf | 244 --- README.md | 787 +++++++++- docker-compose-cluster.yml | 27 + docker-compose.yml | 11 + img/redis-white.png | Bin 0 -> 2794 bytes 27 files changed, 2602 insertions(+), 3708 deletions(-) delete mode 100644 5.0/alpine/.dockerignore delete mode 100644 5.0/alpine/Dockerfile delete mode 100644 5.0/alpine/README.md delete mode 100644 5.0/alpine/redis/default/redis.conf delete mode 100644 5.0/alpine/redis/default/sentinel.conf delete mode 100755 5.0/alpine/redis/entrypoint.sh delete mode 100755 5.0/entrypoint.sh create mode 100644 5.0/prebuilds/usr/local/bin/appcommon.sh create mode 100644 5.0/prebuilds/usr/local/bin/entrypoint.sh create mode 100644 5.0/prebuilds/usr/local/license/LICENSE create mode 100644 5.0/prebuilds/usr/local/overrides/overrides-5.0.8.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libcommon.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libdownload.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libfile.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libfs.sh create mode 100644 5.0/prebuilds/usr/local/scripts/liblog.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libnet.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libos.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libservice.sh create mode 100644 5.0/prebuilds/usr/local/scripts/libvalidations.sh delete mode 100644 5.0/redis/default/redis.conf delete mode 100644 5.0/redis/default/sentinel.conf create mode 100644 docker-compose-cluster.yml create mode 100644 docker-compose.yml create mode 100644 img/redis-white.png diff --git a/5.0/Dockerfile b/5.0/Dockerfile index e5242e3..a54b607 100644 --- a/5.0/Dockerfile +++ b/5.0/Dockerfile @@ -1,65 +1,120 @@ FROM colovu/ubuntu:18.04 -ENV APP_MAJOR=5.0.8 \ - APP_DOWNLOAD_SHA='f3c7eac42f433326a8d981b50dba0169fdfaf46abb23fcda2f933a7552ee4ed7' +ARG app_ver=5.0.8 +ARG LOCAL_SERVER=http://172.29.14.108/dist-files/ + +ENV APP_NAME=redis \ + APP_EXEC=redis-server \ + APP_USER=redis \ + APP_GROUP=redis \ + APP_VERSION=${app_ver} + +ENV APP_BASE_DIR=/usr/local/${APP_NAME} \ + APP_DEF_DIR=/etc/${APP_NAME} \ + APP_CONF_DIR=/srv/conf/${APP_NAME} \ + APP_DATA_DIR=/srv/data/${APP_NAME} \ + APP_DATA_LOG_DIR=/srv/datalog/${APP_NAME} \ + APP_CACHE_DIR=/var/cache/${APP_NAME} \ + APP_RUN_DIR=/var/run/${APP_NAME} \ + APP_LOG_DIR=/var/log/${APP_NAME} \ + APP_CERT_DIR=/srv/cert/${APP_NAME} \ + APP_WWW_DIR=/srv/www + +# 设置应用需要的环境变量 +ENV PATH="${APP_BASE_DIR}/bin:${PATH}" LABEL \ - "Version"="v${APP_MAJOR}" \ - "Description"="Docker image for Redis ${APP_MAJOR} based on Ubuntu 18.04." \ - "Dockerfile"="https://github.com/colovu/docker-redis" \ + "Version"="v${APP_VERSION}" \ + "Description"="Docker image for ${APP_NAME} ${APP_VERSION}." \ + "Dockerfile"="https://github.com/colovu/docker-${APP_NAME}" \ "Vendor"="Endial Fang (endial@126.com)" +COPY prebuilds / + RUN set -eux; \ -# 启用非交互模式安装软件包,规避Readline/Teletype等警告 +# 设置程序使用静默安装,而非交互模式;类似tzdata等程序需要使用静默安装 export DEBIAN_FRONTEND=noninteractive; \ \ - groupadd -r redis; \ - useradd -r -g redis -s /usr/sbin/nologin -d /usr/cache/redis redis; \ +# 设置入口脚本的可执行权限 + chmod +x /usr/local/bin/entrypoint.sh; \ \ - mkdir -p /etc/redis/default /srv/conf/redis /srv/data/redis /var/log/redis /var/run/redis; \ +# 为应用创建对应的组、用户、相关目录 + APP_DIRS="${APP_DEF_DIR:-} ${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_CACHE_DIR:-} ${APP_RUN_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_WWW_DIR:-} ${APP_DATA_LOG_DIR:-}"; \ + groupadd -r ${APP_GROUP}; \ + useradd -r -g ${APP_GROUP} -s /usr/sbin/nologin ${APP_USER}; \ + mkdir -p ${APP_DIRS}; \ + \ +# 应用软件包及依赖 + appDeps=" \ + "; \ \ fetchDeps=" \ + wget \ + ca-certificates \ + \ autoconf \ automake \ gcc \ g++ \ gcc-multilib \ make \ - ca-certificates \ - wget \ + \ "; \ - savedAptMark="$(apt-mark showmanual)"; \ + savedAptMark="$(apt-mark showmanual) ${appDeps}"; \ apt-get -y update; \ apt-get -y install --no-install-recommends $fetchDeps; \ \ - wget -O redis.tar.gz "http://download.redis.io/releases/redis-${APP_MAJOR}.tar.gz"; \ - echo "$APP_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ - mkdir -p /usr/src/redis; \ - tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ - rm redis.tar.gz; \ + # 使用下载(编译)方式安装软件 + DIST_NAME="wait-for-port-1.0.0-1-linux-amd64-debian-10"; \ + DIST_URL=" \ + ${LOCAL_SERVER} \ + https://downloads.bitnami.com/files/stacksmith/ \ + "; \ + . /usr/local/scripts/libdownload.sh && download_dist "${DIST_NAME}.tar.gz" "${DIST_URL}"; \ \ +# 二进制解压 + APP_BIN="/usr/local/bin"; \ + tar --extract --gunzip --file "${DIST_NAME}.tar.gz" --directory "${APP_BIN}" --strip-components 4 "${DIST_NAME}/files/common/bin/"; \ + rm -rf "${DIST_NAME}.tar.gz" "/usr/local/bin/.buildcomplete"; \ + \ +# 使用下载(编译)方式安装软件 + DIST_NAME="${APP_NAME}-${APP_VERSION}.tar.gz"; \ + DIST_SHA256="f3c7eac42f433326a8d981b50dba0169fdfaf46abb23fcda2f933a7552ee4ed7"; \ + DIST_URL=" \ + ${LOCAL_SERVER} \ + http://download.redis.io/releases/ \ + "; \ + . /usr/local/scripts/libdownload.sh && download_dist "${DIST_NAME}" "${DIST_URL}" --checksum "${DIST_SHA256}"; \ + \ +# 源码编译 + APP_SRC="/usr/local/src/${APP_NAME}-${APP_VERSION}"; \ + mkdir -p ${APP_SRC}; \ + tar --extract --file "${DIST_NAME}" --directory "${APP_SRC}" --strip-components 1; \ + cd ${APP_SRC}; \ # disable Redis protected mode [1] as it is unnecessary in context of Docker # (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P) # [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da - grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \ - sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \ - grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \ + grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' ${APP_SRC}/src/server.h; \ + sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' ${APP_SRC}/src/server.h; \ + grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' ${APP_SRC}/src/server.h; \ # for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" # see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 # (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) \ - make -C /usr/src/redis -j "$(nproc)" all; \ - make -C /usr/src/redis install; \ + make -j "$(nproc)" all; \ + make install; \ + cp -rf ./*.conf ${APP_DEF_DIR}/; \ + cd /; \ + rm -rf ${APP_SRC} ${DIST_NAME}; \ \ - cp -rf /usr/src/redis/*.conf /etc/redis/; \ - rm -r /usr/src/redis; \ +# 检测是否存在overrides脚本文件,如果存在,执行 + { [ ! -e "/usr/local/overrides/overrides-${APP_VERSION}.sh" ] || /bin/bash "/usr/local/overrides/overrides-${APP_VERSION}.sh"; }; \ \ - ln -sf /srv/conf/redis/redis.conf /etc/redis/redis.conf; \ - ln -sf /srv/conf/redis/sentinel.conf /etc/redis/sentinel.conf; \ - chown -Rf redis:redis /etc/redis /srv/conf/redis /srv/data/redis /var/log/redis /var/run/redis; \ - chmod 777 /etc/redis /srv/conf/redis /srv/data/redis /var/log/redis /var/run/redis; \ +# 设置临时目录的权限信息,设置为777是为了保证后续使用`--user`或`gosu`时,可以更改目录对应的用户属性信息;运行时会被更改为700或755 + chown -Rf ${APP_USER}:${APP_GROUP} ${APP_DIRS}; \ + chmod 777 ${APP_DIRS}; \ \ -# 查找新安装的应用相应的依赖软件包,并表示为'manual',防止后续自动清理时被删除 +# 查找新安装的应用及应用依赖软件包,并标识为'manual',防止后续自动清理时被删除 apt-mark auto '.*' > /dev/null; \ { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; }; \ find /usr/local -type f -executable -exec ldd '{}' ';' \ @@ -69,25 +124,25 @@ RUN set -eux; \ | cut -d: -f1 \ | sort -u \ | xargs -r apt-mark manual; \ -# 删除临时软件包,清理缓存 apt purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${fetchDeps}; \ - apt autoclean -y; \ + \ +# 删除安装的临时依赖软件包,清理缓存 + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${fetchDeps}; \ + apt-get autoclean -y; \ rm -rf /var/lib/apt/lists/*; \ \ -# 验证新安装的软件是否工作正常 +# 验证安装的软件是否可以正常运行,常规情况下放置在命令行的最后 redis-cli --version; \ redis-server --version - -COPY ./entrypoint.sh /usr/local/bin/ -COPY ./redis /etc/redis - VOLUME [ "/srv/data", "/srv/conf", "/var/log", "/var/run" ] WORKDIR /srv/data/redis -# 如果使用gosu启动,必须保证端口在1024之上 +# 默认使用gosu切换为新建用户启动,必须保证端口在1024之上 EXPOSE 6379 +# 容器初始化命令,默认存放在:/usr/local/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] +# 应用程序的服务命令,必须使用非守护进程方式运行 CMD ["redis-server", "/srv/conf/redis/redis.conf"] diff --git a/5.0/alpine/.dockerignore b/5.0/alpine/.dockerignore deleted file mode 100644 index b3e8a3d..0000000 --- a/5.0/alpine/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -.git -.gitignore -README.md -LICENSE \ No newline at end of file diff --git a/5.0/alpine/Dockerfile b/5.0/alpine/Dockerfile deleted file mode 100644 index 40e52ce..0000000 --- a/5.0/alpine/Dockerfile +++ /dev/null @@ -1,95 +0,0 @@ -FROM endial/alpine:3.11 - -LABEL \ - "Version"="v5.0.8" \ - "Description"="Docker image for Redis 5.0.8 based on Alpine 3.11." \ - "Dockerfile"="https://github.com/endial/docker-redis" \ - "Vendor"="Endial Fang (endial@126.com)" - -ENV REDIS_VERSION 5.0.8 -ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.8.tar.gz -ENV REDIS_DOWNLOAD_SHA f3c7eac42f433326a8d981b50dba0169fdfaf46abb23fcda2f933a7552ee4ed7 - -RUN set -eux; \ - addgroup -S redis; \ - adduser -S -G redis -s /sbin/nologin redis; \ - \ - apk add --no-cache \ - 'su-exec>=0.2' \ - tzdata \ - ; \ - \ - \ - apk add --no-cache --virtual .build-deps \ - coreutils \ - gcc \ - linux-headers \ - make \ - musl-dev \ - openssl-dev \ - ; \ - \ - wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \ - echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ - mkdir -p /usr/src/redis; \ - tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ - rm redis.tar.gz; \ - \ -# disable Redis protected mode [1] as it is unnecessary in context of Docker -# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P) -# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da - grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \ - sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \ - grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \ -# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" -# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 -# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) - \ - make -C /usr/src/redis -j "$(nproc)" all; \ - make -C /usr/src/redis install; \ - \ -# TODO https://github.com/antirez/redis/pull/3494 (deduplicate "redis-server" copies) - serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ - find /usr/local/bin/redis* -maxdepth 0 \ - -type f -not -name redis-server \ - -exec sh -eux -c ' \ - md5="$(md5sum "$1" | cut -d" " -f1)"; \ - test "$md5" = "$serverMd5"; \ - ' -- '{}' ';' \ - -exec ln -svfT 'redis-server' '{}' ';' \ - ; \ - \ - mkdir -p /etc/redis/default; \ - chown redis:root /etc/redis/default; \ - mkdir -p /srv/data/redis; \ - chown redis:root /srv/data/redis; \ - mkdir -p /srv/conf/redis; \ - chown redis:root /srv/conf/redis; \ - \ -# cp -rf /usr/src/redis/*.conf /etc/redis/; \ - ln -sf /srv/conf/redis/redis.conf /etc/redis/redis.conf; \ - ln -sf /srv/conf/redis/sentinel.conf /etc/redis/sentinel.conf; \ - ln -sf /etc/redis/entrypoint.sh /usr/local/bin/entrypoint.sh; \ - rm -r /usr/src/redis; \ - \ - runDeps="$( \ - scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ - | tr ',' '\n' \ - | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ - )"; \ - apk add --no-network --virtual .redis-rundeps $runDeps; \ - apk del --no-network .build-deps; \ - \ - redis-cli --version; \ - redis-server --version - -VOLUME [ "/srv/data", "/srv/conf", "/var/log", "/var/run" ] -EXPOSE 6379 - -COPY ./redis /etc/redis -WORKDIR /srv/data/redis - -ENTRYPOINT ["entrypoint.sh"] - -CMD ["redis-server", "/etc/redis/redis.conf"] diff --git a/5.0/alpine/README.md b/5.0/alpine/README.md deleted file mode 100644 index bbcfd83..0000000 --- a/5.0/alpine/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# Redis - -针对Redis的 Docker 镜像,用于提供 Redis 服务。 - - - -## 基本信息 - -* 镜像地址:endial/redis:5.0.8 - * 依赖镜像:endial/ubuntu:18.04 - -- 镜像地址:endial/redis-alpine:5.0.8 - - 依赖镜像:endial/alpine:3.11 - - - -## 数据卷 - -镜像默认提供以下数据卷定义: - -```shell -/srv/data # Redis 数据文件,主要存放Redis持久化数据;自动创建子目录redis -/srv/conf # Redis 配置文件;自动创建子目录redis -/var/log # 日志文件,日志文件名为:redis-server.log -/var/run # 进程运行PID文件,PID文件名为:redis_6379.pid -``` - -如果需要持久化存储相应数据,需要在宿主机建立本地目录,并在使用镜像初始化容器时进行映射。 - -举例: - -- 使用宿主机`/opt/conf`存储配置文件 -- 使用宿主机`/srv/data`存储数据文件 -- 使用宿主机`/srv/log`存储日志文件 - -创建以上相应的宿主机目录后,容器启动命令中对应的映射参数类似如下: - -```dockerfile --v /opt/conf:/srv/conf -v /srv/data:/srv/data -v /srv/log:/var/log -``` - -> 注意:应用需要使用的子目录会自动创建。 - - - -## 使用说明 - - - -### 运行容器 - -生成并运行一个新的容器: - -```bash -docker run -d --name redis \ - -p 6379:6379 \ - -v /host/dir/for/data:/srv/data \ - -v /host/dir/for/conf:/srv/conf \ - -v /host/dir/for/log:/var/log \ - -v /host/dir/for/run:/var/run \ - endial/redis:5.0.8 -``` - - - -使用个性化配置文件运行容器: - -```shell -docker run -d --name redis \ - -p 6379:6379 \ - -v /host/dir/for/data:/srv/data \ - -v /host/dir/for/conf:/srv/conf \ - -v /host/dir/for/log:/var/log \ - -v /host/dir/for/run:/var/run \ - endial/redis:5.0.8 redis-server /srv/conf/redis/redis.conf --appendonly yes -``` - -- `redis-server /srv/conf/redis/redis.conf`:用于以指定的配置文件创建容器,路径不可修改(为容器中路径) -- 该文件可以在宿主机路径`/host/dir/for/conf`中找到并进行修改;修改后需要重启容器才能使配置起作用 -- `--appendonly yes`:打开redis持久化配置(非必须),可通过配置文件修改 - - - -如果存在`dvc`数据容器,可以使用以下命令: - -```bash -docker run -d --name redis \ - -p 6379:6379 \ - --volumes-from dvc \ - endial/redis:5.0.8 -``` - - - -### 进入容器 - -使用容器ID或启动时的命名(本例中命名为`redis`)进入容器: - -```shell -docker exec -it redis /bin/sh -``` - - - -### 停止容器 - -使用容器ID或启动时的命名(本例中命名为`redis`)停止: - -```shell -docker stop redis -``` - - - -## 注意事项 - -- 容器中Redis启动参数不能配置为后台运行,只能使用前台运行方式,即:`daemonize no` -- 如果应用使用后台方式运行,则容器的启动命令会在运行后自动退出,从而导致容器退出 - - - ----- - -本文原始来源 [Endial Fang](https://github.com/endial) @ [Github.com](https://github.com) - diff --git a/5.0/alpine/redis/default/redis.conf b/5.0/alpine/redis/default/redis.conf deleted file mode 100644 index c934d74..0000000 --- a/5.0/alpine/redis/default/redis.conf +++ /dev/null @@ -1,1378 +0,0 @@ -# Redis configuration file example. -# -# Note that in order to read the configuration file, Redis must be -# started with the file path as first argument: -# -# ./redis-server /path/to/redis.conf - -# Note on units: when memory size is needed, it is possible to specify -# it in the usual form of 1k 5GB 4M and so forth: -# -# 1k => 1000 bytes -# 1kb => 1024 bytes -# 1m => 1000000 bytes -# 1mb => 1024*1024 bytes -# 1g => 1000000000 bytes -# 1gb => 1024*1024*1024 bytes -# -# units are case insensitive so 1GB 1Gb 1gB are all the same. - -################################## INCLUDES ################################### - -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all Redis servers but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. -# -# Notice option "include" won't be rewritten by command "CONFIG REWRITE" -# from admin or Redis Sentinel. Since Redis always uses the last processed -# line as value of a configuration directive, you'd better put includes -# at the beginning of this file to avoid overwriting config change at runtime. -# -# If instead you are interested in using includes to override configuration -# options, it is better to use include as the last line. -# -# include /path/to/local.conf -# include /path/to/other.conf - -################################## MODULES ##################################### - -# Load modules at startup. If the server is not able to load modules -# it will abort. It is possible to use multiple loadmodule directives. -# -# loadmodule /path/to/my_module.so -# loadmodule /path/to/other_module.so - -################################## NETWORK ##################################### - -# By default, if no "bind" configuration directive is specified, Redis listens -# for connections from all the network interfaces available on the server. -# It is possible to listen to just one or multiple selected interfaces using -# the "bind" configuration directive, followed by one or more IP addresses. -# -# Examples: -# -# bind 192.168.1.100 10.0.0.1 -# bind 127.0.0.1 ::1 -# -# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the -# internet, binding to all the interfaces is dangerous and will expose the -# instance to everybody on the internet. So by default we uncomment the -# following bind directive, that will force Redis to listen only into -# the IPv4 loopback interface address (this means Redis will be able to -# accept connections only from clients running into the same computer it -# is running). -# -# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES -# JUST COMMENT THE FOLLOWING LINE. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Modify by Endial Fang -#bind 127.0.0.1 -bind 0.0.0.0 - -# Protected mode is a layer of security protection, in order to avoid that -# Redis instances left open on the internet are accessed and exploited. -# -# When protected mode is on and if: -# -# 1) The server is not binding explicitly to a set of addresses using the -# "bind" directive. -# 2) No password is configured. -# -# The server only accepts connections from clients connecting from the -# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain -# sockets. -# -# By default protected mode is enabled. You should disable it only if -# you are sure you want clients from other hosts to connect to Redis -# even if no authentication is configured, nor a specific set of interfaces -# are explicitly listed using the "bind" directive. -protected-mode yes - -# Accept connections on the specified port, default is 6379 (IANA #815344). -# If port 0 is specified Redis will not listen on a TCP socket. -port 6379 - -# TCP listen() backlog. -# -# In high requests-per-second environments you need an high backlog in order -# to avoid slow clients connections issues. Note that the Linux kernel -# will silently truncate it to the value of /proc/sys/net/core/somaxconn so -# make sure to raise both the value of somaxconn and tcp_max_syn_backlog -# in order to get the desired effect. -tcp-backlog 511 - -# Unix socket. -# -# Specify the path for the Unix socket that will be used to listen for -# incoming connections. There is no default, so Redis will not listen -# on a unix socket when not specified. -# -# unixsocket /tmp/redis.sock -# unixsocketperm 700 - -# Close the connection after a client is idle for N seconds (0 to disable) -timeout 0 - -# TCP keepalive. -# -# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence -# of communication. This is useful for two reasons: -# -# 1) Detect dead peers. -# 2) Take the connection alive from the point of view of network -# equipment in the middle. -# -# On Linux, the specified value (in seconds) is the period used to send ACKs. -# Note that to close the connection the double of the time is needed. -# On other kernels the period depends on the kernel configuration. -# -# A reasonable value for this option is 300 seconds, which is the new -# Redis default starting with Redis 3.2.1. -tcp-keepalive 300 - -################################# GENERAL ##################################### - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize no - -# If you run Redis from upstart or systemd, Redis can interact with your -# supervision tree. Options: -# supervised no - no supervision interaction -# supervised upstart - signal upstart by putting Redis into SIGSTOP mode -# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET -# supervised auto - detect upstart or systemd method based on -# UPSTART_JOB or NOTIFY_SOCKET environment variables -# Note: these supervision methods only signal "process is ready." -# They do not enable continuous liveness pings back to your supervisor. -supervised no - -# If a pid file is specified, Redis writes it where specified at startup -# and removes it at exit. -# -# When the server runs non daemonized, no pid file is created if none is -# specified in the configuration. When the server is daemonized, the pid file -# is used even if not specified, defaulting to "/var/run/redis.pid". -# -# Creating a pid file is best effort: if Redis is not able to create it -# nothing bad happens, the server will start and run normally. -# -# Modify by Endial Fang, Please use default directory: /var/run/redis/ -pidfile /var/run/redis/redis_6379.pid - -# Specify the server verbosity level. -# This can be one of: -# debug (a lot of information, useful for development/testing) -# verbose (many rarely useful info, but not a mess like the debug level) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) -loglevel notice - -# Specify the log file name. Also the empty string can be used to force -# Redis to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -# -# Modify by Endial Fang, Please use default directory: /var/log/redis/ -logfile "" - -# To enable logging to the system logger, just set 'syslog-enabled' to yes, -# and optionally update the other syslog parameters to suit your needs. -# syslog-enabled no - -# Specify the syslog identity. -# syslog-ident redis - -# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -# syslog-facility local0 - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 -databases 16 - -# By default Redis shows an ASCII art logo only when started to log to the -# standard output and if the standard output is a TTY. Basically this means -# that normally a logo is displayed only in interactive sessions. -# -# However it is possible to force the pre-4.0 behavior and always show a -# ASCII art logo in startup logs by setting the following option to yes. -always-show-logo yes - -################################ SNAPSHOTTING ################################ -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -# -# Note: you can disable saving completely by commenting out all "save" lines. -# -# It is also possible to remove all the previously configured save -# points by adding a save directive with a single empty string argument -# like in the following example: -# -# save "" - -save 900 1 -save 300 10 -save 60 10000 - -# By default Redis will stop accepting writes if RDB snapshots are enabled -# (at least one save point) and the latest background save failed. -# This will make the user aware (in a hard way) that data is not persisting -# on disk properly, otherwise chances are that no one will notice and some -# disaster will happen. -# -# If the background saving process will start working again Redis will -# automatically allow writes again. -# -# However if you have setup your proper monitoring of the Redis server -# and persistence, you may want to disable this feature so that Redis will -# continue to work as usual even if there are problems with disk, -# permissions, and so forth. -stop-writes-on-bgsave-error yes - -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. -rdbcompression yes - -# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. -# This makes the format more resistant to corruption but there is a performance -# hit to pay (around 10%) when saving and loading RDB files, so you can disable it -# for maximum performances. -# -# RDB files created with checksum disabled have a checksum of zero that will -# tell the loading code to skip the check. -rdbchecksum yes - -# The filename where to dump the DB -dbfilename dump.rdb - -# The working directory. -# -# The DB will be written inside this directory, with the filename specified -# above using the 'dbfilename' configuration directive. -# -# The Append Only File will also be created inside this directory. -# -# Note that you must specify a directory here, not a file name. -dir ./ - -################################# REPLICATION ################################# - -# Master-Replica replication. Use replicaof to make a Redis instance a copy of -# another Redis server. A few things to understand ASAP about Redis replication. -# -# +------------------+ +---------------+ -# | Master | ---> | Replica | -# | (receive writes) | | (exact copy) | -# +------------------+ +---------------+ -# -# 1) Redis replication is asynchronous, but you can configure a master to -# stop accepting writes if it appears to be not connected with at least -# a given number of replicas. -# 2) Redis replicas are able to perform a partial resynchronization with the -# master if the replication link is lost for a relatively small amount of -# time. You may want to configure the replication backlog size (see the next -# sections of this file) with a sensible value depending on your needs. -# 3) Replication is automatic and does not need user intervention. After a -# network partition replicas automatically try to reconnect to masters -# and resynchronize with them. -# -# replicaof - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the replica to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the replica request. -# -# masterauth - -# When a replica loses its connection with the master, or when the replication -# is still in progress, the replica can act in two different ways: -# -# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will -# still reply to client requests, possibly with out of date data, or the -# data set may just be empty if this is the first synchronization. -# -# 2) if replica-serve-stale-data is set to 'no' the replica will reply with -# an error "SYNC with master in progress" to all the kind of commands -# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, -# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, -# COMMAND, POST, HOST: and LATENCY. -# -replica-serve-stale-data yes - -# You can configure a replica instance to accept writes or not. Writing against -# a replica instance may be useful to store some ephemeral data (because data -# written on a replica will be easily deleted after resync with the master) but -# may also cause problems if clients are writing to it because of a -# misconfiguration. -# -# Since Redis 2.6 by default replicas are read-only. -# -# Note: read only replicas are not designed to be exposed to untrusted clients -# on the internet. It's just a protection layer against misuse of the instance. -# Still a read only replica exports by default all the administrative commands -# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve -# security of read only replicas using 'rename-command' to shadow all the -# administrative / dangerous commands. -replica-read-only yes - -# Replication SYNC strategy: disk or socket. -# -# ------------------------------------------------------- -# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY -# ------------------------------------------------------- -# -# New replicas and reconnecting replicas that are not able to continue the replication -# process just receiving differences, need to do what is called a "full -# synchronization". An RDB file is transmitted from the master to the replicas. -# The transmission can happen in two different ways: -# -# 1) Disk-backed: The Redis master creates a new process that writes the RDB -# file on disk. Later the file is transferred by the parent -# process to the replicas incrementally. -# 2) Diskless: The Redis master creates a new process that directly writes the -# RDB file to replica sockets, without touching the disk at all. -# -# With disk-backed replication, while the RDB file is generated, more replicas -# can be queued and served with the RDB file as soon as the current child producing -# the RDB file finishes its work. With diskless replication instead once -# the transfer starts, new replicas arriving will be queued and a new transfer -# will start when the current one terminates. -# -# When diskless replication is used, the master waits a configurable amount of -# time (in seconds) before starting the transfer in the hope that multiple replicas -# will arrive and the transfer can be parallelized. -# -# With slow disks and fast (large bandwidth) networks, diskless replication -# works better. -repl-diskless-sync no - -# When diskless replication is enabled, it is possible to configure the delay -# the server waits in order to spawn the child that transfers the RDB via socket -# to the replicas. -# -# This is important since once the transfer starts, it is not possible to serve -# new replicas arriving, that will be queued for the next RDB transfer, so the server -# waits a delay in order to let more replicas arrive. -# -# The delay is specified in seconds, and by default is 5 seconds. To disable -# it entirely just set it to 0 seconds and the transfer will start ASAP. -repl-diskless-sync-delay 5 - -# Replicas send PINGs to server in a predefined interval. It's possible to change -# this interval with the repl_ping_replica_period option. The default value is 10 -# seconds. -# -# repl-ping-replica-period 10 - -# The following option sets the replication timeout for: -# -# 1) Bulk transfer I/O during SYNC, from the point of view of replica. -# 2) Master timeout from the point of view of replicas (data, pings). -# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings). -# -# It is important to make sure that this value is greater than the value -# specified for repl-ping-replica-period otherwise a timeout will be detected -# every time there is low traffic between the master and the replica. -# -# repl-timeout 60 - -# Disable TCP_NODELAY on the replica socket after SYNC? -# -# If you select "yes" Redis will use a smaller number of TCP packets and -# less bandwidth to send data to replicas. But this can add a delay for -# the data to appear on the replica side, up to 40 milliseconds with -# Linux kernels using a default configuration. -# -# If you select "no" the delay for data to appear on the replica side will -# be reduced but more bandwidth will be used for replication. -# -# By default we optimize for low latency, but in very high traffic conditions -# or when the master and replicas are many hops away, turning this to "yes" may -# be a good idea. -repl-disable-tcp-nodelay no - -# Set the replication backlog size. The backlog is a buffer that accumulates -# replica data when replicas are disconnected for some time, so that when a replica -# wants to reconnect again, often a full resync is not needed, but a partial -# resync is enough, just passing the portion of data the replica missed while -# disconnected. -# -# The bigger the replication backlog, the longer the time the replica can be -# disconnected and later be able to perform a partial resynchronization. -# -# The backlog is only allocated once there is at least a replica connected. -# -# repl-backlog-size 1mb - -# After a master has no longer connected replicas for some time, the backlog -# will be freed. The following option configures the amount of seconds that -# need to elapse, starting from the time the last replica disconnected, for -# the backlog buffer to be freed. -# -# Note that replicas never free the backlog for timeout, since they may be -# promoted to masters later, and should be able to correctly "partially -# resynchronize" with the replicas: hence they should always accumulate backlog. -# -# A value of 0 means to never release the backlog. -# -# repl-backlog-ttl 3600 - -# The replica priority is an integer number published by Redis in the INFO output. -# It is used by Redis Sentinel in order to select a replica to promote into a -# master if the master is no longer working correctly. -# -# A replica with a low priority number is considered better for promotion, so -# for instance if there are three replicas with priority 10, 100, 25 Sentinel will -# pick the one with priority 10, that is the lowest. -# -# However a special priority of 0 marks the replica as not able to perform the -# role of master, so a replica with priority of 0 will never be selected by -# Redis Sentinel for promotion. -# -# By default the priority is 100. -replica-priority 100 - -# It is possible for a master to stop accepting writes if there are less than -# N replicas connected, having a lag less or equal than M seconds. -# -# The N replicas need to be in "online" state. -# -# The lag in seconds, that must be <= the specified value, is calculated from -# the last ping received from the replica, that is usually sent every second. -# -# This option does not GUARANTEE that N replicas will accept the write, but -# will limit the window of exposure for lost writes in case not enough replicas -# are available, to the specified number of seconds. -# -# For example to require at least 3 replicas with a lag <= 10 seconds use: -# -# min-replicas-to-write 3 -# min-replicas-max-lag 10 -# -# Setting one or the other to 0 disables the feature. -# -# By default min-replicas-to-write is set to 0 (feature disabled) and -# min-replicas-max-lag is set to 10. - -# A Redis master is able to list the address and port of the attached -# replicas in different ways. For example the "INFO replication" section -# offers this information, which is used, among other tools, by -# Redis Sentinel in order to discover replica instances. -# Another place where this info is available is in the output of the -# "ROLE" command of a master. -# -# The listed IP and address normally reported by a replica is obtained -# in the following way: -# -# IP: The address is auto detected by checking the peer address -# of the socket used by the replica to connect with the master. -# -# Port: The port is communicated by the replica during the replication -# handshake, and is normally the port that the replica is using to -# listen for connections. -# -# However when port forwarding or Network Address Translation (NAT) is -# used, the replica may be actually reachable via different IP and port -# pairs. The following two options can be used by a replica in order to -# report to its master a specific set of IP and port, so that both INFO -# and ROLE will report those values. -# -# There is no need to use both the options if you need to override just -# the port or the IP address. -# -# replica-announce-ip 5.5.5.5 -# replica-announce-port 1234 - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# Warning: since Redis is pretty fast an outside user can try up to -# 150k passwords per second against a good box. This means that you should -# use a very strong password otherwise it will be very easy to break. -# -# requirepass foobared - -# Command renaming. -# -# It is possible to change the name of dangerous commands in a shared -# environment. For instance the CONFIG command may be renamed into something -# hard to guess so that it will still be available for internal-use tools -# but not available for general clients. -# -# Example: -# -# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 -# -# It is also possible to completely kill a command by renaming it into -# an empty string: -# -# rename-command CONFIG "" -# -# Please note that changing the name of commands that are logged into the -# AOF file or transmitted to replicas may cause problems. - -################################### CLIENTS #################################### - -# Set the max number of connected clients at the same time. By default -# this limit is set to 10000 clients, however if the Redis server is not -# able to configure the process file limit to allow for the specified limit -# the max number of allowed clients is set to the current file limit -# minus 32 (as Redis reserves a few file descriptors for internal uses). -# -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 10000 - -############################## MEMORY MANAGEMENT ################################ - -# Set a memory usage limit to the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys -# according to the eviction policy selected (see maxmemory-policy). -# -# If Redis can't remove keys according to the policy, or if the policy is -# set to 'noeviction', Redis will start to reply with errors to commands -# that would use more memory, like SET, LPUSH, and so on, and will continue -# to reply to read-only commands like GET. -# -# This option is usually useful when using Redis as an LRU or LFU cache, or to -# set a hard memory limit for an instance (using the 'noeviction' policy). -# -# WARNING: If you have replicas attached to an instance with maxmemory on, -# the size of the output buffers needed to feed the replicas are subtracted -# from the used memory count, so that network problems / resyncs will -# not trigger a loop where keys are evicted, and in turn the output -# buffer of replicas is full with DELs of keys evicted triggering the deletion -# of more keys, and so forth until the database is completely emptied. -# -# In short... if you have replicas attached it is suggested that you set a lower -# limit for maxmemory so that there is some free RAM on the system for replica -# output buffers (but this is not needed if the policy is 'noeviction'). -# -# maxmemory - -# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory -# is reached. You can select among five behaviors: -# -# volatile-lru -> Evict using approximated LRU among the keys with an expire set. -# allkeys-lru -> Evict any key using approximated LRU. -# volatile-lfu -> Evict using approximated LFU among the keys with an expire set. -# allkeys-lfu -> Evict any key using approximated LFU. -# volatile-random -> Remove a random key among the ones with an expire set. -# allkeys-random -> Remove a random key, any key. -# volatile-ttl -> Remove the key with the nearest expire time (minor TTL) -# noeviction -> Don't evict anything, just return an error on write operations. -# -# LRU means Least Recently Used -# LFU means Least Frequently Used -# -# Both LRU, LFU and volatile-ttl are implemented using approximated -# randomized algorithms. -# -# Note: with any of the above policies, Redis will return an error on write -# operations, when there are no suitable keys for eviction. -# -# At the date of writing these commands are: set setnx setex append -# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd -# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby -# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby -# getset mset msetnx exec sort -# -# The default is: -# -# maxmemory-policy noeviction - -# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated -# algorithms (in order to save memory), so you can tune it for speed or -# accuracy. For default Redis will check five keys and pick the one that was -# used less recently, you can change the sample size using the following -# configuration directive. -# -# The default of 5 produces good enough results. 10 Approximates very closely -# true LRU but costs more CPU. 3 is faster but not very accurate. -# -# maxmemory-samples 5 - -# Starting from Redis 5, by default a replica will ignore its maxmemory setting -# (unless it is promoted to master after a failover or manually). It means -# that the eviction of keys will be just handled by the master, sending the -# DEL commands to the replica as keys evict in the master side. -# -# This behavior ensures that masters and replicas stay consistent, and is usually -# what you want, however if your replica is writable, or you want the replica to have -# a different memory setting, and you are sure all the writes performed to the -# replica are idempotent, then you may change this default (but be sure to understand -# what you are doing). -# -# Note that since the replica by default does not evict, it may end using more -# memory than the one set via maxmemory (there are certain buffers that may -# be larger on the replica, or data structures may sometimes take more memory and so -# forth). So make sure you monitor your replicas and make sure they have enough -# memory to never hit a real out-of-memory condition before the master hits -# the configured maxmemory setting. -# -# replica-ignore-maxmemory yes - -############################# LAZY FREEING #################################### - -# Redis has two primitives to delete keys. One is called DEL and is a blocking -# deletion of the object. It means that the server stops processing new commands -# in order to reclaim all the memory associated with an object in a synchronous -# way. If the key deleted is associated with a small object, the time needed -# in order to execute the DEL command is very small and comparable to most other -# O(1) or O(log_N) commands in Redis. However if the key is associated with an -# aggregated value containing millions of elements, the server can block for -# a long time (even seconds) in order to complete the operation. -# -# For the above reasons Redis also offers non blocking deletion primitives -# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and -# FLUSHDB commands, in order to reclaim memory in background. Those commands -# are executed in constant time. Another thread will incrementally free the -# object in the background as fast as possible. -# -# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. -# It's up to the design of the application to understand when it is a good -# idea to use one or the other. However the Redis server sometimes has to -# delete keys or flush the whole database as a side effect of other operations. -# Specifically Redis deletes objects independently of a user call in the -# following scenarios: -# -# 1) On eviction, because of the maxmemory and maxmemory policy configurations, -# in order to make room for new data, without going over the specified -# memory limit. -# 2) Because of expire: when a key with an associated time to live (see the -# EXPIRE command) must be deleted from memory. -# 3) Because of a side effect of a command that stores data on a key that may -# already exist. For example the RENAME command may delete the old key -# content when it is replaced with another one. Similarly SUNIONSTORE -# or SORT with STORE option may delete existing keys. The SET command -# itself removes any old content of the specified key in order to replace -# it with the specified string. -# 4) During replication, when a replica performs a full resynchronization with -# its master, the content of the whole database is removed in order to -# load the RDB file just transferred. -# -# In all the above cases the default is to delete objects in a blocking way, -# like if DEL was called. However you can configure each case specifically -# in order to instead release memory in a non-blocking way like if UNLINK -# was called, using the following configuration directives: - -lazyfree-lazy-eviction no -lazyfree-lazy-expire no -lazyfree-lazy-server-del no -replica-lazy-flush no - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. This mode is -# good enough in many applications, but an issue with the Redis process or -# a power outage may result into a few minutes of writes lost (depending on -# the configured save points). -# -# The Append Only File is an alternative persistence mode that provides -# much better durability. For instance using the default data fsync policy -# (see later in the config file) Redis can lose just one second of writes in a -# dramatic event like a server power outage, or a single write if something -# wrong with the Redis process itself happens, but the operating system is -# still running correctly. -# -# AOF and RDB persistence can be enabled at the same time without problems. -# If the AOF is enabled on startup Redis will load the AOF, that is the file -# with the better durability guarantees. -# -# Please check http://redis.io/topics/persistence for more information. - -appendonly no - -# The name of the append only file (default: "appendonly.aof") - -appendfilename "appendonly.aof" - -# The fsync() call tells the Operating System to actually write data on disk -# instead of waiting for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log. Slow, Safest. -# everysec: fsync only one time every second. Compromise. -# -# The default is "everysec", as that's usually the right compromise between -# speed and data safety. It's up to you to understand if you can relax this to -# "no" that will let the operating system flush the output buffer when -# it wants, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting), -# or on the contrary, use "always" that's very slow but a bit safer than -# everysec. -# -# More details please check the following article: -# http://antirez.com/post/redis-persistence-demystified.html -# -# If unsure, use "everysec". - -# appendfsync always -appendfsync everysec -# appendfsync no - -# When the AOF fsync policy is set to always or everysec, and a background -# saving process (a background save or AOF log background rewriting) is -# performing a lot of I/O against the disk, in some Linux configurations -# Redis may block too long on the fsync() call. Note that there is no fix for -# this currently, as even performing fsync in a different thread will block -# our synchronous write(2) call. -# -# In order to mitigate this problem it's possible to use the following option -# that will prevent fsync() from being called in the main process while a -# BGSAVE or BGREWRITEAOF is in progress. -# -# This means that while another child is saving, the durability of Redis is -# the same as "appendfsync none". In practical terms, this means that it is -# possible to lose up to 30 seconds of log in the worst scenario (with the -# default Linux settings). -# -# If you have latency problems turn this to "yes". Otherwise leave it as -# "no" that is the safest pick from the point of view of durability. - -no-appendfsync-on-rewrite no - -# Automatic rewrite of the append only file. -# Redis is able to automatically rewrite the log file implicitly calling -# BGREWRITEAOF when the AOF log size grows by the specified percentage. -# -# This is how it works: Redis remembers the size of the AOF file after the -# latest rewrite (if no rewrite has happened since the restart, the size of -# the AOF at startup is used). -# -# This base size is compared to the current size. If the current size is -# bigger than the specified percentage, the rewrite is triggered. Also -# you need to specify a minimal size for the AOF file to be rewritten, this -# is useful to avoid rewriting the AOF file even if the percentage increase -# is reached but it is still pretty small. -# -# Specify a percentage of zero in order to disable the automatic AOF -# rewrite feature. - -auto-aof-rewrite-percentage 100 -auto-aof-rewrite-min-size 64mb - -# An AOF file may be found to be truncated at the end during the Redis -# startup process, when the AOF data gets loaded back into memory. -# This may happen when the system where Redis is running -# crashes, especially when an ext4 filesystem is mounted without the -# data=ordered option (however this can't happen when Redis itself -# crashes or aborts but the operating system still works correctly). -# -# Redis can either exit with an error when this happens, or load as much -# data as possible (the default now) and start if the AOF file is found -# to be truncated at the end. The following option controls this behavior. -# -# If aof-load-truncated is set to yes, a truncated AOF file is loaded and -# the Redis server starts emitting a log to inform the user of the event. -# Otherwise if the option is set to no, the server aborts with an error -# and refuses to start. When the option is set to no, the user requires -# to fix the AOF file using the "redis-check-aof" utility before to restart -# the server. -# -# Note that if the AOF file will be found to be corrupted in the middle -# the server will still exit with an error. This option only applies when -# Redis will try to read more data from the AOF file but not enough bytes -# will be found. -aof-load-truncated yes - -# When rewriting the AOF file, Redis is able to use an RDB preamble in the -# AOF file for faster rewrites and recoveries. When this option is turned -# on the rewritten AOF file is composed of two different stanzas: -# -# [RDB file][AOF tail] -# -# When loading Redis recognizes that the AOF file starts with the "REDIS" -# string and loads the prefixed RDB file, and continues loading the AOF -# tail. -aof-use-rdb-preamble yes - -################################ LUA SCRIPTING ############################### - -# Max execution time of a Lua script in milliseconds. -# -# If the maximum execution time is reached Redis will log that a script is -# still in execution after the maximum allowed time and will start to -# reply to queries with an error. -# -# When a long running script exceeds the maximum execution time only the -# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be -# used to stop a script that did not yet called write commands. The second -# is the only way to shut down the server in the case a write command was -# already issued by the script but the user doesn't want to wait for the natural -# termination of the script. -# -# Set it to 0 or a negative value for unlimited execution without warnings. -lua-time-limit 5000 - -################################ REDIS CLUSTER ############################### - -# Normal Redis instances can't be part of a Redis Cluster; only nodes that are -# started as cluster nodes can. In order to start a Redis instance as a -# cluster node enable the cluster support uncommenting the following: -# -# cluster-enabled yes - -# Every cluster node has a cluster configuration file. This file is not -# intended to be edited by hand. It is created and updated by Redis nodes. -# Every Redis Cluster node requires a different cluster configuration file. -# Make sure that instances running in the same system do not have -# overlapping cluster configuration file names. -# -# cluster-config-file nodes-6379.conf - -# Cluster node timeout is the amount of milliseconds a node must be unreachable -# for it to be considered in failure state. -# Most other internal time limits are multiple of the node timeout. -# -# cluster-node-timeout 15000 - -# A replica of a failing master will avoid to start a failover if its data -# looks too old. -# -# There is no simple way for a replica to actually have an exact measure of -# its "data age", so the following two checks are performed: -# -# 1) If there are multiple replicas able to failover, they exchange messages -# in order to try to give an advantage to the replica with the best -# replication offset (more data from the master processed). -# Replicas will try to get their rank by offset, and apply to the start -# of the failover a delay proportional to their rank. -# -# 2) Every single replica computes the time of the last interaction with -# its master. This can be the last ping or command received (if the master -# is still in the "connected" state), or the time that elapsed since the -# disconnection with the master (if the replication link is currently down). -# If the last interaction is too old, the replica will not try to failover -# at all. -# -# The point "2" can be tuned by user. Specifically a replica will not perform -# the failover if, since the last interaction with the master, the time -# elapsed is greater than: -# -# (node-timeout * replica-validity-factor) + repl-ping-replica-period -# -# So for example if node-timeout is 30 seconds, and the replica-validity-factor -# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the -# replica will not try to failover if it was not able to talk with the master -# for longer than 310 seconds. -# -# A large replica-validity-factor may allow replicas with too old data to failover -# a master, while a too small value may prevent the cluster from being able to -# elect a replica at all. -# -# For maximum availability, it is possible to set the replica-validity-factor -# to a value of 0, which means, that replicas will always try to failover the -# master regardless of the last time they interacted with the master. -# (However they'll always try to apply a delay proportional to their -# offset rank). -# -# Zero is the only value able to guarantee that when all the partitions heal -# the cluster will always be able to continue. -# -# cluster-replica-validity-factor 10 - -# Cluster replicas are able to migrate to orphaned masters, that are masters -# that are left without working replicas. This improves the cluster ability -# to resist to failures as otherwise an orphaned master can't be failed over -# in case of failure if it has no working replicas. -# -# Replicas migrate to orphaned masters only if there are still at least a -# given number of other working replicas for their old master. This number -# is the "migration barrier". A migration barrier of 1 means that a replica -# will migrate only if there is at least 1 other working replica for its master -# and so forth. It usually reflects the number of replicas you want for every -# master in your cluster. -# -# Default is 1 (replicas migrate only if their masters remain with at least -# one replica). To disable migration just set it to a very large value. -# A value of 0 can be set but is useful only for debugging and dangerous -# in production. -# -# cluster-migration-barrier 1 - -# By default Redis Cluster nodes stop accepting queries if they detect there -# is at least an hash slot uncovered (no available node is serving it). -# This way if the cluster is partially down (for example a range of hash slots -# are no longer covered) all the cluster becomes, eventually, unavailable. -# It automatically returns available as soon as all the slots are covered again. -# -# However sometimes you want the subset of the cluster which is working, -# to continue to accept queries for the part of the key space that is still -# covered. In order to do so, just set the cluster-require-full-coverage -# option to no. -# -# cluster-require-full-coverage yes - -# This option, when set to yes, prevents replicas from trying to failover its -# master during master failures. However the master can still perform a -# manual failover, if forced to do so. -# -# This is useful in different scenarios, especially in the case of multiple -# data center operations, where we want one side to never be promoted if not -# in the case of a total DC failure. -# -# cluster-replica-no-failover no - -# In order to setup your cluster make sure to read the documentation -# available at http://redis.io web site. - -########################## CLUSTER DOCKER/NAT support ######################## - -# In certain deployments, Redis Cluster nodes address discovery fails, because -# addresses are NAT-ted or because ports are forwarded (the typical case is -# Docker and other containers). -# -# In order to make Redis Cluster working in such environments, a static -# configuration where each node knows its public address is needed. The -# following two options are used for this scope, and are: -# -# * cluster-announce-ip -# * cluster-announce-port -# * cluster-announce-bus-port -# -# Each instruct the node about its address, client port, and cluster message -# bus port. The information is then published in the header of the bus packets -# so that other nodes will be able to correctly map the address of the node -# publishing the information. -# -# If the above options are not used, the normal Redis Cluster auto-detection -# will be used instead. -# -# Note that when remapped, the bus port may not be at the fixed offset of -# clients port + 10000, so you can specify any port and bus-port depending -# on how they get remapped. If the bus-port is not set, a fixed offset of -# 10000 will be used as usually. -# -# Example: -# -# cluster-announce-ip 10.1.1.5 -# cluster-announce-port 6379 -# cluster-announce-bus-port 6380 - -################################## SLOW LOG ################################### - -# The Redis Slow Log is a system to log queries that exceeded a specified -# execution time. The execution time does not include the I/O operations -# like talking with the client, sending the reply and so forth, -# but just the time needed to actually execute the command (this is the only -# stage of command execution where the thread is blocked and can not serve -# other requests in the meantime). -# -# You can configure the slow log with two parameters: one tells Redis -# what is the execution time, in microseconds, to exceed in order for the -# command to get logged, and the other parameter is the length of the -# slow log. When a new command is logged the oldest one is removed from the -# queue of logged commands. - -# The following time is expressed in microseconds, so 1000000 is equivalent -# to one second. Note that a negative number disables the slow log, while -# a value of zero forces the logging of every command. -slowlog-log-slower-than 10000 - -# There is no limit to this length. Just be aware that it will consume memory. -# You can reclaim memory used by the slow log with SLOWLOG RESET. -slowlog-max-len 128 - -################################ LATENCY MONITOR ############################## - -# The Redis latency monitoring subsystem samples different operations -# at runtime in order to collect data related to possible sources of -# latency of a Redis instance. -# -# Via the LATENCY command this information is available to the user that can -# print graphs and obtain reports. -# -# The system only logs operations that were performed in a time equal or -# greater than the amount of milliseconds specified via the -# latency-monitor-threshold configuration directive. When its value is set -# to zero, the latency monitor is turned off. -# -# By default latency monitoring is disabled since it is mostly not needed -# if you don't have latency issues, and collecting data has a performance -# impact, that while very small, can be measured under big load. Latency -# monitoring can easily be enabled at runtime using the command -# "CONFIG SET latency-monitor-threshold " if needed. -latency-monitor-threshold 0 - -############################# EVENT NOTIFICATION ############################## - -# Redis can notify Pub/Sub clients about events happening in the key space. -# This feature is documented at http://redis.io/topics/notifications -# -# For instance if keyspace events notification is enabled, and a client -# performs a DEL operation on key "foo" stored in the Database 0, two -# messages will be published via Pub/Sub: -# -# PUBLISH __keyspace@0__:foo del -# PUBLISH __keyevent@0__:del foo -# -# It is possible to select the events that Redis will notify among a set -# of classes. Every class is identified by a single character: -# -# K Keyspace events, published with __keyspace@__ prefix. -# E Keyevent events, published with __keyevent@__ prefix. -# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... -# $ String commands -# l List commands -# s Set commands -# h Hash commands -# z Sorted set commands -# x Expired events (events generated every time a key expires) -# e Evicted events (events generated when a key is evicted for maxmemory) -# A Alias for g$lshzxe, so that the "AKE" string means all the events. -# -# The "notify-keyspace-events" takes as argument a string that is composed -# of zero or multiple characters. The empty string means that notifications -# are disabled. -# -# Example: to enable list and generic events, from the point of view of the -# event name, use: -# -# notify-keyspace-events Elg -# -# Example 2: to get the stream of the expired keys subscribing to channel -# name __keyevent@0__:expired use: -# -# notify-keyspace-events Ex -# -# By default all notifications are disabled because most users don't need -# this feature and the feature has some overhead. Note that if you don't -# specify at least one of K or E, no events will be delivered. -notify-keyspace-events "" - -############################### ADVANCED CONFIG ############################### - -# Hashes are encoded using a memory efficient data structure when they have a -# small number of entries, and the biggest entry does not exceed a given -# threshold. These thresholds can be configured using the following directives. -hash-max-ziplist-entries 512 -hash-max-ziplist-value 64 - -# Lists are also encoded in a special way to save a lot of space. -# The number of entries allowed per internal list node can be specified -# as a fixed maximum size or a maximum number of elements. -# For a fixed maximum size, use -5 through -1, meaning: -# -5: max size: 64 Kb <-- not recommended for normal workloads -# -4: max size: 32 Kb <-- not recommended -# -3: max size: 16 Kb <-- probably not recommended -# -2: max size: 8 Kb <-- good -# -1: max size: 4 Kb <-- good -# Positive numbers mean store up to _exactly_ that number of elements -# per list node. -# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size), -# but if your use case is unique, adjust the settings as necessary. -list-max-ziplist-size -2 - -# Lists may also be compressed. -# Compress depth is the number of quicklist ziplist nodes from *each* side of -# the list to *exclude* from compression. The head and tail of the list -# are always uncompressed for fast push/pop operations. Settings are: -# 0: disable all list compression -# 1: depth 1 means "don't start compressing until after 1 node into the list, -# going from either the head or tail" -# So: [head]->node->node->...->node->[tail] -# [head], [tail] will always be uncompressed; inner nodes will compress. -# 2: [head]->[next]->node->node->...->node->[prev]->[tail] -# 2 here means: don't compress head or head->next or tail->prev or tail, -# but compress all nodes between them. -# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] -# etc. -list-compress-depth 0 - -# Sets have a special encoding in just one case: when a set is composed -# of just strings that happen to be integers in radix 10 in the range -# of 64 bit signed integers. -# The following configuration setting sets the limit in the size of the -# set in order to use this special memory saving encoding. -set-max-intset-entries 512 - -# Similarly to hashes and lists, sorted sets are also specially encoded in -# order to save a lot of space. This encoding is only used when the length and -# elements of a sorted set are below the following limits: -zset-max-ziplist-entries 128 -zset-max-ziplist-value 64 - -# HyperLogLog sparse representation bytes limit. The limit includes the -# 16 bytes header. When an HyperLogLog using the sparse representation crosses -# this limit, it is converted into the dense representation. -# -# A value greater than 16000 is totally useless, since at that point the -# dense representation is more memory efficient. -# -# The suggested value is ~ 3000 in order to have the benefits of -# the space efficient encoding without slowing down too much PFADD, -# which is O(N) with the sparse encoding. The value can be raised to -# ~ 10000 when CPU is not a concern, but space is, and the data set is -# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. -hll-sparse-max-bytes 3000 - -# Streams macro node max size / items. The stream data structure is a radix -# tree of big nodes that encode multiple items inside. Using this configuration -# it is possible to configure how big a single node can be in bytes, and the -# maximum number of items it may contain before switching to a new node when -# appending new stream entries. If any of the following settings are set to -# zero, the limit is ignored, so for instance it is possible to set just a -# max entires limit by setting max-bytes to 0 and max-entries to the desired -# value. -stream-node-max-bytes 4096 -stream-node-max-entries 100 - -# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in -# order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation Redis uses (see dict.c) -# performs a lazy rehashing: the more operation you run into a hash table -# that is rehashing, the more rehashing "steps" are performed, so if the -# server is idle the rehashing is never complete and some more memory is used -# by the hash table. -# -# The default is to use this millisecond 10 times every second in order to -# actively rehash the main dictionaries, freeing memory when possible. -# -# If unsure: -# use "activerehashing no" if you have hard latency requirements and it is -# not a good thing in your environment that Redis can reply from time to time -# to queries with 2 milliseconds delay. -# -# use "activerehashing yes" if you don't have such hard requirements but -# want to free memory asap when possible. -activerehashing yes - -# The client output buffer limits can be used to force disconnection of clients -# that are not reading data from the server fast enough for some reason (a -# common reason is that a Pub/Sub client can't consume messages as fast as the -# publisher can produce them). -# -# The limit can be set differently for the three different classes of clients: -# -# normal -> normal clients including MONITOR clients -# replica -> replica clients -# pubsub -> clients subscribed to at least one pubsub channel or pattern -# -# The syntax of every client-output-buffer-limit directive is the following: -# -# client-output-buffer-limit -# -# A client is immediately disconnected once the hard limit is reached, or if -# the soft limit is reached and remains reached for the specified number of -# seconds (continuously). -# So for instance if the hard limit is 32 megabytes and the soft limit is -# 16 megabytes / 10 seconds, the client will get disconnected immediately -# if the size of the output buffers reach 32 megabytes, but will also get -# disconnected if the client reaches 16 megabytes and continuously overcomes -# the limit for 10 seconds. -# -# By default normal clients are not limited because they don't receive data -# without asking (in a push way), but just after a request, so only -# asynchronous clients may create a scenario where data is requested faster -# than it can read. -# -# Instead there is a default limit for pubsub and replica clients, since -# subscribers and replicas receive data in a push fashion. -# -# Both the hard or the soft limit can be disabled by setting them to zero. -client-output-buffer-limit normal 0 0 0 -client-output-buffer-limit replica 256mb 64mb 60 -client-output-buffer-limit pubsub 32mb 8mb 60 - -# Client query buffers accumulate new commands. They are limited to a fixed -# amount by default in order to avoid that a protocol desynchronization (for -# instance due to a bug in the client) will lead to unbound memory usage in -# the query buffer. However you can configure it here if you have very special -# needs, such us huge multi/exec requests or alike. -# -# client-query-buffer-limit 1gb - -# In the Redis protocol, bulk requests, that are, elements representing single -# strings, are normally limited ot 512 mb. However you can change this limit -# here. -# -# proto-max-bulk-len 512mb - -# Redis calls an internal function to perform many background tasks, like -# closing connections of clients in timeout, purging expired keys that are -# never requested, and so forth. -# -# Not all tasks are performed with the same frequency, but Redis checks for -# tasks to perform according to the specified "hz" value. -# -# By default "hz" is set to 10. Raising the value will use more CPU when -# Redis is idle, but at the same time will make Redis more responsive when -# there are many keys expiring at the same time, and timeouts may be -# handled with more precision. -# -# The range is between 1 and 500, however a value over 100 is usually not -# a good idea. Most users should use the default of 10 and raise this up to -# 100 only in environments where very low latency is required. -hz 10 - -# Normally it is useful to have an HZ value which is proportional to the -# number of clients connected. This is useful in order, for instance, to -# avoid too many clients are processed for each background task invocation -# in order to avoid latency spikes. -# -# Since the default HZ value by default is conservatively set to 10, Redis -# offers, and enables by default, the ability to use an adaptive HZ value -# which will temporary raise when there are many connected clients. -# -# When dynamic HZ is enabled, the actual configured HZ will be used as -# as a baseline, but multiples of the configured HZ value will be actually -# used as needed once more clients are connected. In this way an idle -# instance will use very little CPU time while a busy instance will be -# more responsive. -dynamic-hz yes - -# When a child rewrites the AOF file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -aof-rewrite-incremental-fsync yes - -# When redis saves RDB file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -rdb-save-incremental-fsync yes - -# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good -# idea to start with the default settings and only change them after investigating -# how to improve the performances and how the keys LFU change over time, which -# is possible to inspect via the OBJECT FREQ command. -# -# There are two tunable parameters in the Redis LFU implementation: the -# counter logarithm factor and the counter decay time. It is important to -# understand what the two parameters mean before changing them. -# -# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis -# uses a probabilistic increment with logarithmic behavior. Given the value -# of the old counter, when a key is accessed, the counter is incremented in -# this way: -# -# 1. A random number R between 0 and 1 is extracted. -# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). -# 3. The counter is incremented only if R < P. -# -# The default lfu-log-factor is 10. This is a table of how the frequency -# counter changes with a different number of accesses with different -# logarithmic factors: -# -# +--------+------------+------------+------------+------------+------------+ -# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | -# +--------+------------+------------+------------+------------+------------+ -# | 0 | 104 | 255 | 255 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 1 | 18 | 49 | 255 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 10 | 10 | 18 | 142 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 100 | 8 | 11 | 49 | 143 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# -# NOTE: The above table was obtained by running the following commands: -# -# redis-benchmark -n 1000000 incr foo -# redis-cli object freq foo -# -# NOTE 2: The counter initial value is 5 in order to give new objects a chance -# to accumulate hits. -# -# The counter decay time is the time, in minutes, that must elapse in order -# for the key counter to be divided by two (or decremented if it has a value -# less <= 10). -# -# The default value for the lfu-decay-time is 1. A Special value of 0 means to -# decay the counter every time it happens to be scanned. -# -# lfu-log-factor 10 -# lfu-decay-time 1 - -########################### ACTIVE DEFRAGMENTATION ####################### -# -# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested -# even in production and manually tested by multiple engineers for some -# time. -# -# What is active defragmentation? -# ------------------------------- -# -# Active (online) defragmentation allows a Redis server to compact the -# spaces left between small allocations and deallocations of data in memory, -# thus allowing to reclaim back memory. -# -# Fragmentation is a natural process that happens with every allocator (but -# less so with Jemalloc, fortunately) and certain workloads. Normally a server -# restart is needed in order to lower the fragmentation, or at least to flush -# away all the data and create it again. However thanks to this feature -# implemented by Oran Agra for Redis 4.0 this process can happen at runtime -# in an "hot" way, while the server is running. -# -# Basically when the fragmentation is over a certain level (see the -# configuration options below) Redis will start to create new copies of the -# values in contiguous memory regions by exploiting certain specific Jemalloc -# features (in order to understand if an allocation is causing fragmentation -# and to allocate it in a better place), and at the same time, will release the -# old copies of the data. This process, repeated incrementally for all the keys -# will cause the fragmentation to drop back to normal values. -# -# Important things to understand: -# -# 1. This feature is disabled by default, and only works if you compiled Redis -# to use the copy of Jemalloc we ship with the source code of Redis. -# This is the default with Linux builds. -# -# 2. You never need to enable this feature if you don't have fragmentation -# issues. -# -# 3. Once you experience fragmentation, you can enable this feature when -# needed with the command "CONFIG SET activedefrag yes". -# -# The configuration parameters are able to fine tune the behavior of the -# defragmentation process. If you are not sure about what they mean it is -# a good idea to leave the defaults untouched. - -# Enabled active defragmentation -# activedefrag yes - -# Minimum amount of fragmentation waste to start active defrag -# active-defrag-ignore-bytes 100mb - -# Minimum percentage of fragmentation to start active defrag -# active-defrag-threshold-lower 10 - -# Maximum percentage of fragmentation at which we use maximum effort -# active-defrag-threshold-upper 100 - -# Minimal effort for defrag in CPU percentage -# active-defrag-cycle-min 5 - -# Maximal effort for defrag in CPU percentage -# active-defrag-cycle-max 75 - -# Maximum number of set/hash/zset/list fields that will be processed from -# the main dictionary scan -# active-defrag-max-scan-fields 1000 - diff --git a/5.0/alpine/redis/default/sentinel.conf b/5.0/alpine/redis/default/sentinel.conf deleted file mode 100644 index bc9a705..0000000 --- a/5.0/alpine/redis/default/sentinel.conf +++ /dev/null @@ -1,244 +0,0 @@ -# Example sentinel.conf - -# *** IMPORTANT *** -# -# By default Sentinel will not be reachable from interfaces different than -# localhost, either use the 'bind' directive to bind to a list of network -# interfaces, or disable protected mode with "protected-mode no" by -# adding it to this configuration file. -# -# Before doing that MAKE SURE the instance is protected from the outside -# world via firewalling or other means. -# -# For example you may use one of the following: -# -# bind 127.0.0.1 192.168.1.1 -# -# protected-mode no - -# port -# The port that this sentinel instance will run on -port 26379 - -# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when -# daemonized. -daemonize no - -# When running daemonized, Redis Sentinel writes a pid file in -# /var/run/redis-sentinel.pid by default. You can specify a custom pid file -# location here. -pidfile /var/run/redis-sentinel.pid - -# Specify the log file name. Also the empty string can be used to force -# Sentinel to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -logfile "" - -# sentinel announce-ip -# sentinel announce-port -# -# The above two configuration directives are useful in environments where, -# because of NAT, Sentinel is reachable from outside via a non-local address. -# -# When announce-ip is provided, the Sentinel will claim the specified IP address -# in HELLO messages used to gossip its presence, instead of auto-detecting the -# local address as it usually does. -# -# Similarly when announce-port is provided and is valid and non-zero, Sentinel -# will announce the specified TCP port. -# -# The two options don't need to be used together, if only announce-ip is -# provided, the Sentinel will announce the specified IP and the server port -# as specified by the "port" option. If only announce-port is provided, the -# Sentinel will announce the auto-detected local IP and the specified port. -# -# Example: -# -# sentinel announce-ip 1.2.3.4 - -# dir -# Every long running process should have a well-defined working directory. -# For Redis Sentinel to chdir to /tmp at startup is the simplest thing -# for the process to don't interfere with administrative tasks such as -# unmounting filesystems. -dir /tmp - -# sentinel monitor -# -# Tells Sentinel to monitor this master, and to consider it in O_DOWN -# (Objectively Down) state only if at least sentinels agree. -# -# Note that whatever is the ODOWN quorum, a Sentinel will require to -# be elected by the majority of the known Sentinels in order to -# start a failover, so no failover can be performed in minority. -# -# Replicas are auto-discovered, so you don't need to specify replicas in -# any way. Sentinel itself will rewrite this configuration file adding -# the replicas using additional configuration options. -# Also note that the configuration file is rewritten when a -# replica is promoted to master. -# -# Note: master name should not include special characters or spaces. -# The valid charset is A-z 0-9 and the three characters ".-_". -sentinel monitor mymaster 127.0.0.1 6379 2 - -# sentinel auth-pass -# -# Set the password to use to authenticate with the master and replicas. -# Useful if there is a password set in the Redis instances to monitor. -# -# Note that the master password is also used for replicas, so it is not -# possible to set a different password in masters and replicas instances -# if you want to be able to monitor these instances with Sentinel. -# -# However you can have Redis instances without the authentication enabled -# mixed with Redis instances requiring the authentication (as long as the -# password set is the same for all the instances requiring the password) as -# the AUTH command will have no effect in Redis instances with authentication -# switched off. -# -# Example: -# -# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd - -# sentinel down-after-milliseconds -# -# Number of milliseconds the master (or any attached replica or sentinel) should -# be unreachable (as in, not acceptable reply to PING, continuously, for the -# specified period) in order to consider it in S_DOWN state (Subjectively -# Down). -# -# Default is 30 seconds. -sentinel down-after-milliseconds mymaster 30000 - -# sentinel parallel-syncs -# -# How many replicas we can reconfigure to point to the new replica simultaneously -# during the failover. Use a low number if you use the replicas to serve query -# to avoid that all the replicas will be unreachable at about the same -# time while performing the synchronization with the master. -sentinel parallel-syncs mymaster 1 - -# sentinel failover-timeout -# -# Specifies the failover timeout in milliseconds. It is used in many ways: -# -# - The time needed to re-start a failover after a previous failover was -# already tried against the same master by a given Sentinel, is two -# times the failover timeout. -# -# - The time needed for a replica replicating to a wrong master according -# to a Sentinel current configuration, to be forced to replicate -# with the right master, is exactly the failover timeout (counting since -# the moment a Sentinel detected the misconfiguration). -# -# - The time needed to cancel a failover that is already in progress but -# did not produced any configuration change (SLAVEOF NO ONE yet not -# acknowledged by the promoted replica). -# -# - The maximum time a failover in progress waits for all the replicas to be -# reconfigured as replicas of the new master. However even after this time -# the replicas will be reconfigured by the Sentinels anyway, but not with -# the exact parallel-syncs progression as specified. -# -# Default is 3 minutes. -sentinel failover-timeout mymaster 180000 - -# SCRIPTS EXECUTION -# -# sentinel notification-script and sentinel reconfig-script are used in order -# to configure scripts that are called to notify the system administrator -# or to reconfigure clients after a failover. The scripts are executed -# with the following rules for error handling: -# -# If script exits with "1" the execution is retried later (up to a maximum -# number of times currently set to 10). -# -# If script exits with "2" (or an higher value) the script execution is -# not retried. -# -# If script terminates because it receives a signal the behavior is the same -# as exit code 1. -# -# A script has a maximum running time of 60 seconds. After this limit is -# reached the script is terminated with a SIGKILL and the execution retried. - -# NOTIFICATION SCRIPT -# -# sentinel notification-script -# -# Call the specified notification script for any sentinel event that is -# generated in the WARNING level (for instance -sdown, -odown, and so forth). -# This script should notify the system administrator via email, SMS, or any -# other messaging system, that there is something wrong with the monitored -# Redis systems. -# -# The script is called with just two arguments: the first is the event type -# and the second the event description. -# -# The script must exist and be executable in order for sentinel to start if -# this option is provided. -# -# Example: -# -# sentinel notification-script mymaster /var/redis/notify.sh - -# CLIENTS RECONFIGURATION SCRIPT -# -# sentinel client-reconfig-script -# -# When the master changed because of a failover a script can be called in -# order to perform application-specific tasks to notify the clients that the -# configuration has changed and the master is at a different address. -# -# The following arguments are passed to the script: -# -# -# -# is currently always "failover" -# is either "leader" or "observer" -# -# The arguments from-ip, from-port, to-ip, to-port are used to communicate -# the old address of the master and the new address of the elected replica -# (now a master). -# -# This script should be resistant to multiple invocations. -# -# Example: -# -# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh - -# SECURITY -# -# By default SENTINEL SET will not be able to change the notification-script -# and client-reconfig-script at runtime. This avoids a trivial security issue -# where clients can set the script to anything and trigger a failover in order -# to get the program executed. - -sentinel deny-scripts-reconfig yes - -# REDIS COMMANDS RENAMING -# -# Sometimes the Redis server has certain commands, that are needed for Sentinel -# to work correctly, renamed to unguessable strings. This is often the case -# of CONFIG and SLAVEOF in the context of providers that provide Redis as -# a service, and don't want the customers to reconfigure the instances outside -# of the administration console. -# -# In such case it is possible to tell Sentinel to use different command names -# instead of the normal ones. For example if the master "mymaster", and the -# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use: -# -# SENTINEL rename-command mymaster CONFIG GUESSME -# -# After such configuration is set, every time Sentinel would use CONFIG it will -# use GUESSME instead. Note that there is no actual need to respect the command -# case, so writing "config guessme" is the same in the example above. -# -# SENTINEL SET can also be used in order to perform this configuration at runtime. -# -# In order to set a command back to its original name (undo the renaming), it -# is possible to just rename a command to itsef: -# -# SENTINEL rename-command mymaster CONFIG CONFIG diff --git a/5.0/alpine/redis/entrypoint.sh b/5.0/alpine/redis/entrypoint.sh deleted file mode 100755 index 9f303b6..0000000 --- a/5.0/alpine/redis/entrypoint.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -# docker entrypoint script - -echo "[i] Initial Container for redis" - -set -e - -if [ ! -d /var/log/redis ]; then - echo "[i] Create directory: /var/log/redis" - mkdir -p /var/log/redis - chown redis:root /var/log/redis -fi - -if [ ! -d /var/run/redis ]; then - echo "[i] Create directory: /var/run/redis" - mkdir -p /var/run/redis - chown redis:root /var/run/redis -fi - -if [ ! -d /srv/data/redis ]; then - echo "[i] Create directory: /srv/data/redis" - mkdir -p /srv/data/redis - chown redis:root /srv/data/redis -fi - -if [ ! -d /srv/conf/redis ]; then - echo "[i] Create directory: /srv/conf/redis" - mkdir -p /srv/conf/redis - chown redis:root /srv/conf/redis -fi - -if [ ! -f /srv/conf/redis/redis.conf ]; then - echo "[i] Copy default redis.conf to /srv/conf/redis" - cp /etc/redis/default/redis.conf /srv/conf/redis/ -fi - -if [ ! -f /srv/conf/redis/sentinel.conf ]; then - echo "[i] Copy default sentinel.conf to /srv/conf/redis" - cp /etc/redis/default/sentinel.conf /srv/conf/redis/ -fi - -# first arg is `-f` or `--some-option` -# or first arg is `something.conf` -if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then - echo "[i] Reset command parameter: $@" - set -- redis-server "$@" - echo "[i] After reset: $@" -fi - -# allow the container to be started with `--user` or `-u` -if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then - find . \! -user redis -exec chown redis '{}' + - echo "[i] Restart container with user: redis" - echo "" - exec gosu redis "$0" "$@" -fi - -echo "[i] Start redis-server with parameter: $@" -exec "$@" diff --git a/5.0/entrypoint.sh b/5.0/entrypoint.sh deleted file mode 100755 index b4ab8b2..0000000 --- a/5.0/entrypoint.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash -# Alpine 系统只能使用 /bin/sh -# -# docker entrypoint script - -# Alpine系统因使用/bin/sh,仅支持 set -e -set -Eeo pipefail - -LOG_RAW() { - local type="$1"; shift - printf '%s [%s] Entrypoint: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$type" "$*" -} -LOG_I() { - LOG_RAW Note "$@" -} -LOG_W() { - LOG_RAW Warn "$@" >&2 -} -LOG_E() { - LOG_RAW Error "$@" >&2 - exit 1 -} - -LOG_I "Initial container for Redis" - -# 检测当前脚本是被直接执行的,还是从其他脚本中使用 "source" 调用的 -_is_sourced() { - [ "${#FUNCNAME[@]}" -ge 2 ] \ - && [ "${FUNCNAME[0]}" = '_is_sourced' ] \ - && [ "${FUNCNAME[1]}" = 'source' ] -} - -# 使用root用户运行时,创建默认的数据目录,并拷贝所必须的默认配置文件及初始化文件 -# 修改对应目录所属用户为应用对应的用户(Docker镜像创建时,相应目录默认为777模式) -docker_create_user_directories() { - local user_id; user_id="$(id -u)" -#/etc/redis/default /srv/conf/redis /srv/data/redis - LOG_I "Check directories used by redis" - mkdir -p "/var/log/redis" - mkdir -p "/var/run/redis" - mkdir -p "/srv/data/redis" - - mkdir -p "/srv/conf/redis" - # 检测指定文件是否存在,如果不存在则拷贝 - [ ! -e /srv/conf/redis/redis.conf ] && cp /etc/redis/default/redis.conf /srv/conf/redis/redis.conf - [ ! -e /srv/conf/redis/sentinel.conf ] && cp /etc/redis/default/sentinel.conf /srv/conf/redis/sentinel.conf - - # 允许容器使用`--user`参数启动,修改相应目录的所属用户信息 - # 如果设置了'--user',这里 user_id 不为 0 - # 如果没有设置'--user',这里 user_id 为 0,需要使用默认用户名设置相关目录权限 - if [ "$user_id" = '0' ]; then - find /var/run/redis \! -user redis -exec chown redis '{}' + - find /var/log/redis \! -user redis -exec chown redis '{}' + - find /srv/data/redis \! -user redis -exec chown redis '{}' + - find /srv/conf/redis \! -user redis -exec chown redis '{}' + - chmod 0755 /etc/redis /var/log/redis /var/run/redis /srv/conf/redis /srv/data/redis - # 解决使用gosu后,nginx: [emerg] open() "/dev/stdout" failed (13: Permission denied) - chmod 0622 /dev/stdout /dev/stderr - fi -} - -# 检测可能导致容器执行后直接退出的命令,如"--help";如果存在,直接返回 0 -docker_app_want_help() { - local arg - for arg; do - case "$arg" in - -'?'|--help|-V|--version) - return 0 - ;; - esac - done - return 1 -} - -_main() { - # 如果命令行参数是以配置参数("-")开始,修改执行命令,确保使用可执行应用命令启动服务器 - if [ "${1:0:1}" = '-' ]; then - set -- redis-server "$@" - fi - - # 命令行参数以可执行应用命令起始,且不包含直接返回的命令(如:-V、--version、--help)时,执行初始化操作 - if [ "$1" = "redis-server" ] && ! docker_app_want_help "$@"; then - # 以root用户运行时,设置数据存储目录与权限;设置完成后,会使用gosu重新以"redis"用户运行当前脚本 - docker_create_user_directories - if [ "$(id -u)" = '0' ]; then - LOG_I "Restart container with default user: redis'" - LOG_I "" - exec gosu redis "$0" "$@" - fi - fi - - LOG_I "Start container with: $@" - # 执行命令行 - exec "$@" -} - -if ! _is_sourced; then - _main "$@" -fi diff --git a/5.0/prebuilds/usr/local/bin/appcommon.sh b/5.0/prebuilds/usr/local/bin/appcommon.sh new file mode 100644 index 0000000..e9ad53e --- /dev/null +++ b/5.0/prebuilds/usr/local/bin/appcommon.sh @@ -0,0 +1,477 @@ +#!/bin/bash +# +# 应用通用业务处理函数 + +# 加载依赖脚本 +. /usr/local/scripts/liblog.sh +. /usr/local/scripts/libfile.sh +. /usr/local/scripts/libfs.sh +. /usr/local/scripts/libos.sh +. /usr/local/scripts/libcommon.sh +. /usr/local/scripts/libvalidations.sh + +# 函数列表 + +# 加载应用使用的环境变量初始值,该函数在相关脚本中以eval方式调用 +# 全局变量: +# ENV_* : 容器使用的全局变量 +# REDIS_* : 应用配置文件使用的全局变量,变量名根据配置项定义 +# 返回值: +# 可以被 'eval' 使用的序列化输出 +docker_app_env() { + # 以下变量已经在创建镜像时定义,可直接使用 + # APP_NAME、APP_EXEC、APP_USER、APP_GROUP、APP_VERSION + # APP_BASE_DIR、APP_DEF_DIR、APP_CONF_DIR、APP_CERT_DIR、APP_DATA_DIR、APP_DATA_LOG_DIR、APP_CACHE_DIR、APP_RUN_DIR、APP_LOG_DIR + cat <<"EOF" +# Debug log message +export ENV_DEBUG=${ENV_DEBUG:-false} + +# Paths +export REDIS_BASE_DIR="${REDIS_BASE_DIR:-${APP_BASE_DIR}}" +export REDIS_DATA_DIR="${REDIS_DATA_DIR:-${APP_DATA_DIR}}" +export REDIS_DATALOG_DIR="${REDIS_DATALOG_DIR:-${APP_DATA_LOG_DIR}}" +export REDIS_CONF_DIR="${REDIS_CONF_DIR:-${APP_CONF_DIR}}" +export REDIS_LOG_DIR="${REDIS_LOG_DIR:-${APP_LOG_DIR}}" +export REDIS_BIN_DIR="${REDIS_BIN_DIR:-${REDIS_BASE_DIR}/bin}" +export REDIS_CONF_FILE="${REDIS_CONF_DIR}/redis.conf" + +# Users +export REDIS_DAEMON_USER="${REDIS_DAEMON_USER:-${APP_USER}}" +export REDIS_DAEMON_GROUP="${REDIS_DAEMON_GROUP:-${APP_GROUP}}" + +# Redis settings +export REDIS_PORT="${REDIS_PORT:-6379}" +export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" +export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" + +# Cluster configuration +export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}" +export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-}" +export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}" + +export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" +export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" +export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" +export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" + +# Redis TLS Settings +export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" +export REDIS_TLS_PORT="${REDIS_TLS_PORT:-6379}" +export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" +export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" +export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" +export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" +export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" + +# Authentication +export REDIS_ALLOW_EMPTY_PASSWORD="${REDIS_ALLOW_EMPTY_PASSWORD:-no}" +export REDIS_PASSWORD="${REDIS_PASSWORD:-}" +EOF + + if [[ -f "${REDIS_PASSWORD_FILE:-}" ]]; then + cat <<"EOF" +export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" +EOF + fi + if [[ -f "${REDIS_MASTER_PASSWORD_FILE:-}" ]]; then + cat <<"EOF" +export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" +EOF + fi +} + +# 将变量配置更新至配置文件 +# 参数: +# $1 - 文件 +# $2 - 变量 +# $3 - 值(列表) +redis_common_conf_set() { + local file="${1:?missing file}" + local key="${2:?missing key}" + shift + shift + local values=("$@") + + if [[ "${#values[@]}" -eq 0 ]]; then + LOG_E "missing value" + return 1 + elif [[ "${#values[@]}" -ne 1 ]]; then + for i in "${!values[@]}"; do + redis_common_conf_set "$file" "${key[$i]}" "${values[$i]}" + done + else + value="${values[0]}" + # Sanitize inputs + value="${value//\\/\\\\}" + value="${value//&/\\&}" + value="${value//\?/\\?}" + [[ "$value" = "" ]] && value="\"$value\"" + # Check if the value was set before + if grep -q "^${key} .*" "$file"; then + # Update the existing key + replace_in_file "$file" "^${key} .*" "${key} ${value}" false + else + # Add a new key + printf '\n%s %s' "$key" "$value" >>"$file" + fi + fi +} + +# 获取配置文件中指定关键字对应的值 +# 全局变量: +# APP_CONF_DIR +# 变量: +# $1 - 变量 +redis_conf_get() { + local key="${1:?missing key}" + + grep -E "^\s*$key " "${REDIS_CONF_DIR}/redis.conf" | awk '{print $2}' +} + +# 更新 redis.conf 配置文件中指定变量值,设置关键字及对应值 +# 全局变量: +# APP_CONF_DIR +# 变量: +# $1 - 变量 +# $2 - 值(列表) +redis_conf_set() { + redis_common_conf_set "${REDIS_CONF_DIR}/redis.conf" "$@" +} + +# 更新 sentinel.conf 配置文件中指定变量值,设置关键字及对应值 +# 全局变量: +# APP_CONF_DIR +# 变量: +# $1 - 变量 +# $2 - 值(列表) +redis_sentinel_conf_set() { + redis_common_conf_set "${REDIS_CONF_DIR}/sentinel.conf" "$@" +} + +# 更新 redis.conf 配置文件中指定变量值,取消关键字设置信息 +# 全局变量: +# APP_CONF_DIR +# 变量: +# $1 - 变量 +redis_conf_unset() { + local key="${1:?missing key}" + remove_in_file "${REDIS_CONF_DIR}/redis.conf" "^\s*$key .*" false +} + +# 获取 Redis 版本信息 +# 返回值: +# Redis 版本号 +redis_version() { + redis-cli --version | grep -E -o "[0-9]+.[0-9]+.[0-9]+" +} + +# 获取 Redis 主版本号 +# 返回值: +# Redis 主版本号 +redis_major_version() { + redis_version | grep -E -o "^[0-9]+" +} + +# 检测用户参数信息是否满足条件;针对部分权限过于开放情况,打印提示信息 +# 全局变量: +# REDIS_* +app_verify_minimum_env() { + local error_code=0 + LOG_D "Validating settings in REDIS_* env vars..." + + # Auxiliary functions + print_validation_error() { + LOG_E "$1" + error_code=1 + } + + # Redis authentication validations + if is_boolean_yes "$REDIS_ALLOW_EMPTY_PASSWORD"; then + LOG_W "You set the environment variable REDIS_ALLOW_EMPTY_PASSWORD=${REDIS_ALLOW_EMPTY_PASSWORD}. For safety reasons, do not use this flag in a production environment." + elif [[ -z "$REDIS_PASSWORD" ]]; then + print_validation_error "The REDIS_PASSWORD environment variable is empty or not set. Set the environment variable REDIS_ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development." + fi + + if [[ -n "$REDIS_REPLICATION_MODE" ]]; then + if [[ "$REDIS_REPLICATION_MODE" =~ ^(slave|replica)$ ]]; then + if [[ -n "$REDIS_MASTER_PORT_NUMBER" ]]; then + if ! err=$(validate_port "$REDIS_MASTER_PORT_NUMBER"); then + print_validation_error "An invalid port was specified in the environment variable REDIS_MASTER_PORT_NUMBER: $err" + fi + fi + if ! is_boolean_yes "$REDIS_ALLOW_EMPTY_PASSWORD" && [[ -z "$REDIS_MASTER_PASSWORD" ]]; then + print_validation_error "The REDIS_MASTER_PASSWORD environment variable is empty or not set. Set the environment variable REDIS_ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development." + fi + elif [[ "$REDIS_REPLICATION_MODE" != "master" ]]; then + print_validation_error "Invalid replication mode. Available options are 'master/replica'" + fi + fi + + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + if [[ "$REDIS_PORT" == "$REDIS_TLS_PORT" ]] && [[ "$REDIS_PORT" != "6379" ]]; then + # If both ports are assigned the same numbers and they are different to the default settings + print_validation_error "Enviroment variables REDIS_PORT and REDIS_TLS_PORT point to the same port number (${REDIS_PORT}). Change one of them or disable non-TLS traffic by setting REDIS_PORT=0" + fi + if [[ -z "$REDIS_TLS_CERT_FILE" ]]; then + print_validation_error "You must provide a X.509 certificate in order to use TLS" + elif [[ ! -f "$REDIS_TLS_CERT_FILE" ]]; then + print_validation_error "The X.509 certificate file in the specified path ${REDIS_TLS_CERT_FILE} does not exist" + fi + if [[ -z "$REDIS_TLS_KEY_FILE" ]]; then + print_validation_error "You must provide a private key in order to use TLS" + elif [[ ! -f "$REDIS_TLS_KEY_FILE" ]]; then + print_validation_error "The private key file in the specified path ${REDIS_TLS_KEY_FILE} does not exist" + fi + if [[ -z "$REDIS_TLS_CA_FILE" ]]; then + print_validation_error "You must provide a CA X.509 certificate in order to use TLS" + elif [[ ! -f "$REDIS_TLS_CA_FILE" ]]; then + print_validation_error "The CA X.509 certificate file in the specified path ${REDIS_TLS_CA_FILE} does not exist" + fi + if [[ -n "$REDIS_TLS_DH_PARAMS_FILE" ]] && [[ ! -f "$REDIS_TLS_DH_PARAMS_FILE" ]]; then + print_validation_error "The DH param file in the specified path ${REDIS_TLS_DH_PARAMS_FILE} does not exist" + fi + fi + + [[ "$error_code" -eq 0 ]] || exit "$error_code" +} + +# 加载在后续脚本命令中使用的参数信息,包括从"*_FILE"文件中导入的配置 +# 必须在其他函数使用前调用 +docker_setup_env() { + # 尝试从文件获取环境变量的值 + # file_env 'ENV_VAR_NAME' + + # 尝试从文件获取环境变量的值,如果不存在,使用默认值 default_val + # file_env 'ENV_VAR_NAME' 'default_val' + + # 检测变量 ENV_VAR_NAME 未定义或值为空,赋值为默认值:default_val + # : "${ENV_VAR_NAME:=default_val}" + : +} + +# 禁用 Redis 不安全的命令 +# Globals: +# REDIS_BASEDIR +# 参数: +# $1 - 待禁用的命令列表 +redis_disable_unsafe_commands() { + # The current syntax gets a comma separated list of commands, we split them + # before passing to redis_disable_unsafe_commands + read -r -a disabledCommands <<< "$(tr ',' ' ' <<< "$REDIS_DISABLE_COMMANDS")" + LOG_D "Disabling commands: ${disabledCommands[*]}" + for cmd in "${disabledCommands[@]}"; do + if grep -E -q "^\s*rename-command\s+$cmd\s+\"\"\s*$" "${REDIS_CONF_FILE}"; then + LOG_D "$cmd was already disabled" + continue + fi + echo "rename-command $cmd \"\"" >> "${REDIS_CONF_FILE}" + done +} + +# 生成默认配置文件 +# 全局变量: +# REDIS_* +redis_generate_conf() { + redis_conf_set port "$REDIS_PORT" + redis_conf_set dir "${REDIS_DATA_DIR}" + redis_conf_set logfile "${REDIS_LOG_DIR}/redis.log" # Log to stdout + redis_conf_set pidfile "${APP_RUN_DIR}/redis_6379.pid" + redis_conf_set daemonize no + redis_conf_set bind 0.0.0.0 # Allow remote connections + # Enable AOF https://redis.io/topics/persistence#append-only-file + # Leave default fsync (every second) + redis_conf_set appendonly "${REDIS_AOF_ENABLED}" + # Disable RDB persistence, AOF persistence already enabled. + # Ref: https://redis.io/topics/persistence#interactions-between-aof-and-rdb-persistence + redis_conf_set save "" + # TLS configuration + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + if [[ "$REDIS_PORT" == "6379" ]] && [[ "$REDIS_TLS_PORT" == "6379" ]]; then + # If both ports are set to default values, enable TLS traffic only + redis_conf_set port 0 + redis_conf_set tls-port "$REDIS_TLS_PORT" + else + # Different ports were specified + redis_conf_set port "$REDIS_PORT" + redis_conf_set tls-port "$REDIS_TLS_PORT" + fi + redis_conf_set tls-cert-file "$REDIS_TLS_CERT_FILE" + redis_conf_set tls-key-file "$REDIS_TLS_KEY_FILE" + redis_conf_set tls-ca-cert-file "$REDIS_TLS_CA_FILE" + [[ -n "$REDIS_TLS_DH_PARAMS_FILE" ]] && redis_conf_set tls-dh-params-file "$REDIS_TLS_DH_PARAMS_FILE" + redis_conf_set tls-auth-clients "$REDIS_TLS_AUTH_CLIENTS" + fi + + if [[ -n "$REDIS_PASSWORD" ]]; then + redis_conf_set requirepass "$REDIS_PASSWORD" + else + redis_conf_unset requirepass + fi + if [[ -n "$REDIS_DISABLE_COMMANDS" ]]; then + redis_disable_unsafe_commands + fi +} + +# 配置 Redis 复制模式参数 +# 全局变量: +# REDIS_* +# 参数: +# $1 - 复制模式 +redis_configure_replication() { + LOG_I "Configuring replication mode..." + + redis_conf_set replica-announce-ip "$(get_machine_ip)" + redis_conf_set replica-announce-port "$REDIS_MASTER_PORT_NUMBER" + if [[ "$REDIS_REPLICATION_MODE" = "master" ]]; then + if [[ -n "$REDIS_PASSWORD" ]]; then + redis_conf_set masterauth "$REDIS_PASSWORD" + fi + elif [[ "$REDIS_REPLICATION_MODE" =~ ^(slave|replica)$ ]]; then + if [[ -n "$REDIS_SENTINEL_HOST" ]]; then + local sentinel_info_command + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + sentinel_info_command="redis-cli -h ${REDIS_SENTINEL_HOST} -p ${REDIS_SENTINEL_PORT_NUMBER} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name ${REDIS_SENTINEL_MASTER_NAME}" + else + sentinel_info_command="redis-cli -h ${REDIS_SENTINEL_HOST} -p ${REDIS_SENTINEL_PORT_NUMBER} sentinel get-master-addr-by-name ${REDIS_SENTINEL_MASTER_NAME}" + fi + REDIS_SENTINEL_INFO=($($sentinel_info_command)) + REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} + REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} + fi + LOG_I "Waitting for Redis Master ready..." + wait-for-port --host "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" + [[ -n "$REDIS_MASTER_PASSWORD" ]] && redis_conf_set masterauth "$REDIS_MASTER_PASSWORD" + # Starting with Redis 5, use 'replicaof' instead of 'slaveof'. Maintaining both for backward compatibility + local parameter="replicaof" + [[ $(redis_major_version) -lt 5 ]] && parameter="slaveof" + redis_conf_set "$parameter" "$REDIS_MASTER_HOST $REDIS_MASTER_PORT_NUMBER" + # Configure replicas to use TLS for outgoing connections to the master + if is_boolean_yes "$REDIS_TLS_ENABLED"; then + redis_conf_set tls-replication yes + fi + fi +} + +# 检测 Redis 服务是否在运行中 +# 全局变量: +# APP_RUN_DIR +# 返回值: +# 布尔值 +######################### +is_redis_running() { + local pid + pid="$(get_pid_from_file "$APP_RUN_DIR/redis_6379.pid")" + + if [[ -z "$pid" ]]; then + false + else + is_service_running "$pid" + fi +} + +# 以后台方式启动 Redis 服务,并等待启动就绪 +# 全局变量: +# REDIS_* +redis_start_server_bg() { + is_redis_running && return + debug "Starting Redis..." + if _is_run_as_root; then + gosu "$REDIS_DAEMON_USER" "redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes" + else + "redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes" + fi + local counter=3 + while ! is_redis_running ; do + if [[ "$counter" -ne 0 ]]; then + break + fi + sleep 1; + counter=$((counter - 1)) + done + + # 检测端口是否就绪 + # wait-for-port --timeout 60 "$REDIS_PORT_NUMBER" +} + +# 停止 Redis 后台服务 +# 全局变量: +# ENV_DEBUG +redis_stop_server() { + local pass + local port + local args + + ! is_redis_running && return + pass="$(redis_conf_get "requirepass")" + is_boolean_yes "$REDIS_TLS_ENABLED" && port="$(redis_conf_get "tls-port")" || port="$(redis_conf_get "port")" + + [[ -n "$pass" ]] && args+=("-a" "\"$pass\"") + [[ "$port" != "0" ]] && args+=("-p" "$port") + #args+=("--daemonize" "yes") + + debug "Stopping Redis..." + if _is_run_as_root; then + gosu "$REDIS_DAEMON_USER" "redis-cli" "${args[@]}" shutdown + else + "redis-cli" "${args[@]}" shutdown + fi + local counter=5 + while is_redis_running ; do + if [[ "$counter" -ne 0 ]]; then + break + fi + sleep 1; + counter=$((counter - 1)) + done +} + +# 应用默认初始化操作 +# 执行完毕后,会在 ${REDIS_DATA_DIR} 目录中生成 app_init_flag 及 data_init_flag 文件 +docker_app_init() { + LOG_D "Check init status of ${APP_NAME}..." + + # 检测配置文件是否存在 + if [[ ! -f "$REDIS_CONF_FILE" || ! -f "${REDIS_DATA_DIR}/app_init_flag" ]]; then + LOG_I "No injected configuration file found, creating default config files..." + redis_generate_conf + + # Configure Replication mode + if [[ -n "$REDIS_REPLICATION_MODE" ]]; then + redis_configure_replication + fi + + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." > ${REDIS_DATA_DIR}/app_init_flag + else + LOG_I "User injected custom configuration detected!" + fi + + if is_dir_empty "$REDIS_DATA_DIR" || [[ ! -f "${REDIS_DATA_DIR}/data_init_flag" ]]; then + LOG_I "Deploying ${APP_NAME} from scratch..." + + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." > ${REDIS_DATA_DIR}/data_init_flag + else + LOG_I "Deploying ${APP_NAME} with persisted data..." + fi +} + +# 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 +# 执行完毕后,会在 ${REDIS_DATA_DIR} 目录中生成 custom_init_flag 文件 +docker_custom_init() { + # 检测用户配置文件目录是否存在initdb.d文件夹,如果存在,尝试执行目录中的初始化脚本 + if [ -d "${REDIS_CONF_DIR}/initdb.d" ]; then + # 检测数据存储目录是否存在已初始化标志文件;如果不存在,进行初始化操作 + if [ ! -f "${REDIS_DATA_DIR}/custom_init_flag" ]; then + LOG_I "Process custom init scripts for ${APP_NAME}..." + + # 检测目录权限,防止初始化失败 + ls "${REDIS_CONF_DIR}/initdb.d/" > /dev/null + + docker_process_init_files ${REDIS_CONF_DIR}/initdb.d/* + + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." > ${REDIS_DATA_DIR}/custom_init_flag + LOG_I "Custom init for ${APP_NAME} complete." + else + LOG_I "Custom init for ${APP_NAME} already done before, skipping initialization." + fi + fi +} diff --git a/5.0/prebuilds/usr/local/bin/entrypoint.sh b/5.0/prebuilds/usr/local/bin/entrypoint.sh new file mode 100644 index 0000000..d9978db --- /dev/null +++ b/5.0/prebuilds/usr/local/bin/entrypoint.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +# 容器入口脚本 + +set -o errexit +set -o nounset +set -o pipefail +# set -o xtrace # Uncomment this line for debugging purpose + +# 加载依赖脚本 +. /usr/local/scripts/liblog.sh +. /usr/local/scripts/libcommon.sh + +. /usr/local/bin/appcommon.sh + +APP_DIRS="${APP_DEF_DIR:-} ${APP_HOME_DIR:-} ${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_CACHE_DIR:-} ${APP_RUN_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_WWW_DIR:-} ${APP_DATA_LOG_DIR:-}"; \ + +# 加载环境变量, docker_app_env()函数在文件 app-common.sh 中定义 +eval "$(docker_app_env)" + +# 打印镜像欢迎信息 +docker_print_welcome + +# 检测数据卷,创建默认的关联目录,并拷贝所必须的默认配置文件及初始化文件 +docker_ensure_dir_and_configs() { + local user_id; user_id="$(id -u)" + + for dir in ${APP_DIRS}; do + LOG_D "Check directory $dir" + ensure_dir_exists "$dir" + done + + # 检测指定文件是否在配置文件存储目录存在,如果不存在则拷贝(新挂载数据卷、手动删除都会导致不存在) + LOG_D "Check config files" + if ! is_dir_empty ${APP_DEF_DIR}; then + ensure_config_file_exist ${APP_DEF_DIR}/* + fi +} + +_main() { + # 如果命令行参数是以配置参数("-")开始,修改执行命令,确保使用可执行应用命令启动服务器 + if [ "${1:0:1}" = '-' ]; then + set -- "${APP_EXEC}" "$@" + fi + + # 命令行参数以可执行应用命令起始,且不包含直接返回的命令(如:-V、--version、--help)时,执行初始化操作 + if [ "$1" = "${APP_EXEC}" ] && ! docker_command_help "$@"; then + # docker_setup_env + + # 检测 ENV_* REDIS_* 环境变量是否有效 + app_verify_minimum_env + + # 检测应用需要使用的目录是否存在,并设置相应用户权限 + docker_ensure_dir_and_configs + + # 以root用户运行时,会使用gosu重新以"APP_USER"用户运行当前脚本 + LOG_D "Check if run as root" + if _is_run_as_root; then + LOG_D "Change permissions when run as root" + + # 以root用户启动时,修改相应目录的所属用户信息为APP_USER,确保切换用户时,权限正常 + for dir in ${APP_DIRS}; do + LOG_D "Change ownership and permissions of $dir" + configure_permissions_ownership "$dir" -f 755 -d 755 -u "${APP_USER}" + done + + # 解决使用gosu后,nginx: [emerg] open() "/dev/stdout" failed (13: Permission denied) + LOG_D "Change permissions of stdout/stderr to 0622" + chmod 0622 /dev/stdout /dev/stderr + + LOG_I "Restart container with default user: ${APP_USER}" + exec gosu "${APP_USER}" "$0" "$@" + fi + + # 执行应用初始化操作 + docker_app_init + + # 执行用户自定义初始化脚本 + docker_custom_init + fi + + LOG_I "Start container with: $@" + # 执行命令行 + exec "$@" +} + +# 脚本入口命令 +if ! _is_sourced; then + _main "$@" +fi diff --git a/5.0/prebuilds/usr/local/license/LICENSE b/5.0/prebuilds/usr/local/license/LICENSE new file mode 100644 index 0000000..80e3bb7 --- /dev/null +++ b/5.0/prebuilds/usr/local/license/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Endial Fang (endial@126.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/5.0/prebuilds/usr/local/overrides/overrides-5.0.8.sh b/5.0/prebuilds/usr/local/overrides/overrides-5.0.8.sh new file mode 100644 index 0000000..faa75eb --- /dev/null +++ b/5.0/prebuilds/usr/local/overrides/overrides-5.0.8.sh @@ -0,0 +1,17 @@ +#!/bin/bash -e + +# 在安装完应用后,使用该脚本修改默认配置文件中部分配置项 +# 如果相应的配置项已经定义整体环境变量,则不需要在这里修改 +echo "Process overrides for default configs..." +#sed -i -E 's/^listeners=/d' "$KAFKA_HOME/config/server.properties" + +# 修改默认配置信息 +sed -i -E 's/^bind .*/bind 0.0.0.0/g' "$APP_DEF_DIR/redis.conf" +sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis_6379.pid/g' "$APP_DEF_DIR/redis.conf" +sed -i -E 's/^daemonize .*/daemonize no/g' "$APP_DEF_DIR/redis.conf" +sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis.log\"/g' "$APP_DEF_DIR/redis.conf" + +# 修改 Sentinel 默认配置信息 +sed -i -E 's/^daemonize .*/daemonize yes/g' "$APP_DEF_DIR/sentinel.conf" +sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "$APP_DEF_DIR/sentinel.conf" +sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis-sentinel.log\"/g' "$APP_DEF_DIR/sentinel.conf" diff --git a/5.0/prebuilds/usr/local/scripts/libcommon.sh b/5.0/prebuilds/usr/local/scripts/libcommon.sh new file mode 100644 index 0000000..d514df5 --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libcommon.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# + +# shellcheck disable=SC1091 + +BOLD='\033[1m' + +# 加载依赖项 +. /usr/local/scripts/liblog.sh + +# 函数列表 + +# 打印包含包含Logo的欢迎信息 +# 全局变量: +# APP_NAME +print_image_welcome_page() { + local github_url="https://github.com/colovu/docker-${APP_NAME}" + if [ x"${WELCOME_MESSAGE:-}" = "x" ]; then + LOG_I "" + LOG_I " ######## ######## ### ######## ### ## ### ##" + LOG_I " ### ## ### ## ### ### ## ### ## ### ##" + LOG_I " ### ### ## ### ### ## ### ## ### ##" + LOG_I " ### ### ## ### ### ## ### ## ### ##" + LOG_I " ### ### ## ### ### ## ### ## ### ##" + LOG_I " ### ## ### ## ### ### ## #### ### ##" + LOG_I "######## ######## ######## ######## ## ########" + LOG_I "" + LOG_I "Welcome to the ${BOLD}${APP_NAME}${RESET} container" + LOG_I "Project on Github: ${BOLD}${github_url}${RESET}" + LOG_I "Send us your feedback at ${BOLD}endial@126.com${RESET}" + LOG_I "" + + export WELCOME_MESSAGE=1 + fi +} + +# 根据需要打印欢迎信息 +# 全局变量: +# ENV_DISABLE_WELCOME_MESSAGE +# APP_NAME +docker_print_welcome() { + if [[ -z "${ENV_DISABLE_WELCOME_MESSAGE:-}" ]]; then + if [[ -n "$APP_NAME" ]]; then + print_image_welcome_page + fi + fi +} + +# 检测可能导致容器执行后直接退出的命令,如"--help";如果存在,直接返回 0 +# 参数: +# $1 - 待检测的参数表 +docker_command_help() { + local arg + for arg; do + case "$arg" in + -'?'|--help|-V|--version) + return 0 + ;; + esac + done + return 1 +} + +# 根据脚本扩展名及权限,执行相应的初始化脚本 +# 参数: +# $1 - 文件列表,支持路径通配符 +# 使用: +# docker_process_init_files [file [file [...]]] +# 例子: +# docker_process_init_files /src/conf/${APP_NAME}/initdb.d/* +docker_process_init_files() { + echo + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + LOG_I "$0: running $f" + "$f" + else + LOG_I "$0: sourcing $f" + . "$f" + fi + ;; + *) LOG_W "$0: ignoring $f" ;; + esac + echo + done +} + +# 检测应用相应的配置文件是否存在,如果不存在,则从默认配置文件目录拷贝一份 +# 默认配置文件路径:/etc/${APP_NAME} +# 目标配置文件路径:/srv/conf/${APP_NAME} +# 参数: +# $* - 文件及目录列表字符串,以" "分割 +# 例子: +# ensure_config_file_exist /etc/${APP_NAME}/* +ensure_config_file_exist() { + local f + + LOG_D "Parameter: $@" + while [ "$#" -gt 0 ]; do + f="${1}" + LOG_D "Process ${f}" + if [ -d ${f} ]; then + dist="$(echo ${f} | sed -e 's/\/etc/\/srv\/conf/g')" + [ ! -d "${dist}" ] && LOG_I "Create directory: ${dist}" && mkdir -p "${dist}" + [[ ! -z $(ls -A "$f") ]] && ensure_config_file_exist ${f}/* + else + dist="$(echo ${f} | sed -e 's/\/etc/\/srv\/conf/g')" + [ ! -e "${dist}" ] && LOG_I "Copy: ${f} ===> ${dist}" && cp "${f}" "${dist}" + fi + shift + done +} + +# 检测当前用户是否为 root +# 返回值: +# 布尔值 +_is_run_as_root() { + if [[ "$(id -u)" = "0" ]]; then + LOG_D "Run as root" + true + else + LOG_D "User id: $(id -u)" + false + fi +} + +# 检测当前脚本是被直接执行的,还是从其他脚本中使用 "source" 调用的 +_is_sourced() { + [ "${#FUNCNAME[@]}" -ge 2 ] \ + && [ "${FUNCNAME[0]}" = '_is_sourced' ] \ + && [ "${FUNCNAME[1]}" = 'source' ] +} diff --git a/5.0/prebuilds/usr/local/scripts/libdownload.sh b/5.0/prebuilds/usr/local/scripts/libdownload.sh new file mode 100644 index 0000000..7c79454 --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libdownload.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# +# 从服务器(列表)下载相应软件包 + +# Constants +#CV_BASE="http://archive.colovu.com/dist-files/" +#CV_BASE="http://10.37.129.2/dist-files/" +CV_BASE="" + +# 检测软件包签名是否正确 +# 参数: +# $1 - 软件包签名文件 +# $2 - 软件包文件 +# $3 - PGPKEY +check_pgp() { + local name_asc=${1:?missing asc file name} + local name=${2:?missing file name} + local keys="${3:?missing key id}" + + GNUPGHOME="$(mktemp -d)" + for key in $keys; do + gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "${key}" || + gpg --batch --keyserver pgp.mit.edu --recv-keys "${key}" || + gpg --batch --keyserver keys.gnupg.net --recv-keys "${key}" || + gpg --batch --keyserver keyserver.pgp.com --recv-keys "${key}"; + done + gpg --batch --verify "$name_asc" "$name" + command -v gpgconf > /dev/null && gpgconf --kill all + rm -rf "$GNUPGHOME" "$name_asc" +} + +# 从私有服务器下载软件包,如果不存在,则从官网服务器下载 +# 参数: +# $1 - 软件包全名(字符串) +# $2 - 官网路径(字符串) +# $3 - "-c"/"--checksum" +# $4 - 软件包SHA256值 +# $3 - "-g"/"--pgpkey" +# $4 - 用于软件包签名的KEY ID +# 例子: +# . /usr/local/scripts/libdownload.sh && download_dist "java" "11.0.7-0" --checksum 02a1fc9b79b11617ad39221667f6a34209f5c45ca908268f8ba6c264a2577ee2 +download_dist() { + local name="${1:?name is required}" + local base_urls="${2:?url is required}" + local package_sha256="" + local pgp_key="" + local success="" + + # 获取SHA256或PGP KEY + shift 2 + while [ "$#" -gt 0 ]; do + case "$1" in + -c|--checksum) + shift + package_sha256="${1:?missing package checksum}" + ;; + -g|--pgpkey) + shift + pgp_key="${1:?missing package PGP key}" + ;; + *) + echo "Invalid command line flag $1" >&2 + return 1 + ;; + esac + shift + done + + echo "Downloading $name package" + for url in $CV_BASE $base_urls; do + if wget -O "$name" "$url$name" && [ -s "$name" ]; then + if [ -n "$pgp_key" ]; then + wget -O "$name.asc" "$url$name.asc" + if [ ! -e "$name.asc" ]; then + wget -O "$name.asc" "$url$name.sig" + fi + fi + success=1 + break + fi + done + + if [ -n "$success" ]; then + if [ -n "$package_sha256" ]; then + echo "Verifying package whith sha256" + echo "$package_sha256 *${name}" | sha256sum --check - + fi + + if [ -n "$pgp_key" ]; then + echo "Verifying package with PGP" + check_pgp "$name.asc" "$name" "$pgp_key" + fi + else + [ -n "$success" ] + fi +} diff --git a/5.0/prebuilds/usr/local/scripts/libfile.sh b/5.0/prebuilds/usr/local/scripts/libfile.sh new file mode 100644 index 0000000..9da26fa --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libfile.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# +# 文件操作函数库 + +# 函数列表 + +# 检测"*_FILE"文件,并从文件中读取信息作为参数值;环境变量不允许 VAR 与 VAR_FILE 方式并存 +# 变量: +# $1 - 需要设置的环境变量名称 +# $2 - 该变量对应的默认值(Option) +# +# 使用: file_env ENV_VAR [DEFAULT] +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + LOG_E "Both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# 使用规则表达式在文件中替换数据 +# 参数: +# $1 - 文件名 +# $2 - 正则表达式 +# $3 - 替代数据表达式 +# $4 - 是否使用POSIX表达式. Default: true +replace_in_file() { + local filename="${1:?filename is required}" + local match_regex="${2:?match regex is required}" + local substitute_regex="${3:?substitute regex is required}" + local posix_regex=${4:-true} + + local result + + # 因部分系统兼容性问题,需要防止使用 'sed in-place' 方式操作 + if [[ $posix_regex = true ]]; then + result="$(sed -E "s@$match_regex@$substitute_regex@g" "$filename")" + else + result="$(sed "s@$match_regex@$substitute_regex@g" "$filename")" + fi + echo "$result" > "$filename" +} + +# 使用规则表达式在文件中删除数据 +# 参数: +# $1 - 文件名 +# $2 - 正则表达式 +# $3 - 是否使用POSIX表达式. Default: true +remove_in_file() { + local filename="${1:?filename is required}" + local match_regex="${2:?match regex is required}" + local posix_regex=${3:-true} + local result + + # 因部分系统兼容性问题,需要防止使用 'sed in-place' 方式操作 + if [[ $posix_regex = true ]]; then + result="$(sed -E "/$match_regex/d" "$filename")" + else + result="$(sed "/$match_regex/d" "$filename")" + fi + echo "$result" > "$filename" +} diff --git a/5.0/prebuilds/usr/local/scripts/libfs.sh b/5.0/prebuilds/usr/local/scripts/libfs.sh new file mode 100644 index 0000000..2ab7c7d --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libfs.sh @@ -0,0 +1,119 @@ +#!/bin/bash +# +# 文件管理函数库 + +# 加载依赖项 +. /usr/local/scripts/liblog.sh + +# 函数列表 + +# Ensure a file/directory is owned (user and group) but the given user +# Arguments: +# $1 - filepath +# $2 - owner +ensure_owned_by() { + local path="${1:?path is missing}" + local owner="${2:?owner is missing}" + + chown "$owner":"$owner" "$path" +} + +# 检测目录是否存在,如果不存在则创建,同时修改为指定的用户 +# Arguments: +# $1 - directory +# $2 - owner +ensure_dir_exists() { + local dir="${1:?directory is missing}" + local owner="${2:-}" + + mkdir -p "${dir}" + if [[ -n $owner ]]; then + ensure_owned_by "$dir" "$owner" + fi +} + +# 检测目录是否存在或为空 +# 参数: +# $1 - 目录路径 +# 返回值: +# 布尔值 +is_dir_empty() { + local dir="${1:?missing directory}" + + if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then + true + else + false + fi +} + +# 循环设置目录中子目录及文件权限 +# 参数: +# $1 - paths (as a string). +# Flags: +# -f|--file-mode - 文件权限模式 +# -d|--dir-mode - 目录权限模式 +# -u|--user - 用户 +# -g|--group - 用户组 +configure_permissions_ownership() { + local -r paths="${1:?paths is missing}" + local dir_mode="" + local file_mode="" + local user="" + local group="" + + # Validate arguments + shift 1 + while [ "$#" -gt 0 ]; do + case "$1" in + -f|--file-mode) + shift + file_mode="${1:?missing mode for files}" + ;; + -d|--dir-mode) + shift + dir_mode="${1:?missing mode for directories}" + ;; + -u|--user) + shift + user="${1:?missing user}" + ;; + -g|--group) + shift + group="${1:?missing group}" + ;; + *) + LOG_E "Invalid command line flag $1" >&2 + return 1 + ;; + esac + shift + done + + read -r -a filepaths <<< "$paths" + for p in "${filepaths[@]}"; do + if [[ -e "$p" ]]; then + LOG_D "Check directory $p" + if [[ -n $dir_mode ]]; then + LOG_D "Change permissions to 755 of directories in $p" + find -L "$p" -type d -exec chmod "$dir_mode" '{}' + + fi + if [[ -n $file_mode ]]; then + LOG_D "Change permissions to 755 of files in $p" + find -L "$p" -type f -exec chmod "$file_mode" '{}' + + fi + if [[ -n $user ]] && [[ -n $group ]]; then + LOG_D "Change ownership to ${user}:${group} of files and directories in $p" + find -L "$p" \! -user ${user} -or \! -group ${group} -exec chown -L "$user":"$group" '{}' + + elif [[ -n $user ]] && [[ -z $group ]]; then + LOG_D "Change user to ${user} of files and directories in $p" + find -L "$p" \! -user ${user} -exec chown -L "$user" '{}' + + elif [[ -z $user ]] && [[ -n $group ]]; then + LOG_D "Change groupto ${group} of files and directories in $p" + find -L "$p" \! -group ${group} -exec chgrp -L "$group" '{}' + + fi + else + LOG_E "$p does not exist" + fi + done +} \ No newline at end of file diff --git a/5.0/prebuilds/usr/local/scripts/liblog.sh b/5.0/prebuilds/usr/local/scripts/liblog.sh new file mode 100644 index 0000000..8901e8c --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/liblog.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# +# 日志处理函数库 + +# 定义颜色信息 +RESET='\033[0m' +RED='\033[31;1m' +GREEN='\033[32;2m' +YELLOW='\033[33;1m' +MAGENTA='\033[36;2m' +CYAN='\033[35;2m' +BLUE='\033[34;2m' + +# 函数列表 + +# 输出实际日志信息 +# 参数: +# $1 - 日志类型 +# $2 - 日志信息 +LOG_RAW() { + local type="$1"; shift + case "${type}" in + x) printf "${CYAN}${APP_NAME:-} ${MAGENTA}%s ${RESET}${BLUE}DEBUG${RESET} %b\n" "$(date "+%T.%2N")" "${*}" ;; + I) printf "${CYAN}${APP_NAME:-} ${MAGENTA}%s ${RESET}${GREEN}INFO ${RESET} %b\n" "$(date "+%T.%2N")" "${*}";; + W) printf "${CYAN}${APP_NAME:-} ${MAGENTA}%s ${RESET}${YELLOW}WARN ${RESET} %b\n" "$(date "+%T.%2N")" "${*}";; + E) printf "${CYAN}${APP_NAME:-} ${MAGENTA}%s ${RESET}${RED}ERROR${RESET} %b\n" "$(date "+%T.%2N")" "${*}";; + esac +} + +# 输出调试类日志信息,尽量少使用 +# 参数: +# $1 - 日志类型 +# $2 - 日志信息 +LOG_D() { + local -r bool="${ENV_DEBUG:-false}" + shopt -s nocasematch + if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then + LOG_RAW x "$@" + fi +} + +# 输出提示信息类日志信息 +# 参数: +# $1 - 日志类型 +# $2 - 日志信息 +LOG_I() { + shopt -s nocasematch + LOG_RAW I "$@" +} + +# 输出警告类日志信息至sterr +# 参数: +# $1 - 日志类型 +# $2 - 日志信息 +LOG_W() { + LOG_RAW W "$@" >&2 +} + +# 输出错误类日志信息至sterr,并退出脚本 +# 参数: +# $1 - 日志类型 +# $2 - 日志信息 +LOG_E() { + LOG_RAW E "$@" >&2 +} diff --git a/5.0/prebuilds/usr/local/scripts/libnet.sh b/5.0/prebuilds/usr/local/scripts/libnet.sh new file mode 100644 index 0000000..be3c1ff --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libnet.sh @@ -0,0 +1,119 @@ +#!/bin/bash +# +# 网络管理函数库 + +# shellcheck disable=SC1091 + +# 加载依赖项 +. /usr/local/scripts/liblog.sh + +# 函数列表 + +# 解析主机名为 IP +# 参数: +# $1 - 待解析的主机名 +# 返回值: +# IP 地址 +######################### +dns_lookup() { + local host="${1:?host is missing}" + getent ahosts "$host" | awk '/STREAM/ {print $1 }' +} + +# 等待主机名解析,并返回 IP +# 参数: +# $1 - 主机名 +# $2 - 重试次数 +# $3 - 重试间隔(秒) +# 返回值: +# - IP 地址 +wait_for_dns_lookup() { + local hostname="${1:?hostname is missing}" + local retries="${2:-5}" + local seconds="${3:-1}" + check_host() { + if [[ $(dns_lookup "$hostname") == "" ]]; then + false + else + true + fi + } + # Wait for the host to be ready + retry_while "check_host ${hostname}" "$retries" "$seconds" + dns_lookup "$hostname" +} + +# 获取机器的 IP +# 返回值: +# - IP 地址 +get_machine_ip() { + dns_lookup "$(hostname)" +} + +# 检测提供的参数是否为可解析地址的主机名 +# 参数: +# $1 - 待检测值 +# 返回值: +# 布尔值 +is_hostname_resolved() { + local -r host="${1:?missing value}" + if [[ -n "$(dns_lookup "$host")" ]]; then + true + else + false + fi +} + +# 解析 URL +# 参数: +# $1 - URI 字符串 +# $2 - 待解析参数字符串。有效值 (scheme, authority, userinfo, host, port, path, query or fragment) +# 返回值: +# 字符串 +parse_uri() { + local uri="${1:?uri is missing}" + local component="${2:?component is missing}" + + # Solution based on https://tools.ietf.org/html/rfc3986#appendix-B with + # additional sub-expressions to split authority into userinfo, host and port + # Credits to Patryk Obara (see https://stackoverflow.com/a/45977232/6694969) + local -r URI_REGEX='^(([^:/?#]+):)?(//((([^@/?#]+)@)?([^:/?#]+)(:([0-9]+))?))?(/([^?#]*))?(\?([^#]*))?(#(.*))?' + # || | ||| | | | | | | | | | + # |2 scheme | ||6 userinfo 7 host | 9 port | 11 rpath | 13 query | 15 fragment + # 1 scheme: | |5 userinfo@ 8 :... 10 path 12 ?... 14 #... + # | 4 authority + # 3 //... + local index=0 + case "$component" in + scheme) + index=2 + ;; + authority) + index=4 + ;; + userinfo) + index=6 + ;; + host) + index=7 + ;; + port) + index=9 + ;; + path) + index=10 + ;; + query) + index=13 + ;; + fragment) + index=14 + ;; + *) + stderr_print "unrecognized component $component" + return 1 + ;; + esac + [[ "$uri" =~ $URI_REGEX ]] && echo "${BASH_REMATCH[${index}]}" +} + \ No newline at end of file diff --git a/5.0/prebuilds/usr/local/scripts/libos.sh b/5.0/prebuilds/usr/local/scripts/libos.sh new file mode 100644 index 0000000..680c498 --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libos.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# +# 操作系统控制函数库 + +# shellcheck disable=SC1091 + +# 加载依赖项 +. /usr/local/scripts/liblog.sh + +# 函数列表 + +# 检测指定用户账户是否存在 +# 参数: +# $1 - 用户账户 +# 返回值: +# 布尔值 +user_exists() { + local user="${1:?user is missing}" + id "$user" >/dev/null 2>&1 +} + +# 检测指定用户分组是否存在 +# 参数: +# $1 - 用户组 +# 返回值: +# 布尔值 +group_exists() { + local group="${1:?group is missing}" + getent group "$group" >/dev/null 2>&1 +} + +# 确保用户组存在,如果不存在则创建相应用户组 +# 参数: +# $1 - 用户组 +ensure_group_exists() { + local group="${1:?group is missing}" + + if ! group_exists "$group"; then + groupadd "$group" >/dev/null 2>&1 + fi +} + +# 确保用户组及用户账户存在,如果不存在则创建相应用户组及账户 +# 参数: +# $1 - 用户 +# $2 - 用户组 +ensure_user_exists() { + local user="${1:?user is missing}" + local group="${2:-}" + + if ! user_exists "$user"; then + useradd "$user" >/dev/null 2>&1 + fi + + if [[ -n "$group" ]]; then + ensure_group_exists "$group" + fi + + usermod -a -G "$group" "$user" >/dev/null 2>&1 +} + +# 获取系统可用内存 +# 返回值: +# 内存大小(MB) +get_total_memory() { + echo $(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024)) +} + +# 获取以定量方式描述的内存大小 +# 参数: +# $1 - 内存大小 (可选) +# 返回值: +# 基于定量内存大小的内存大小描述 +get_machine_size() { + local memory="${1:-}" + if [[ -z "$memory" ]]; then + debug "Memory was not specified, detecting available memory automatically" + memory="$(get_total_memory)" + fi + sanitized_memory=$(convert_to_mb "$memory") + if [[ "$sanitized_memory" -gt 26000 ]]; then + echo 2xlarge + elif [[ "$sanitized_memory" -gt 13000 ]]; then + echo xlarge + elif [[ "$sanitized_memory" -gt 6000 ]]; then + echo large + elif [[ "$sanitized_memory" -gt 3000 ]]; then + echo medium + elif [[ "$sanitized_memory" -gt 1500 ]]; then + echo small + else + echo micro + fi +} + +# 获取已定义的所有内存大小描述 +# 返回值: +# 内存大小描述 +get_supported_machine_sizes() { + echo micro small medium large xlarge 2xlarge +} + +# 将以字符串表示的内存大小转换为以MB为单位的内存大小值 (i.e. 2G -> 2048) +# 参数: +# $1 - 内存大小 +# 返回值: +# 内存大小值(以MB为单位) +convert_to_mb() { + local amount="${1:-}" + if [[ $amount =~ ^([0-9]+)(M|G) ]]; then + size="${BASH_REMATCH[1]}" + unit="${BASH_REMATCH[2]}" + if [[ "$unit" = "G" ]]; then + amount="$((size * 1024))" + else + amount="$size" + fi + fi + echo "$amount" +} + +# 如果禁用调试模式,将输出信息重定向至 /dev/null +# 全局变量: +# ENV_DEBUG +# 参数: +# $@ - 待执行的命令 +debug_execute() { + local -r bool="${ENV_DEBUG:-false}" + shopt -s nocasematch + if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then + "$@" >/dev/null 2>&1 + else + "$@" + fi +} + +# 重试执行命令 +# 参数: +# $1 - cmd (as a string) +# $2 - 最大尝试次数. Default: 12 +# $3 - 重试前等待时间(秒). Default: 5 +# 返回值: +# 布尔值 +retry_while() { + local -r cmd="${1:?cmd is missing}" + local -r retries="${2:-12}" + local -r sleep_time="${3:-5}" + local return_value=1 + + read -r -a command <<< "$cmd" + for ((i = 1 ; i <= retries ; i+=1 )); do + "${command[@]}" && return_value=0 && break + sleep "$sleep_time" + done + return $return_value +} + + \ No newline at end of file diff --git a/5.0/prebuilds/usr/local/scripts/libservice.sh b/5.0/prebuilds/usr/local/scripts/libservice.sh new file mode 100644 index 0000000..a4ab489 --- /dev/null +++ b/5.0/prebuilds/usr/local/scripts/libservice.sh @@ -0,0 +1,131 @@ +#!/bin/bash +# +# 服务管理函数库 + +# shellcheck disable=SC1091 + +# Load Generic Libraries +. /usr/local/scripts/libvalidations.sh + +# 函数列表 + +# 获取并返回服务 PID +# 参数: +# $1 - PID 文件 +# 返回值: +# PID +get_pid_from_file() { + local pid_file="${1:?pid file is missing}" + + if [[ -f "$pid_file" ]]; then + if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then + echo "$(< "$pid_file")" + fi + fi +} + +# 检测 PID 对应的服务是否在运行中 +# 参数: +# $1 - PID +# 返回值: +# Boolean +is_service_running() { + local pid="${1:?pid is missing}" + + kill -0 "$pid" 2>/dev/null +} + +# 通过发送信号停止一个指定的服务 +# 参数: +# $1 - PID 文件 +# $2 - 信号 (可选) +stop_service_using_pid() { + local pid_file="${1:?pid file is missing}" + local signal="${2:-}" + local pid + + pid="$(get_pid_from_file "$pid_file")" + [[ -z "$pid" ]] || ! is_service_running "$pid" && return + + if [[ -n "$signal" ]]; then + kill "-${signal}" "$pid" + else + kill "$pid" + fi + + local counter=10 + while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do + sleep 1 + counter=$((counter - 1)) + done +} + +# 为指定的服务生成一个监控配置文件 +# Arguments: +# $1 - 服务名 +# $2 - PID 文件 +# $3 - 启动命令 +# $4 - 停止命令 +# Flags: +# --disabled - Whether to disable the monit configuration +generate_monit_conf() { + local service_name="${1:?service name is missing}" + local pid_file="${2:?pid file is missing}" + local start_command="${3:?start command is missing}" + local stop_command="${4:?stop command is missing}" + local monit_conf_dir="/etc/monit/conf.d" + local disabled="no" + + # Parse optional CLI flags + shift 4 + while [[ "$#" -gt 0 ]]; do + case "$1" in + --disabled) + shift + disabled="$1" + ;; + *) + echo "Invalid command line flag ${1}" >&2 + return 1 + ;; + esac + shift + done + + is_boolean_yes "$disabled" && conf_suffix=".disabled" + mkdir -p "$monit_conf_dir" + cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <"${logrotate_conf_dir}/${service_name}" <= 0 )); then + true + else + false + fi +} + +# 检测数据是否为布尔值 '1' 或字符串 'yes/true' +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +is_boolean_yes() { + local -r bool="${1:-}" + # comparison is performed without regard to the case of alphabetic characters + shopt -s nocasematch + if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then + true + else + false + fi +} + +# 检测数据是否为字符串 'yes/no' +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +is_yes_no_value() { + local -r bool="${1:-}" + if [[ "$bool" =~ ^(yes|no)$ ]]; then + true + else + false + fi +} + +# 检测数据是否为字符串 'true/false' +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +is_true_false_value() { + local -r bool="${1:-}" + if [[ "$bool" =~ ^(true|false)$ ]]; then + true + else + false + fi +} + +# 检测提供的参数是否为空字符串或未定义 +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +is_empty_value() { + local -r val="${1:-}" + if [[ -z "$val" ]]; then + true + else + false + fi +} + +# 检测数据是否为有效的端口号 +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 或 错误消息 +validate_port() { + local value + local unprivileged=0 + + # Parse flags + while [[ "$#" -gt 0 ]]; do + case "$1" in + -unprivileged) + unprivileged=1 + ;; + --) + shift + break + ;; + -*) + stderr_print "unrecognized flag $1" + return 1 + ;; + *) + break + ;; + esac + shift + done + + if [[ "$#" -gt 1 ]]; then + echo "too many arguments provided" + return 2 + elif [[ "$#" -eq 0 ]]; then + stderr_print "missing port argument" + return 1 + else + value=$1 + fi + + if [[ -z "$value" ]]; then + echo "the value is empty" + return 1 + else + if ! is_int "$value"; then + echo "value is not an integer" + return 2 + elif [[ "$value" -lt 0 ]]; then + echo "negative value provided" + return 2 + elif [[ "$value" -gt 65535 ]]; then + echo "requested port is greater than 65535" + return 2 + elif [[ "$unprivileged" = 1 && "$value" -lt 1024 ]]; then + echo "privileged port requested" + return 3 + fi + fi +} + +# 检测数据是否为有效的IPv4地址 +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +validate_ipv4() { + local ip="${1:?ip is missing}" + local stat=1 + + if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + read -r -a ip_array <<< "$(tr '.' ' ' <<< "$ip")" + [[ ${ip_array[0]} -le 255 && ${ip_array[1]} -le 255 \ + && ${ip_array[2]} -le 255 && ${ip_array[3]} -le 255 ]] + stat=$? + fi + return $stat +} + +# 校验字符串格式 +# 参数: +# $1 - 待检测的数据 +# 返回值: +# 布尔值 +validate_string() { + local string + local min_length=-1 + local max_length=-1 + + # Parse flags + while [ "$#" -gt 0 ]; do + case "$1" in + -min-length) + shift + min_length=${1:-} + ;; + -max-length) + shift + max_length=${1:-} + ;; + --) + shift + break + ;; + -*) + stderr_print "unrecognized flag $1" + return 1 + ;; + *) + break + ;; + esac + shift + done + + if [ "$#" -gt 1 ]; then + stderr_print "too many arguments provided" + return 2 + elif [ "$#" -eq 0 ]; then + stderr_print "missing string" + return 1 + else + string=$1 + fi + + if [[ "$min_length" -ge 0 ]] && [[ "${#string}" -lt "$min_length" ]]; then + echo "string length is less than $min_length" + return 1 + fi + if [[ "$max_length" -ge 0 ]] && [[ "${#string}" -gt "$max_length" ]]; then + echo "string length is great than $max_length" + return 1 + fi +} \ No newline at end of file diff --git a/5.0/redis/default/redis.conf b/5.0/redis/default/redis.conf deleted file mode 100644 index c934d74..0000000 --- a/5.0/redis/default/redis.conf +++ /dev/null @@ -1,1378 +0,0 @@ -# Redis configuration file example. -# -# Note that in order to read the configuration file, Redis must be -# started with the file path as first argument: -# -# ./redis-server /path/to/redis.conf - -# Note on units: when memory size is needed, it is possible to specify -# it in the usual form of 1k 5GB 4M and so forth: -# -# 1k => 1000 bytes -# 1kb => 1024 bytes -# 1m => 1000000 bytes -# 1mb => 1024*1024 bytes -# 1g => 1000000000 bytes -# 1gb => 1024*1024*1024 bytes -# -# units are case insensitive so 1GB 1Gb 1gB are all the same. - -################################## INCLUDES ################################### - -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all Redis servers but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. -# -# Notice option "include" won't be rewritten by command "CONFIG REWRITE" -# from admin or Redis Sentinel. Since Redis always uses the last processed -# line as value of a configuration directive, you'd better put includes -# at the beginning of this file to avoid overwriting config change at runtime. -# -# If instead you are interested in using includes to override configuration -# options, it is better to use include as the last line. -# -# include /path/to/local.conf -# include /path/to/other.conf - -################################## MODULES ##################################### - -# Load modules at startup. If the server is not able to load modules -# it will abort. It is possible to use multiple loadmodule directives. -# -# loadmodule /path/to/my_module.so -# loadmodule /path/to/other_module.so - -################################## NETWORK ##################################### - -# By default, if no "bind" configuration directive is specified, Redis listens -# for connections from all the network interfaces available on the server. -# It is possible to listen to just one or multiple selected interfaces using -# the "bind" configuration directive, followed by one or more IP addresses. -# -# Examples: -# -# bind 192.168.1.100 10.0.0.1 -# bind 127.0.0.1 ::1 -# -# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the -# internet, binding to all the interfaces is dangerous and will expose the -# instance to everybody on the internet. So by default we uncomment the -# following bind directive, that will force Redis to listen only into -# the IPv4 loopback interface address (this means Redis will be able to -# accept connections only from clients running into the same computer it -# is running). -# -# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES -# JUST COMMENT THE FOLLOWING LINE. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Modify by Endial Fang -#bind 127.0.0.1 -bind 0.0.0.0 - -# Protected mode is a layer of security protection, in order to avoid that -# Redis instances left open on the internet are accessed and exploited. -# -# When protected mode is on and if: -# -# 1) The server is not binding explicitly to a set of addresses using the -# "bind" directive. -# 2) No password is configured. -# -# The server only accepts connections from clients connecting from the -# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain -# sockets. -# -# By default protected mode is enabled. You should disable it only if -# you are sure you want clients from other hosts to connect to Redis -# even if no authentication is configured, nor a specific set of interfaces -# are explicitly listed using the "bind" directive. -protected-mode yes - -# Accept connections on the specified port, default is 6379 (IANA #815344). -# If port 0 is specified Redis will not listen on a TCP socket. -port 6379 - -# TCP listen() backlog. -# -# In high requests-per-second environments you need an high backlog in order -# to avoid slow clients connections issues. Note that the Linux kernel -# will silently truncate it to the value of /proc/sys/net/core/somaxconn so -# make sure to raise both the value of somaxconn and tcp_max_syn_backlog -# in order to get the desired effect. -tcp-backlog 511 - -# Unix socket. -# -# Specify the path for the Unix socket that will be used to listen for -# incoming connections. There is no default, so Redis will not listen -# on a unix socket when not specified. -# -# unixsocket /tmp/redis.sock -# unixsocketperm 700 - -# Close the connection after a client is idle for N seconds (0 to disable) -timeout 0 - -# TCP keepalive. -# -# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence -# of communication. This is useful for two reasons: -# -# 1) Detect dead peers. -# 2) Take the connection alive from the point of view of network -# equipment in the middle. -# -# On Linux, the specified value (in seconds) is the period used to send ACKs. -# Note that to close the connection the double of the time is needed. -# On other kernels the period depends on the kernel configuration. -# -# A reasonable value for this option is 300 seconds, which is the new -# Redis default starting with Redis 3.2.1. -tcp-keepalive 300 - -################################# GENERAL ##################################### - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize no - -# If you run Redis from upstart or systemd, Redis can interact with your -# supervision tree. Options: -# supervised no - no supervision interaction -# supervised upstart - signal upstart by putting Redis into SIGSTOP mode -# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET -# supervised auto - detect upstart or systemd method based on -# UPSTART_JOB or NOTIFY_SOCKET environment variables -# Note: these supervision methods only signal "process is ready." -# They do not enable continuous liveness pings back to your supervisor. -supervised no - -# If a pid file is specified, Redis writes it where specified at startup -# and removes it at exit. -# -# When the server runs non daemonized, no pid file is created if none is -# specified in the configuration. When the server is daemonized, the pid file -# is used even if not specified, defaulting to "/var/run/redis.pid". -# -# Creating a pid file is best effort: if Redis is not able to create it -# nothing bad happens, the server will start and run normally. -# -# Modify by Endial Fang, Please use default directory: /var/run/redis/ -pidfile /var/run/redis/redis_6379.pid - -# Specify the server verbosity level. -# This can be one of: -# debug (a lot of information, useful for development/testing) -# verbose (many rarely useful info, but not a mess like the debug level) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) -loglevel notice - -# Specify the log file name. Also the empty string can be used to force -# Redis to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -# -# Modify by Endial Fang, Please use default directory: /var/log/redis/ -logfile "" - -# To enable logging to the system logger, just set 'syslog-enabled' to yes, -# and optionally update the other syslog parameters to suit your needs. -# syslog-enabled no - -# Specify the syslog identity. -# syslog-ident redis - -# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -# syslog-facility local0 - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 -databases 16 - -# By default Redis shows an ASCII art logo only when started to log to the -# standard output and if the standard output is a TTY. Basically this means -# that normally a logo is displayed only in interactive sessions. -# -# However it is possible to force the pre-4.0 behavior and always show a -# ASCII art logo in startup logs by setting the following option to yes. -always-show-logo yes - -################################ SNAPSHOTTING ################################ -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -# -# Note: you can disable saving completely by commenting out all "save" lines. -# -# It is also possible to remove all the previously configured save -# points by adding a save directive with a single empty string argument -# like in the following example: -# -# save "" - -save 900 1 -save 300 10 -save 60 10000 - -# By default Redis will stop accepting writes if RDB snapshots are enabled -# (at least one save point) and the latest background save failed. -# This will make the user aware (in a hard way) that data is not persisting -# on disk properly, otherwise chances are that no one will notice and some -# disaster will happen. -# -# If the background saving process will start working again Redis will -# automatically allow writes again. -# -# However if you have setup your proper monitoring of the Redis server -# and persistence, you may want to disable this feature so that Redis will -# continue to work as usual even if there are problems with disk, -# permissions, and so forth. -stop-writes-on-bgsave-error yes - -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. -rdbcompression yes - -# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. -# This makes the format more resistant to corruption but there is a performance -# hit to pay (around 10%) when saving and loading RDB files, so you can disable it -# for maximum performances. -# -# RDB files created with checksum disabled have a checksum of zero that will -# tell the loading code to skip the check. -rdbchecksum yes - -# The filename where to dump the DB -dbfilename dump.rdb - -# The working directory. -# -# The DB will be written inside this directory, with the filename specified -# above using the 'dbfilename' configuration directive. -# -# The Append Only File will also be created inside this directory. -# -# Note that you must specify a directory here, not a file name. -dir ./ - -################################# REPLICATION ################################# - -# Master-Replica replication. Use replicaof to make a Redis instance a copy of -# another Redis server. A few things to understand ASAP about Redis replication. -# -# +------------------+ +---------------+ -# | Master | ---> | Replica | -# | (receive writes) | | (exact copy) | -# +------------------+ +---------------+ -# -# 1) Redis replication is asynchronous, but you can configure a master to -# stop accepting writes if it appears to be not connected with at least -# a given number of replicas. -# 2) Redis replicas are able to perform a partial resynchronization with the -# master if the replication link is lost for a relatively small amount of -# time. You may want to configure the replication backlog size (see the next -# sections of this file) with a sensible value depending on your needs. -# 3) Replication is automatic and does not need user intervention. After a -# network partition replicas automatically try to reconnect to masters -# and resynchronize with them. -# -# replicaof - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the replica to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the replica request. -# -# masterauth - -# When a replica loses its connection with the master, or when the replication -# is still in progress, the replica can act in two different ways: -# -# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will -# still reply to client requests, possibly with out of date data, or the -# data set may just be empty if this is the first synchronization. -# -# 2) if replica-serve-stale-data is set to 'no' the replica will reply with -# an error "SYNC with master in progress" to all the kind of commands -# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, -# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, -# COMMAND, POST, HOST: and LATENCY. -# -replica-serve-stale-data yes - -# You can configure a replica instance to accept writes or not. Writing against -# a replica instance may be useful to store some ephemeral data (because data -# written on a replica will be easily deleted after resync with the master) but -# may also cause problems if clients are writing to it because of a -# misconfiguration. -# -# Since Redis 2.6 by default replicas are read-only. -# -# Note: read only replicas are not designed to be exposed to untrusted clients -# on the internet. It's just a protection layer against misuse of the instance. -# Still a read only replica exports by default all the administrative commands -# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve -# security of read only replicas using 'rename-command' to shadow all the -# administrative / dangerous commands. -replica-read-only yes - -# Replication SYNC strategy: disk or socket. -# -# ------------------------------------------------------- -# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY -# ------------------------------------------------------- -# -# New replicas and reconnecting replicas that are not able to continue the replication -# process just receiving differences, need to do what is called a "full -# synchronization". An RDB file is transmitted from the master to the replicas. -# The transmission can happen in two different ways: -# -# 1) Disk-backed: The Redis master creates a new process that writes the RDB -# file on disk. Later the file is transferred by the parent -# process to the replicas incrementally. -# 2) Diskless: The Redis master creates a new process that directly writes the -# RDB file to replica sockets, without touching the disk at all. -# -# With disk-backed replication, while the RDB file is generated, more replicas -# can be queued and served with the RDB file as soon as the current child producing -# the RDB file finishes its work. With diskless replication instead once -# the transfer starts, new replicas arriving will be queued and a new transfer -# will start when the current one terminates. -# -# When diskless replication is used, the master waits a configurable amount of -# time (in seconds) before starting the transfer in the hope that multiple replicas -# will arrive and the transfer can be parallelized. -# -# With slow disks and fast (large bandwidth) networks, diskless replication -# works better. -repl-diskless-sync no - -# When diskless replication is enabled, it is possible to configure the delay -# the server waits in order to spawn the child that transfers the RDB via socket -# to the replicas. -# -# This is important since once the transfer starts, it is not possible to serve -# new replicas arriving, that will be queued for the next RDB transfer, so the server -# waits a delay in order to let more replicas arrive. -# -# The delay is specified in seconds, and by default is 5 seconds. To disable -# it entirely just set it to 0 seconds and the transfer will start ASAP. -repl-diskless-sync-delay 5 - -# Replicas send PINGs to server in a predefined interval. It's possible to change -# this interval with the repl_ping_replica_period option. The default value is 10 -# seconds. -# -# repl-ping-replica-period 10 - -# The following option sets the replication timeout for: -# -# 1) Bulk transfer I/O during SYNC, from the point of view of replica. -# 2) Master timeout from the point of view of replicas (data, pings). -# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings). -# -# It is important to make sure that this value is greater than the value -# specified for repl-ping-replica-period otherwise a timeout will be detected -# every time there is low traffic between the master and the replica. -# -# repl-timeout 60 - -# Disable TCP_NODELAY on the replica socket after SYNC? -# -# If you select "yes" Redis will use a smaller number of TCP packets and -# less bandwidth to send data to replicas. But this can add a delay for -# the data to appear on the replica side, up to 40 milliseconds with -# Linux kernels using a default configuration. -# -# If you select "no" the delay for data to appear on the replica side will -# be reduced but more bandwidth will be used for replication. -# -# By default we optimize for low latency, but in very high traffic conditions -# or when the master and replicas are many hops away, turning this to "yes" may -# be a good idea. -repl-disable-tcp-nodelay no - -# Set the replication backlog size. The backlog is a buffer that accumulates -# replica data when replicas are disconnected for some time, so that when a replica -# wants to reconnect again, often a full resync is not needed, but a partial -# resync is enough, just passing the portion of data the replica missed while -# disconnected. -# -# The bigger the replication backlog, the longer the time the replica can be -# disconnected and later be able to perform a partial resynchronization. -# -# The backlog is only allocated once there is at least a replica connected. -# -# repl-backlog-size 1mb - -# After a master has no longer connected replicas for some time, the backlog -# will be freed. The following option configures the amount of seconds that -# need to elapse, starting from the time the last replica disconnected, for -# the backlog buffer to be freed. -# -# Note that replicas never free the backlog for timeout, since they may be -# promoted to masters later, and should be able to correctly "partially -# resynchronize" with the replicas: hence they should always accumulate backlog. -# -# A value of 0 means to never release the backlog. -# -# repl-backlog-ttl 3600 - -# The replica priority is an integer number published by Redis in the INFO output. -# It is used by Redis Sentinel in order to select a replica to promote into a -# master if the master is no longer working correctly. -# -# A replica with a low priority number is considered better for promotion, so -# for instance if there are three replicas with priority 10, 100, 25 Sentinel will -# pick the one with priority 10, that is the lowest. -# -# However a special priority of 0 marks the replica as not able to perform the -# role of master, so a replica with priority of 0 will never be selected by -# Redis Sentinel for promotion. -# -# By default the priority is 100. -replica-priority 100 - -# It is possible for a master to stop accepting writes if there are less than -# N replicas connected, having a lag less or equal than M seconds. -# -# The N replicas need to be in "online" state. -# -# The lag in seconds, that must be <= the specified value, is calculated from -# the last ping received from the replica, that is usually sent every second. -# -# This option does not GUARANTEE that N replicas will accept the write, but -# will limit the window of exposure for lost writes in case not enough replicas -# are available, to the specified number of seconds. -# -# For example to require at least 3 replicas with a lag <= 10 seconds use: -# -# min-replicas-to-write 3 -# min-replicas-max-lag 10 -# -# Setting one or the other to 0 disables the feature. -# -# By default min-replicas-to-write is set to 0 (feature disabled) and -# min-replicas-max-lag is set to 10. - -# A Redis master is able to list the address and port of the attached -# replicas in different ways. For example the "INFO replication" section -# offers this information, which is used, among other tools, by -# Redis Sentinel in order to discover replica instances. -# Another place where this info is available is in the output of the -# "ROLE" command of a master. -# -# The listed IP and address normally reported by a replica is obtained -# in the following way: -# -# IP: The address is auto detected by checking the peer address -# of the socket used by the replica to connect with the master. -# -# Port: The port is communicated by the replica during the replication -# handshake, and is normally the port that the replica is using to -# listen for connections. -# -# However when port forwarding or Network Address Translation (NAT) is -# used, the replica may be actually reachable via different IP and port -# pairs. The following two options can be used by a replica in order to -# report to its master a specific set of IP and port, so that both INFO -# and ROLE will report those values. -# -# There is no need to use both the options if you need to override just -# the port or the IP address. -# -# replica-announce-ip 5.5.5.5 -# replica-announce-port 1234 - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# Warning: since Redis is pretty fast an outside user can try up to -# 150k passwords per second against a good box. This means that you should -# use a very strong password otherwise it will be very easy to break. -# -# requirepass foobared - -# Command renaming. -# -# It is possible to change the name of dangerous commands in a shared -# environment. For instance the CONFIG command may be renamed into something -# hard to guess so that it will still be available for internal-use tools -# but not available for general clients. -# -# Example: -# -# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 -# -# It is also possible to completely kill a command by renaming it into -# an empty string: -# -# rename-command CONFIG "" -# -# Please note that changing the name of commands that are logged into the -# AOF file or transmitted to replicas may cause problems. - -################################### CLIENTS #################################### - -# Set the max number of connected clients at the same time. By default -# this limit is set to 10000 clients, however if the Redis server is not -# able to configure the process file limit to allow for the specified limit -# the max number of allowed clients is set to the current file limit -# minus 32 (as Redis reserves a few file descriptors for internal uses). -# -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 10000 - -############################## MEMORY MANAGEMENT ################################ - -# Set a memory usage limit to the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys -# according to the eviction policy selected (see maxmemory-policy). -# -# If Redis can't remove keys according to the policy, or if the policy is -# set to 'noeviction', Redis will start to reply with errors to commands -# that would use more memory, like SET, LPUSH, and so on, and will continue -# to reply to read-only commands like GET. -# -# This option is usually useful when using Redis as an LRU or LFU cache, or to -# set a hard memory limit for an instance (using the 'noeviction' policy). -# -# WARNING: If you have replicas attached to an instance with maxmemory on, -# the size of the output buffers needed to feed the replicas are subtracted -# from the used memory count, so that network problems / resyncs will -# not trigger a loop where keys are evicted, and in turn the output -# buffer of replicas is full with DELs of keys evicted triggering the deletion -# of more keys, and so forth until the database is completely emptied. -# -# In short... if you have replicas attached it is suggested that you set a lower -# limit for maxmemory so that there is some free RAM on the system for replica -# output buffers (but this is not needed if the policy is 'noeviction'). -# -# maxmemory - -# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory -# is reached. You can select among five behaviors: -# -# volatile-lru -> Evict using approximated LRU among the keys with an expire set. -# allkeys-lru -> Evict any key using approximated LRU. -# volatile-lfu -> Evict using approximated LFU among the keys with an expire set. -# allkeys-lfu -> Evict any key using approximated LFU. -# volatile-random -> Remove a random key among the ones with an expire set. -# allkeys-random -> Remove a random key, any key. -# volatile-ttl -> Remove the key with the nearest expire time (minor TTL) -# noeviction -> Don't evict anything, just return an error on write operations. -# -# LRU means Least Recently Used -# LFU means Least Frequently Used -# -# Both LRU, LFU and volatile-ttl are implemented using approximated -# randomized algorithms. -# -# Note: with any of the above policies, Redis will return an error on write -# operations, when there are no suitable keys for eviction. -# -# At the date of writing these commands are: set setnx setex append -# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd -# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby -# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby -# getset mset msetnx exec sort -# -# The default is: -# -# maxmemory-policy noeviction - -# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated -# algorithms (in order to save memory), so you can tune it for speed or -# accuracy. For default Redis will check five keys and pick the one that was -# used less recently, you can change the sample size using the following -# configuration directive. -# -# The default of 5 produces good enough results. 10 Approximates very closely -# true LRU but costs more CPU. 3 is faster but not very accurate. -# -# maxmemory-samples 5 - -# Starting from Redis 5, by default a replica will ignore its maxmemory setting -# (unless it is promoted to master after a failover or manually). It means -# that the eviction of keys will be just handled by the master, sending the -# DEL commands to the replica as keys evict in the master side. -# -# This behavior ensures that masters and replicas stay consistent, and is usually -# what you want, however if your replica is writable, or you want the replica to have -# a different memory setting, and you are sure all the writes performed to the -# replica are idempotent, then you may change this default (but be sure to understand -# what you are doing). -# -# Note that since the replica by default does not evict, it may end using more -# memory than the one set via maxmemory (there are certain buffers that may -# be larger on the replica, or data structures may sometimes take more memory and so -# forth). So make sure you monitor your replicas and make sure they have enough -# memory to never hit a real out-of-memory condition before the master hits -# the configured maxmemory setting. -# -# replica-ignore-maxmemory yes - -############################# LAZY FREEING #################################### - -# Redis has two primitives to delete keys. One is called DEL and is a blocking -# deletion of the object. It means that the server stops processing new commands -# in order to reclaim all the memory associated with an object in a synchronous -# way. If the key deleted is associated with a small object, the time needed -# in order to execute the DEL command is very small and comparable to most other -# O(1) or O(log_N) commands in Redis. However if the key is associated with an -# aggregated value containing millions of elements, the server can block for -# a long time (even seconds) in order to complete the operation. -# -# For the above reasons Redis also offers non blocking deletion primitives -# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and -# FLUSHDB commands, in order to reclaim memory in background. Those commands -# are executed in constant time. Another thread will incrementally free the -# object in the background as fast as possible. -# -# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. -# It's up to the design of the application to understand when it is a good -# idea to use one or the other. However the Redis server sometimes has to -# delete keys or flush the whole database as a side effect of other operations. -# Specifically Redis deletes objects independently of a user call in the -# following scenarios: -# -# 1) On eviction, because of the maxmemory and maxmemory policy configurations, -# in order to make room for new data, without going over the specified -# memory limit. -# 2) Because of expire: when a key with an associated time to live (see the -# EXPIRE command) must be deleted from memory. -# 3) Because of a side effect of a command that stores data on a key that may -# already exist. For example the RENAME command may delete the old key -# content when it is replaced with another one. Similarly SUNIONSTORE -# or SORT with STORE option may delete existing keys. The SET command -# itself removes any old content of the specified key in order to replace -# it with the specified string. -# 4) During replication, when a replica performs a full resynchronization with -# its master, the content of the whole database is removed in order to -# load the RDB file just transferred. -# -# In all the above cases the default is to delete objects in a blocking way, -# like if DEL was called. However you can configure each case specifically -# in order to instead release memory in a non-blocking way like if UNLINK -# was called, using the following configuration directives: - -lazyfree-lazy-eviction no -lazyfree-lazy-expire no -lazyfree-lazy-server-del no -replica-lazy-flush no - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. This mode is -# good enough in many applications, but an issue with the Redis process or -# a power outage may result into a few minutes of writes lost (depending on -# the configured save points). -# -# The Append Only File is an alternative persistence mode that provides -# much better durability. For instance using the default data fsync policy -# (see later in the config file) Redis can lose just one second of writes in a -# dramatic event like a server power outage, or a single write if something -# wrong with the Redis process itself happens, but the operating system is -# still running correctly. -# -# AOF and RDB persistence can be enabled at the same time without problems. -# If the AOF is enabled on startup Redis will load the AOF, that is the file -# with the better durability guarantees. -# -# Please check http://redis.io/topics/persistence for more information. - -appendonly no - -# The name of the append only file (default: "appendonly.aof") - -appendfilename "appendonly.aof" - -# The fsync() call tells the Operating System to actually write data on disk -# instead of waiting for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log. Slow, Safest. -# everysec: fsync only one time every second. Compromise. -# -# The default is "everysec", as that's usually the right compromise between -# speed and data safety. It's up to you to understand if you can relax this to -# "no" that will let the operating system flush the output buffer when -# it wants, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting), -# or on the contrary, use "always" that's very slow but a bit safer than -# everysec. -# -# More details please check the following article: -# http://antirez.com/post/redis-persistence-demystified.html -# -# If unsure, use "everysec". - -# appendfsync always -appendfsync everysec -# appendfsync no - -# When the AOF fsync policy is set to always or everysec, and a background -# saving process (a background save or AOF log background rewriting) is -# performing a lot of I/O against the disk, in some Linux configurations -# Redis may block too long on the fsync() call. Note that there is no fix for -# this currently, as even performing fsync in a different thread will block -# our synchronous write(2) call. -# -# In order to mitigate this problem it's possible to use the following option -# that will prevent fsync() from being called in the main process while a -# BGSAVE or BGREWRITEAOF is in progress. -# -# This means that while another child is saving, the durability of Redis is -# the same as "appendfsync none". In practical terms, this means that it is -# possible to lose up to 30 seconds of log in the worst scenario (with the -# default Linux settings). -# -# If you have latency problems turn this to "yes". Otherwise leave it as -# "no" that is the safest pick from the point of view of durability. - -no-appendfsync-on-rewrite no - -# Automatic rewrite of the append only file. -# Redis is able to automatically rewrite the log file implicitly calling -# BGREWRITEAOF when the AOF log size grows by the specified percentage. -# -# This is how it works: Redis remembers the size of the AOF file after the -# latest rewrite (if no rewrite has happened since the restart, the size of -# the AOF at startup is used). -# -# This base size is compared to the current size. If the current size is -# bigger than the specified percentage, the rewrite is triggered. Also -# you need to specify a minimal size for the AOF file to be rewritten, this -# is useful to avoid rewriting the AOF file even if the percentage increase -# is reached but it is still pretty small. -# -# Specify a percentage of zero in order to disable the automatic AOF -# rewrite feature. - -auto-aof-rewrite-percentage 100 -auto-aof-rewrite-min-size 64mb - -# An AOF file may be found to be truncated at the end during the Redis -# startup process, when the AOF data gets loaded back into memory. -# This may happen when the system where Redis is running -# crashes, especially when an ext4 filesystem is mounted without the -# data=ordered option (however this can't happen when Redis itself -# crashes or aborts but the operating system still works correctly). -# -# Redis can either exit with an error when this happens, or load as much -# data as possible (the default now) and start if the AOF file is found -# to be truncated at the end. The following option controls this behavior. -# -# If aof-load-truncated is set to yes, a truncated AOF file is loaded and -# the Redis server starts emitting a log to inform the user of the event. -# Otherwise if the option is set to no, the server aborts with an error -# and refuses to start. When the option is set to no, the user requires -# to fix the AOF file using the "redis-check-aof" utility before to restart -# the server. -# -# Note that if the AOF file will be found to be corrupted in the middle -# the server will still exit with an error. This option only applies when -# Redis will try to read more data from the AOF file but not enough bytes -# will be found. -aof-load-truncated yes - -# When rewriting the AOF file, Redis is able to use an RDB preamble in the -# AOF file for faster rewrites and recoveries. When this option is turned -# on the rewritten AOF file is composed of two different stanzas: -# -# [RDB file][AOF tail] -# -# When loading Redis recognizes that the AOF file starts with the "REDIS" -# string and loads the prefixed RDB file, and continues loading the AOF -# tail. -aof-use-rdb-preamble yes - -################################ LUA SCRIPTING ############################### - -# Max execution time of a Lua script in milliseconds. -# -# If the maximum execution time is reached Redis will log that a script is -# still in execution after the maximum allowed time and will start to -# reply to queries with an error. -# -# When a long running script exceeds the maximum execution time only the -# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be -# used to stop a script that did not yet called write commands. The second -# is the only way to shut down the server in the case a write command was -# already issued by the script but the user doesn't want to wait for the natural -# termination of the script. -# -# Set it to 0 or a negative value for unlimited execution without warnings. -lua-time-limit 5000 - -################################ REDIS CLUSTER ############################### - -# Normal Redis instances can't be part of a Redis Cluster; only nodes that are -# started as cluster nodes can. In order to start a Redis instance as a -# cluster node enable the cluster support uncommenting the following: -# -# cluster-enabled yes - -# Every cluster node has a cluster configuration file. This file is not -# intended to be edited by hand. It is created and updated by Redis nodes. -# Every Redis Cluster node requires a different cluster configuration file. -# Make sure that instances running in the same system do not have -# overlapping cluster configuration file names. -# -# cluster-config-file nodes-6379.conf - -# Cluster node timeout is the amount of milliseconds a node must be unreachable -# for it to be considered in failure state. -# Most other internal time limits are multiple of the node timeout. -# -# cluster-node-timeout 15000 - -# A replica of a failing master will avoid to start a failover if its data -# looks too old. -# -# There is no simple way for a replica to actually have an exact measure of -# its "data age", so the following two checks are performed: -# -# 1) If there are multiple replicas able to failover, they exchange messages -# in order to try to give an advantage to the replica with the best -# replication offset (more data from the master processed). -# Replicas will try to get their rank by offset, and apply to the start -# of the failover a delay proportional to their rank. -# -# 2) Every single replica computes the time of the last interaction with -# its master. This can be the last ping or command received (if the master -# is still in the "connected" state), or the time that elapsed since the -# disconnection with the master (if the replication link is currently down). -# If the last interaction is too old, the replica will not try to failover -# at all. -# -# The point "2" can be tuned by user. Specifically a replica will not perform -# the failover if, since the last interaction with the master, the time -# elapsed is greater than: -# -# (node-timeout * replica-validity-factor) + repl-ping-replica-period -# -# So for example if node-timeout is 30 seconds, and the replica-validity-factor -# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the -# replica will not try to failover if it was not able to talk with the master -# for longer than 310 seconds. -# -# A large replica-validity-factor may allow replicas with too old data to failover -# a master, while a too small value may prevent the cluster from being able to -# elect a replica at all. -# -# For maximum availability, it is possible to set the replica-validity-factor -# to a value of 0, which means, that replicas will always try to failover the -# master regardless of the last time they interacted with the master. -# (However they'll always try to apply a delay proportional to their -# offset rank). -# -# Zero is the only value able to guarantee that when all the partitions heal -# the cluster will always be able to continue. -# -# cluster-replica-validity-factor 10 - -# Cluster replicas are able to migrate to orphaned masters, that are masters -# that are left without working replicas. This improves the cluster ability -# to resist to failures as otherwise an orphaned master can't be failed over -# in case of failure if it has no working replicas. -# -# Replicas migrate to orphaned masters only if there are still at least a -# given number of other working replicas for their old master. This number -# is the "migration barrier". A migration barrier of 1 means that a replica -# will migrate only if there is at least 1 other working replica for its master -# and so forth. It usually reflects the number of replicas you want for every -# master in your cluster. -# -# Default is 1 (replicas migrate only if their masters remain with at least -# one replica). To disable migration just set it to a very large value. -# A value of 0 can be set but is useful only for debugging and dangerous -# in production. -# -# cluster-migration-barrier 1 - -# By default Redis Cluster nodes stop accepting queries if they detect there -# is at least an hash slot uncovered (no available node is serving it). -# This way if the cluster is partially down (for example a range of hash slots -# are no longer covered) all the cluster becomes, eventually, unavailable. -# It automatically returns available as soon as all the slots are covered again. -# -# However sometimes you want the subset of the cluster which is working, -# to continue to accept queries for the part of the key space that is still -# covered. In order to do so, just set the cluster-require-full-coverage -# option to no. -# -# cluster-require-full-coverage yes - -# This option, when set to yes, prevents replicas from trying to failover its -# master during master failures. However the master can still perform a -# manual failover, if forced to do so. -# -# This is useful in different scenarios, especially in the case of multiple -# data center operations, where we want one side to never be promoted if not -# in the case of a total DC failure. -# -# cluster-replica-no-failover no - -# In order to setup your cluster make sure to read the documentation -# available at http://redis.io web site. - -########################## CLUSTER DOCKER/NAT support ######################## - -# In certain deployments, Redis Cluster nodes address discovery fails, because -# addresses are NAT-ted or because ports are forwarded (the typical case is -# Docker and other containers). -# -# In order to make Redis Cluster working in such environments, a static -# configuration where each node knows its public address is needed. The -# following two options are used for this scope, and are: -# -# * cluster-announce-ip -# * cluster-announce-port -# * cluster-announce-bus-port -# -# Each instruct the node about its address, client port, and cluster message -# bus port. The information is then published in the header of the bus packets -# so that other nodes will be able to correctly map the address of the node -# publishing the information. -# -# If the above options are not used, the normal Redis Cluster auto-detection -# will be used instead. -# -# Note that when remapped, the bus port may not be at the fixed offset of -# clients port + 10000, so you can specify any port and bus-port depending -# on how they get remapped. If the bus-port is not set, a fixed offset of -# 10000 will be used as usually. -# -# Example: -# -# cluster-announce-ip 10.1.1.5 -# cluster-announce-port 6379 -# cluster-announce-bus-port 6380 - -################################## SLOW LOG ################################### - -# The Redis Slow Log is a system to log queries that exceeded a specified -# execution time. The execution time does not include the I/O operations -# like talking with the client, sending the reply and so forth, -# but just the time needed to actually execute the command (this is the only -# stage of command execution where the thread is blocked and can not serve -# other requests in the meantime). -# -# You can configure the slow log with two parameters: one tells Redis -# what is the execution time, in microseconds, to exceed in order for the -# command to get logged, and the other parameter is the length of the -# slow log. When a new command is logged the oldest one is removed from the -# queue of logged commands. - -# The following time is expressed in microseconds, so 1000000 is equivalent -# to one second. Note that a negative number disables the slow log, while -# a value of zero forces the logging of every command. -slowlog-log-slower-than 10000 - -# There is no limit to this length. Just be aware that it will consume memory. -# You can reclaim memory used by the slow log with SLOWLOG RESET. -slowlog-max-len 128 - -################################ LATENCY MONITOR ############################## - -# The Redis latency monitoring subsystem samples different operations -# at runtime in order to collect data related to possible sources of -# latency of a Redis instance. -# -# Via the LATENCY command this information is available to the user that can -# print graphs and obtain reports. -# -# The system only logs operations that were performed in a time equal or -# greater than the amount of milliseconds specified via the -# latency-monitor-threshold configuration directive. When its value is set -# to zero, the latency monitor is turned off. -# -# By default latency monitoring is disabled since it is mostly not needed -# if you don't have latency issues, and collecting data has a performance -# impact, that while very small, can be measured under big load. Latency -# monitoring can easily be enabled at runtime using the command -# "CONFIG SET latency-monitor-threshold " if needed. -latency-monitor-threshold 0 - -############################# EVENT NOTIFICATION ############################## - -# Redis can notify Pub/Sub clients about events happening in the key space. -# This feature is documented at http://redis.io/topics/notifications -# -# For instance if keyspace events notification is enabled, and a client -# performs a DEL operation on key "foo" stored in the Database 0, two -# messages will be published via Pub/Sub: -# -# PUBLISH __keyspace@0__:foo del -# PUBLISH __keyevent@0__:del foo -# -# It is possible to select the events that Redis will notify among a set -# of classes. Every class is identified by a single character: -# -# K Keyspace events, published with __keyspace@__ prefix. -# E Keyevent events, published with __keyevent@__ prefix. -# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... -# $ String commands -# l List commands -# s Set commands -# h Hash commands -# z Sorted set commands -# x Expired events (events generated every time a key expires) -# e Evicted events (events generated when a key is evicted for maxmemory) -# A Alias for g$lshzxe, so that the "AKE" string means all the events. -# -# The "notify-keyspace-events" takes as argument a string that is composed -# of zero or multiple characters. The empty string means that notifications -# are disabled. -# -# Example: to enable list and generic events, from the point of view of the -# event name, use: -# -# notify-keyspace-events Elg -# -# Example 2: to get the stream of the expired keys subscribing to channel -# name __keyevent@0__:expired use: -# -# notify-keyspace-events Ex -# -# By default all notifications are disabled because most users don't need -# this feature and the feature has some overhead. Note that if you don't -# specify at least one of K or E, no events will be delivered. -notify-keyspace-events "" - -############################### ADVANCED CONFIG ############################### - -# Hashes are encoded using a memory efficient data structure when they have a -# small number of entries, and the biggest entry does not exceed a given -# threshold. These thresholds can be configured using the following directives. -hash-max-ziplist-entries 512 -hash-max-ziplist-value 64 - -# Lists are also encoded in a special way to save a lot of space. -# The number of entries allowed per internal list node can be specified -# as a fixed maximum size or a maximum number of elements. -# For a fixed maximum size, use -5 through -1, meaning: -# -5: max size: 64 Kb <-- not recommended for normal workloads -# -4: max size: 32 Kb <-- not recommended -# -3: max size: 16 Kb <-- probably not recommended -# -2: max size: 8 Kb <-- good -# -1: max size: 4 Kb <-- good -# Positive numbers mean store up to _exactly_ that number of elements -# per list node. -# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size), -# but if your use case is unique, adjust the settings as necessary. -list-max-ziplist-size -2 - -# Lists may also be compressed. -# Compress depth is the number of quicklist ziplist nodes from *each* side of -# the list to *exclude* from compression. The head and tail of the list -# are always uncompressed for fast push/pop operations. Settings are: -# 0: disable all list compression -# 1: depth 1 means "don't start compressing until after 1 node into the list, -# going from either the head or tail" -# So: [head]->node->node->...->node->[tail] -# [head], [tail] will always be uncompressed; inner nodes will compress. -# 2: [head]->[next]->node->node->...->node->[prev]->[tail] -# 2 here means: don't compress head or head->next or tail->prev or tail, -# but compress all nodes between them. -# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] -# etc. -list-compress-depth 0 - -# Sets have a special encoding in just one case: when a set is composed -# of just strings that happen to be integers in radix 10 in the range -# of 64 bit signed integers. -# The following configuration setting sets the limit in the size of the -# set in order to use this special memory saving encoding. -set-max-intset-entries 512 - -# Similarly to hashes and lists, sorted sets are also specially encoded in -# order to save a lot of space. This encoding is only used when the length and -# elements of a sorted set are below the following limits: -zset-max-ziplist-entries 128 -zset-max-ziplist-value 64 - -# HyperLogLog sparse representation bytes limit. The limit includes the -# 16 bytes header. When an HyperLogLog using the sparse representation crosses -# this limit, it is converted into the dense representation. -# -# A value greater than 16000 is totally useless, since at that point the -# dense representation is more memory efficient. -# -# The suggested value is ~ 3000 in order to have the benefits of -# the space efficient encoding without slowing down too much PFADD, -# which is O(N) with the sparse encoding. The value can be raised to -# ~ 10000 when CPU is not a concern, but space is, and the data set is -# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. -hll-sparse-max-bytes 3000 - -# Streams macro node max size / items. The stream data structure is a radix -# tree of big nodes that encode multiple items inside. Using this configuration -# it is possible to configure how big a single node can be in bytes, and the -# maximum number of items it may contain before switching to a new node when -# appending new stream entries. If any of the following settings are set to -# zero, the limit is ignored, so for instance it is possible to set just a -# max entires limit by setting max-bytes to 0 and max-entries to the desired -# value. -stream-node-max-bytes 4096 -stream-node-max-entries 100 - -# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in -# order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation Redis uses (see dict.c) -# performs a lazy rehashing: the more operation you run into a hash table -# that is rehashing, the more rehashing "steps" are performed, so if the -# server is idle the rehashing is never complete and some more memory is used -# by the hash table. -# -# The default is to use this millisecond 10 times every second in order to -# actively rehash the main dictionaries, freeing memory when possible. -# -# If unsure: -# use "activerehashing no" if you have hard latency requirements and it is -# not a good thing in your environment that Redis can reply from time to time -# to queries with 2 milliseconds delay. -# -# use "activerehashing yes" if you don't have such hard requirements but -# want to free memory asap when possible. -activerehashing yes - -# The client output buffer limits can be used to force disconnection of clients -# that are not reading data from the server fast enough for some reason (a -# common reason is that a Pub/Sub client can't consume messages as fast as the -# publisher can produce them). -# -# The limit can be set differently for the three different classes of clients: -# -# normal -> normal clients including MONITOR clients -# replica -> replica clients -# pubsub -> clients subscribed to at least one pubsub channel or pattern -# -# The syntax of every client-output-buffer-limit directive is the following: -# -# client-output-buffer-limit -# -# A client is immediately disconnected once the hard limit is reached, or if -# the soft limit is reached and remains reached for the specified number of -# seconds (continuously). -# So for instance if the hard limit is 32 megabytes and the soft limit is -# 16 megabytes / 10 seconds, the client will get disconnected immediately -# if the size of the output buffers reach 32 megabytes, but will also get -# disconnected if the client reaches 16 megabytes and continuously overcomes -# the limit for 10 seconds. -# -# By default normal clients are not limited because they don't receive data -# without asking (in a push way), but just after a request, so only -# asynchronous clients may create a scenario where data is requested faster -# than it can read. -# -# Instead there is a default limit for pubsub and replica clients, since -# subscribers and replicas receive data in a push fashion. -# -# Both the hard or the soft limit can be disabled by setting them to zero. -client-output-buffer-limit normal 0 0 0 -client-output-buffer-limit replica 256mb 64mb 60 -client-output-buffer-limit pubsub 32mb 8mb 60 - -# Client query buffers accumulate new commands. They are limited to a fixed -# amount by default in order to avoid that a protocol desynchronization (for -# instance due to a bug in the client) will lead to unbound memory usage in -# the query buffer. However you can configure it here if you have very special -# needs, such us huge multi/exec requests or alike. -# -# client-query-buffer-limit 1gb - -# In the Redis protocol, bulk requests, that are, elements representing single -# strings, are normally limited ot 512 mb. However you can change this limit -# here. -# -# proto-max-bulk-len 512mb - -# Redis calls an internal function to perform many background tasks, like -# closing connections of clients in timeout, purging expired keys that are -# never requested, and so forth. -# -# Not all tasks are performed with the same frequency, but Redis checks for -# tasks to perform according to the specified "hz" value. -# -# By default "hz" is set to 10. Raising the value will use more CPU when -# Redis is idle, but at the same time will make Redis more responsive when -# there are many keys expiring at the same time, and timeouts may be -# handled with more precision. -# -# The range is between 1 and 500, however a value over 100 is usually not -# a good idea. Most users should use the default of 10 and raise this up to -# 100 only in environments where very low latency is required. -hz 10 - -# Normally it is useful to have an HZ value which is proportional to the -# number of clients connected. This is useful in order, for instance, to -# avoid too many clients are processed for each background task invocation -# in order to avoid latency spikes. -# -# Since the default HZ value by default is conservatively set to 10, Redis -# offers, and enables by default, the ability to use an adaptive HZ value -# which will temporary raise when there are many connected clients. -# -# When dynamic HZ is enabled, the actual configured HZ will be used as -# as a baseline, but multiples of the configured HZ value will be actually -# used as needed once more clients are connected. In this way an idle -# instance will use very little CPU time while a busy instance will be -# more responsive. -dynamic-hz yes - -# When a child rewrites the AOF file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -aof-rewrite-incremental-fsync yes - -# When redis saves RDB file, if the following option is enabled -# the file will be fsync-ed every 32 MB of data generated. This is useful -# in order to commit the file to the disk more incrementally and avoid -# big latency spikes. -rdb-save-incremental-fsync yes - -# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good -# idea to start with the default settings and only change them after investigating -# how to improve the performances and how the keys LFU change over time, which -# is possible to inspect via the OBJECT FREQ command. -# -# There are two tunable parameters in the Redis LFU implementation: the -# counter logarithm factor and the counter decay time. It is important to -# understand what the two parameters mean before changing them. -# -# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis -# uses a probabilistic increment with logarithmic behavior. Given the value -# of the old counter, when a key is accessed, the counter is incremented in -# this way: -# -# 1. A random number R between 0 and 1 is extracted. -# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). -# 3. The counter is incremented only if R < P. -# -# The default lfu-log-factor is 10. This is a table of how the frequency -# counter changes with a different number of accesses with different -# logarithmic factors: -# -# +--------+------------+------------+------------+------------+------------+ -# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | -# +--------+------------+------------+------------+------------+------------+ -# | 0 | 104 | 255 | 255 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 1 | 18 | 49 | 255 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 10 | 10 | 18 | 142 | 255 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# | 100 | 8 | 11 | 49 | 143 | 255 | -# +--------+------------+------------+------------+------------+------------+ -# -# NOTE: The above table was obtained by running the following commands: -# -# redis-benchmark -n 1000000 incr foo -# redis-cli object freq foo -# -# NOTE 2: The counter initial value is 5 in order to give new objects a chance -# to accumulate hits. -# -# The counter decay time is the time, in minutes, that must elapse in order -# for the key counter to be divided by two (or decremented if it has a value -# less <= 10). -# -# The default value for the lfu-decay-time is 1. A Special value of 0 means to -# decay the counter every time it happens to be scanned. -# -# lfu-log-factor 10 -# lfu-decay-time 1 - -########################### ACTIVE DEFRAGMENTATION ####################### -# -# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested -# even in production and manually tested by multiple engineers for some -# time. -# -# What is active defragmentation? -# ------------------------------- -# -# Active (online) defragmentation allows a Redis server to compact the -# spaces left between small allocations and deallocations of data in memory, -# thus allowing to reclaim back memory. -# -# Fragmentation is a natural process that happens with every allocator (but -# less so with Jemalloc, fortunately) and certain workloads. Normally a server -# restart is needed in order to lower the fragmentation, or at least to flush -# away all the data and create it again. However thanks to this feature -# implemented by Oran Agra for Redis 4.0 this process can happen at runtime -# in an "hot" way, while the server is running. -# -# Basically when the fragmentation is over a certain level (see the -# configuration options below) Redis will start to create new copies of the -# values in contiguous memory regions by exploiting certain specific Jemalloc -# features (in order to understand if an allocation is causing fragmentation -# and to allocate it in a better place), and at the same time, will release the -# old copies of the data. This process, repeated incrementally for all the keys -# will cause the fragmentation to drop back to normal values. -# -# Important things to understand: -# -# 1. This feature is disabled by default, and only works if you compiled Redis -# to use the copy of Jemalloc we ship with the source code of Redis. -# This is the default with Linux builds. -# -# 2. You never need to enable this feature if you don't have fragmentation -# issues. -# -# 3. Once you experience fragmentation, you can enable this feature when -# needed with the command "CONFIG SET activedefrag yes". -# -# The configuration parameters are able to fine tune the behavior of the -# defragmentation process. If you are not sure about what they mean it is -# a good idea to leave the defaults untouched. - -# Enabled active defragmentation -# activedefrag yes - -# Minimum amount of fragmentation waste to start active defrag -# active-defrag-ignore-bytes 100mb - -# Minimum percentage of fragmentation to start active defrag -# active-defrag-threshold-lower 10 - -# Maximum percentage of fragmentation at which we use maximum effort -# active-defrag-threshold-upper 100 - -# Minimal effort for defrag in CPU percentage -# active-defrag-cycle-min 5 - -# Maximal effort for defrag in CPU percentage -# active-defrag-cycle-max 75 - -# Maximum number of set/hash/zset/list fields that will be processed from -# the main dictionary scan -# active-defrag-max-scan-fields 1000 - diff --git a/5.0/redis/default/sentinel.conf b/5.0/redis/default/sentinel.conf deleted file mode 100644 index bc9a705..0000000 --- a/5.0/redis/default/sentinel.conf +++ /dev/null @@ -1,244 +0,0 @@ -# Example sentinel.conf - -# *** IMPORTANT *** -# -# By default Sentinel will not be reachable from interfaces different than -# localhost, either use the 'bind' directive to bind to a list of network -# interfaces, or disable protected mode with "protected-mode no" by -# adding it to this configuration file. -# -# Before doing that MAKE SURE the instance is protected from the outside -# world via firewalling or other means. -# -# For example you may use one of the following: -# -# bind 127.0.0.1 192.168.1.1 -# -# protected-mode no - -# port -# The port that this sentinel instance will run on -port 26379 - -# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when -# daemonized. -daemonize no - -# When running daemonized, Redis Sentinel writes a pid file in -# /var/run/redis-sentinel.pid by default. You can specify a custom pid file -# location here. -pidfile /var/run/redis-sentinel.pid - -# Specify the log file name. Also the empty string can be used to force -# Sentinel to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -logfile "" - -# sentinel announce-ip -# sentinel announce-port -# -# The above two configuration directives are useful in environments where, -# because of NAT, Sentinel is reachable from outside via a non-local address. -# -# When announce-ip is provided, the Sentinel will claim the specified IP address -# in HELLO messages used to gossip its presence, instead of auto-detecting the -# local address as it usually does. -# -# Similarly when announce-port is provided and is valid and non-zero, Sentinel -# will announce the specified TCP port. -# -# The two options don't need to be used together, if only announce-ip is -# provided, the Sentinel will announce the specified IP and the server port -# as specified by the "port" option. If only announce-port is provided, the -# Sentinel will announce the auto-detected local IP and the specified port. -# -# Example: -# -# sentinel announce-ip 1.2.3.4 - -# dir -# Every long running process should have a well-defined working directory. -# For Redis Sentinel to chdir to /tmp at startup is the simplest thing -# for the process to don't interfere with administrative tasks such as -# unmounting filesystems. -dir /tmp - -# sentinel monitor -# -# Tells Sentinel to monitor this master, and to consider it in O_DOWN -# (Objectively Down) state only if at least sentinels agree. -# -# Note that whatever is the ODOWN quorum, a Sentinel will require to -# be elected by the majority of the known Sentinels in order to -# start a failover, so no failover can be performed in minority. -# -# Replicas are auto-discovered, so you don't need to specify replicas in -# any way. Sentinel itself will rewrite this configuration file adding -# the replicas using additional configuration options. -# Also note that the configuration file is rewritten when a -# replica is promoted to master. -# -# Note: master name should not include special characters or spaces. -# The valid charset is A-z 0-9 and the three characters ".-_". -sentinel monitor mymaster 127.0.0.1 6379 2 - -# sentinel auth-pass -# -# Set the password to use to authenticate with the master and replicas. -# Useful if there is a password set in the Redis instances to monitor. -# -# Note that the master password is also used for replicas, so it is not -# possible to set a different password in masters and replicas instances -# if you want to be able to monitor these instances with Sentinel. -# -# However you can have Redis instances without the authentication enabled -# mixed with Redis instances requiring the authentication (as long as the -# password set is the same for all the instances requiring the password) as -# the AUTH command will have no effect in Redis instances with authentication -# switched off. -# -# Example: -# -# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd - -# sentinel down-after-milliseconds -# -# Number of milliseconds the master (or any attached replica or sentinel) should -# be unreachable (as in, not acceptable reply to PING, continuously, for the -# specified period) in order to consider it in S_DOWN state (Subjectively -# Down). -# -# Default is 30 seconds. -sentinel down-after-milliseconds mymaster 30000 - -# sentinel parallel-syncs -# -# How many replicas we can reconfigure to point to the new replica simultaneously -# during the failover. Use a low number if you use the replicas to serve query -# to avoid that all the replicas will be unreachable at about the same -# time while performing the synchronization with the master. -sentinel parallel-syncs mymaster 1 - -# sentinel failover-timeout -# -# Specifies the failover timeout in milliseconds. It is used in many ways: -# -# - The time needed to re-start a failover after a previous failover was -# already tried against the same master by a given Sentinel, is two -# times the failover timeout. -# -# - The time needed for a replica replicating to a wrong master according -# to a Sentinel current configuration, to be forced to replicate -# with the right master, is exactly the failover timeout (counting since -# the moment a Sentinel detected the misconfiguration). -# -# - The time needed to cancel a failover that is already in progress but -# did not produced any configuration change (SLAVEOF NO ONE yet not -# acknowledged by the promoted replica). -# -# - The maximum time a failover in progress waits for all the replicas to be -# reconfigured as replicas of the new master. However even after this time -# the replicas will be reconfigured by the Sentinels anyway, but not with -# the exact parallel-syncs progression as specified. -# -# Default is 3 minutes. -sentinel failover-timeout mymaster 180000 - -# SCRIPTS EXECUTION -# -# sentinel notification-script and sentinel reconfig-script are used in order -# to configure scripts that are called to notify the system administrator -# or to reconfigure clients after a failover. The scripts are executed -# with the following rules for error handling: -# -# If script exits with "1" the execution is retried later (up to a maximum -# number of times currently set to 10). -# -# If script exits with "2" (or an higher value) the script execution is -# not retried. -# -# If script terminates because it receives a signal the behavior is the same -# as exit code 1. -# -# A script has a maximum running time of 60 seconds. After this limit is -# reached the script is terminated with a SIGKILL and the execution retried. - -# NOTIFICATION SCRIPT -# -# sentinel notification-script -# -# Call the specified notification script for any sentinel event that is -# generated in the WARNING level (for instance -sdown, -odown, and so forth). -# This script should notify the system administrator via email, SMS, or any -# other messaging system, that there is something wrong with the monitored -# Redis systems. -# -# The script is called with just two arguments: the first is the event type -# and the second the event description. -# -# The script must exist and be executable in order for sentinel to start if -# this option is provided. -# -# Example: -# -# sentinel notification-script mymaster /var/redis/notify.sh - -# CLIENTS RECONFIGURATION SCRIPT -# -# sentinel client-reconfig-script -# -# When the master changed because of a failover a script can be called in -# order to perform application-specific tasks to notify the clients that the -# configuration has changed and the master is at a different address. -# -# The following arguments are passed to the script: -# -# -# -# is currently always "failover" -# is either "leader" or "observer" -# -# The arguments from-ip, from-port, to-ip, to-port are used to communicate -# the old address of the master and the new address of the elected replica -# (now a master). -# -# This script should be resistant to multiple invocations. -# -# Example: -# -# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh - -# SECURITY -# -# By default SENTINEL SET will not be able to change the notification-script -# and client-reconfig-script at runtime. This avoids a trivial security issue -# where clients can set the script to anything and trigger a failover in order -# to get the program executed. - -sentinel deny-scripts-reconfig yes - -# REDIS COMMANDS RENAMING -# -# Sometimes the Redis server has certain commands, that are needed for Sentinel -# to work correctly, renamed to unguessable strings. This is often the case -# of CONFIG and SLAVEOF in the context of providers that provide Redis as -# a service, and don't want the customers to reconfigure the instances outside -# of the administration console. -# -# In such case it is possible to tell Sentinel to use different command names -# instead of the normal ones. For example if the master "mymaster", and the -# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use: -# -# SENTINEL rename-command mymaster CONFIG GUESSME -# -# After such configuration is set, every time Sentinel would use CONFIG it will -# use GUESSME instead. Note that there is no actual need to respect the command -# case, so writing "config guessme" is the same in the example above. -# -# SENTINEL SET can also be used in order to perform this configuration at runtime. -# -# In order to set a command back to its original name (undo the renaming), it -# is possible to just rename a command to itsef: -# -# SENTINEL rename-command mymaster CONFIG CONFIG diff --git a/README.md b/README.md index 3123ea1..fb1e61c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,16 @@ # Redis -针对 Redis 的 Docker 镜像,用于提供 Redis 服务。 +针对 Redis 应用的 Docker 镜像,用于提供 Redis 服务。 + +详细信息可参照官网:https://redis.io + + + +![redis-white](img/redis-white.png) **版本信息:** +- 6.0、6.0.5 - 5.0、5.0.8、latest **镜像信息:** @@ -11,26 +18,44 @@ * 镜像地址:colovu/redis:latest * 依赖镜像:colovu/ubuntu:latest +**使用 Docker Compose 运行应用** + +可以使用 Git 仓库中的默认`docker-compose.yml`,快速启动应用进行测试: + +```shell +$ curl -sSL https://raw.githubusercontent.com/colovu/docker-redis/master/docker-compose.yml > docker-compose.yml + +$ docker-compose up -d +``` -## 数据卷 + +## 默认对外声明 + +### 端口 + +- 6379:Redis 业务客户端访问端口 +- 26379:Redis Sentinel 端口 + +### 数据卷 镜像默认提供以下数据卷定义: ```shell /srv/data # Redis 数据文件,主要存放Redis持久化数据;自动创建子目录redis +/srv/datalog # Redis 数据操作日志文件;自动创建子目录redis /srv/conf # Redis 配置文件;自动创建子目录redis -/var/log # 日志文件,日志文件名为:redis-server.log -/var/run # 进程运行PID文件,PID文件名为:redis_6379.pid +/var/log # 日志文件,日志文件名为:redis.log +/var/run # 进程运行PID文件,PID文件名为:redis_6379.pid、redis_sentinel.pid ``` 如果需要持久化存储相应数据,需要在宿主机建立本地目录,并在使用镜像初始化容器时进行映射。 举例: -- 使用宿主机`/opt/conf`存储配置文件 -- 使用宿主机`/srv/data`存储数据文件 -- 使用宿主机`/srv/log`存储日志文件 +- 使用宿主机`/host/dir/for/conf`存储配置文件 +- 使用宿主机`/host/dir/for/data`存储数据文件 +- 使用宿主机`/host/dir/for/log`存储日志文件 创建以上相应的宿主机目录后,容器启动命令中对应的映射参数类似如下: @@ -38,82 +63,754 @@ -v /host/dir/for/conf:/srv/conf -v /host/dir/for/data:/srv/data -v /host/dir/for/log:/var/log ``` +使用 Docker Compose 时配置文件类似如下: + +```yaml +services: + redis: + ... + volumes: + - /host/dir/to/conf:/srv/conf + - /host/dir/to/data:/srv/data + - /host/dir/to/log:/var/log + ... +``` + > 注意:应用需要使用的子目录会自动创建。 ## 使用说明 +- 在后续介绍中,启动的容器默认命名为`redis`/`redis1`/`redis2`/`redis3`,需要根据实际情况修改 +- 在后续介绍中,容器默认使用的网络命名为`app-tier`,需要根据实际情况修改 -### 运行容器 + +### 容器网络 + +在工作在同一个网络组中时,如果容器需要互相访问,相关联的容器可以使用容器初始化时定义的名称作为主机名进行互相访问。 + +创建网络: + +```shell +$ docker network create app-tier --driver bridge +``` + +- 使用桥接方式,创建一个命名为`app-tier`的网络 + + + +如果使用已创建的网络连接不同容器,需要在启动命令中增加类似`--network app-tier`的参数。使用 Docker Compose 时,在`docker-compose`的配置文件中增加: + +```yaml +services: + redis: + ... + networks: + - app-tier + ... +``` + + + +### 下载镜像 + +可以不单独下载镜像,如果镜像不存在,会在初始化容器时自动下载。 + +```shell +# 下载指定Tag的镜像 +$ docker pull colovu/redis:tag + +# 下载最新镜像 +$ docker pull colovu/redis:latest +``` + +> TAG:替换为需要使用的指定标签名 + + + +### 持久化数据存储 + +如果需要将容器数据持久化存储至宿主机或数据存储中,需要确保宿主机对应的路径存在,并在启动时,映射为对应的数据卷。 + +Redis 镜像默认配置了用于存储数据的数据卷 `/srv/data`及用于存储数据日志的数据卷`/srv/datalog`。可以使用宿主机目录映射相应的数据卷,将数据持久化存储在宿主机中。路径中,应用对应的子目录如果不存在,容器会在初始化时创建,并生成相应的默认文件。 + +> 注意:将数据持久化存储至宿主机,可避免容器销毁导致的数据丢失。同时,将数据存储及数据日志分别映射为不同的本地设备(如不同的共享数据存储)可提供较好的性能保证。 + + + +### 实例化服务容器 生成并运行一个新的容器: -```bash -docker run -d --name redis \ - -p 6379:6379 \ - -v /host/dir/for/data:/srv/data \ - -v /host/dir/for/conf:/srv/conf \ - -v /host/dir/for/log:/var/log \ - -v /host/dir/for/run:/var/run \ - colovu/redis:latest +```shell +$ docker run -d --name redis -p 6379:6379 -e REDIS_ALLOW_EMPTY_PASSWORD=yes colovu/redis:latest ``` +- `-d`: 使用服务方式启动容器 +- `--name redis`: 为当前容器命名 +- `-e REDIS_ALLOW_EMPTY_PASSWORD=yes`: 设置默认允许任意用户登录(调试时使用,生产系统应当使用认证) -使用个性化配置文件运行容器: + +使用数据卷映射生成并运行一个容器: ```shell -docker run -d --name redis \ - -p 6379:6379 \ - -v /host/dir/for/data:/srv/data \ - -v /host/dir/for/conf:/srv/conf \ - -v /host/dir/for/log:/var/log \ - -v /host/dir/for/run:/var/run \ - colovu/redis:latest redis-server /srv/conf/redis/redis.conf --appendonly yes -``` - -- `redis-server /srv/conf/redis/redis.conf`:用于以指定的配置文件创建容器,路径不可修改(为容器中路径) -- 该文件可以在宿主机路径`/host/dir/for/conf`中找到并进行修改;修改后需要重启容器才能使配置起作用 -- `--appendonly yes`:打开redis持久化配置(非必须),可通过配置文件修改 - - - -如果存在`dvc`数据容器,可以使用以下命令: - -```bash -docker run -d --name redis \ - -p 6379:6379 \ - --volumes-from dvc \ - colovu/redis:latest + $ docker run -d --name redis -e REDIS_ALLOW_EMPTY_PASSWORD=yes \ + -p 6379:6379 \ + -v /host/dir/to/data:/srv/data \ + -v /host/dir/to/datalog:/srv/datalog \ + -v /host/dir/to/conf:/srv/conf \ + colovu/redis:latest ``` -### 进入容器 +### 连接容器 -使用容器ID或启动时的命名(本例中命名为`redis`)进入容器: +启用 [Docker container networking](https://docs.docker.com/engine/userguide/networking/)后,工作在容器中的 Redis 服务可以被其他应用容器访问和使用。 + +#### 命令行方式 + +使用已定义网络`app-tier`,启动 Redis 容器: ```shell -docker exec -it redis /bin/sh +$ docker run -d --name redis -e REDIS_ALLOW_EMPTY_PASSWORD=yes \ + -p 6379:6379 \ + --network app-tier \ + colovu/redis:latest ``` +- `--network app-tier`: 容器使用的网络 + + + +其他业务容器连接至 Redis 容器: + +```shell +$ docker run -d --name other-app -p 6379:6379 --network app-tier --link redis:redis.server other-app-image:tag +``` + +- `--link redis:redis.server`: 链接 redis 容器,并命名为 `redis.server` 进行使用(如果其他容器中使用了该名称进行访问) + + + +#### Docker Compose 方式 + +如使用配置文件`docker-compose-test.yml`: + +```yaml +version: '3.6' + +services: + redis: + image: 'colovu/redis:latest' + ports: + - 6379:6379 + environment: + - REDIS_ALLOW_EMPTY_PASSWORD=yes + networks: + - app-tier + myapp: + image: 'other-app-img:tag' + links: + - redis:redis.server + networks: + - app-tier + +networks: + app-tier: + driver: bridge +``` + +> 注意: +> +> - 需要修改 `other-app-img:tag`为相应业务镜像的名字 +> - 在其他的应用中,使用`redis`连接 Redis 容器,如果应用不是使用的该名字,可以重定义启动时的命名,如使用`--links redis:name-in-app`进行名称映射 + +启动方式: + +```shell +$ docker-compose -f docker-compose-test.yml up -d +``` + +- 如果配置文件命名为`docker-compose.yml`,可以省略`-f docker-compose-test.yml`参数 + + + +#### 其他连接操作 + +使用 exec 命令访问容器ID或启动时的命名,进入容器并执行命令: + +```shell +$ docker exec -it redis /bin/bash +``` + +- `/bin/bash`: 在进入容器后,运行的命令 + + + +使用 attach 命令进入已运行的容器: + +```shell +$ docker attach --sig-proxy=false redis +``` + +- **该方式无法执行命令**,仅用于通过日志观察应用运行状态 +- 如果不使用` --sig-proxy=false`,关闭终端或`Ctrl + C`时,会导致容器停止 + ### 停止容器 -使用容器ID或启动时的命名(本例中命名为`redis`)停止: +使用 stop 命令以容器ID或启动时的命名方式停止容器: ```shell -docker stop redis +$ docker stop redis +``` + + + +### 查看日志 + +默认方式启动容器时,容器的运行日志输出至终端,可使用如下方式进行查看: + +```shell +$ docker logs redis +``` + +在使用 Docker Compose 管理容器时,使用以下命令查看: + +```shell +$ docker-compose logs redis +``` + + + +## Docker Compose 部署 + +### 单机部署 + +根据需要,修改 Docker Compose 配置文件,如`docker-compose.yml`,并启动: + +```bash +$ docker-compose up -d +``` + +- 在不定义配置文件的情况下,默认使用当前目录的`docker-compose.yml`文件 +- 如果配置文件为其他名称,可以使用`-f 文件名`方式指定 + + + +`docker-compose.yml`文件参考如下: + +```yaml +version: '3.6' + +services: + redis: + image: 'colovu/redis:latest' + ports: + - '6379:6379' + environment: + - REDIS_ALLOW_EMPTY_PASSWORD=yes + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL +``` + + + +#### 环境验证 + + + + + +### 集群部署 + +根据需要,修改 Docker Compose 配置文件,如`docker-compose-cluster.yml`,并启动: + +```bash +$ docker-compose -f docker-compose-cluster.yml up -d +``` + +- 在不定义配置文件的情况下,默认使用当前目录的`docker-compose.yml`文件 + + + +可以使用 [`docker stack deploy`](https://docs.docker.com/engine/reference/commandline/stack_deploy/) 或 [`docker-compose`](https://github.com/docker/compose) 方式,启动一组服务容器。 `docker-compose.yml` 配置文件(伪集群)参考如下: + +```yaml +version: '3.6' + +services: + redis-primary: + image: 'colovu/redis:latest' + ports: + - '6379:6379' + environment: + - REDIS_REPLICATION_MODE=master + - REDIS_PASSWORD=colovu + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + + redis-replica: + image: 'colovu/redis:latest' + ports: + - '6379' + environment: + - REDIS_REPLICATION_MODE=slave + - REDIS_MASTER_HOST=redis-primary + - REDIS_MASTER_PORT_NUMBER=6379 + - REDIS_MASTER_PASSWORD=colovu + - REDIS_PASSWORD=colovu + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + depends_on: + - redis-primary + +``` + +> 由于配置的是伪集群模式, 所以各个 server 的端口参数必须不同(使用同一个宿主机的不同端口) + + + +以上方式将以 [replicated mode](https://redis.io/topics/cluster-tutorial) 启动 Redis 。也可以以 [Docker Swarm](https://www.docker.com/products/docker-swarm) 方式进行配置。 + +> 注意:在一个机器上设置多个服务容器,并不能提供冗余特性;如果主机因各种原因导致宕机,则所有 Redis 服务都会下线。如果需要完全的冗余特性,需要在完全独立的不同物理主机中启动服务容器;即使在一个集群的中的不同虚拟主机中启动单独的服务容器也无法完全避免因物理主机宕机导致的问题。 + + + +#### 集群动态扩容 + +```shell +docker-compose up --detach --scale redis-primary=1 --scale redis-replica=3 +``` + +以上命令,将 replicated 容器增加为 3 台,也可以使用类似命令减少容器数量。 + +> 不能增加/减少 primary 容器的数量,仅能存在一个 primary 容器节点。 + + + +#### 环境验证 + +使用`docker ps`命令可以查看所有在运行的容器: + + + + + +## 容器配置 + +在初始化 redis 容器时,如果配置文件`zoo.cfg`不存在,可以在命令行中使用相应参数对默认参数进行修改。类似命令如下: + +```shell +$ docker run -d --restart always -e "REDIS_INIT_LIMIT=10" --name zoo1 colovu/zookeeper:latest +``` + + + +### 常规配置参数 + +常使用的环境变量主要包括: + +#### `REDIS_PORT` + +默认值:**6379**。设置应用的默认客户访问端口。 + +#### `REDIS_DISABLE_COMMANDS` + +默认值:**无**。设置禁用的 Redis 命令。 + +#### `REDIS_AOF_ENABLED` + +默认值:**yes**。设置是否启用 Append Only File 存储。 + +#### `ENV_DEBUG` + +默认值:**false**。设置是否输出容器调试信息。 + +> 可设置为:1、true、yes + + + +### Sentinel配置参数 + +#### `REDIS_SENTINEL_HOST` + +默认值:**无**。 + +#### `REDIS_SENTINEL_MASTER_NAME` + +默认值:**无**。 + +#### `REDIS_SENTINEL_PORT_NUMBER` + +默认值:**26379**。设置 Sentinel 默认端口。 + + + +### 集群配置参数 + +使用 redis 镜像,可以很容易的建立一个 [redis](https://redis.apache.org/doc/r3.1.2/redisAdmin.html) 集群。针对 redis 的集群模式(复制模式),有以下参数可以配置: + +#### `REDIS_REPLICATION_MODE` + +默认值:**无**。当前主机在集群中的工作模式,可使用值为:`master`/`slave`/`replica`。 + +#### `REDIS_MASTER_HOST` + +默认值:**无**。作为`slave`/`replica`时,对应的 master 主机名或 IP 地址。 + +#### `REDIS_MASTER_PORT_NUMBER` + +默认值:**6379**。master 主机对应的端口。 + +#### `REDIS_MASTER_PASSWORD` + +默认值:**无**。master 主机对应的登录验证密码。 + + + +### 可选配置参数 + +如果没有必要,可选配置参数可以不用定义,直接使用对应的默认值,主要包括: + +#### `REDIS_BASE_DIR` + +默认值:**/usr/local/redis**。设置应用的默认基础目录。 + +#### `REDIS_DATA_DIR` + +默认值:**/srv/data/redis**。设置应用的默认数据存储目录。 + +#### `REDIS_DATA_LOG_DIR` + +默认值:**/srv/datalog/redis**。设置应用的默认数据日志目录。 + +#### `REDIS_CONF_DIR` + +默认值:**/srv/conf/redis**。设置应用的默认配置文件目录。 + +#### `REDIS_LOG_DIR` + +默认值:**/var/log/redis**。设置应用的默认日志目录。 + +#### `REDIS_DAEMON_USER` + +默认值:**redis**。设置应用的默认运行用户。 + +#### `REDIS_DAEMON_GROUP` + +默认值:**redis**。设置应用的默认运行用户组。 + +#### `REDIS_ALLOW_EMPTY_PASSWORD` + +默认值:**no**。设置是否允许无密码连接。如果没有设置`REDIS_PASSWORD`,则必须设置当前环境变量为 `yes`。 + +#### `REDIS_PASSWORD` + +默认值:**无**。客户端认证的密码。 + +#### `REDIS_PASSWORD_FILE` + +默认值:**无**。以绝对地址指定的客户端认证用户密码存储文件。该路径指的是容器内的路径。 + +#### `REDIS_MASTER_PASSWORD_FILE` + +默认值:**无**。以绝对地址指定的服务器密码存储文件。该路径指的是容器内的路径。 + + + +### SSL配置参数 + +使用证书加密传输时,相关配置参数如下: + +- `REDIS_TLS_ENABLED`: 启用或禁用 TLS。默认值:**no** + - `REDIS_TLS_PORT`: 使用 TLS 加密传输的端口。默认值:**6379** + - `REDIS_TLS_CERT_FILE`: TLS 证书文件。默认值:**无** + - `REDIS_TLS_KEY_FILE`: TLS 私钥文件。默认值:**无** + - `REDIS_TLS_CA_FILE`: TLS 根证书文件。默认值:**无** + - `REDIS_TLS_DH_PARAMS_FILE`: 包含 DH 参数的配置文件 (DH 加密方式时需要)。默认值:**无** + - `REDIS_TLS_AUTH_CLIENTS`: 配置客户端是否需要 TLS 认证。 默认值:**yes** + +当使用 TLS 时,则默认的 non-TLS 通讯被禁用。如果需要同时支持 TLS 与 non-TLS 通讯,可以使用参数`REDIS_TLS_PORT`配置容器使用不同的 TLS 端口。 + +1. 使用 `docker run`: + + ```console + $ docker run --name redis \ + -v /path/to/certs:/srv/cert/redis \ + -v /path/to/redis-data:/srv/data/redis \ + -e ALLOW_EMPTY_PASSWORD=yes \ + -e REDIS_TLS_ENABLED=yes \ + -e REDIS_TLS_CERT_FILE=/srv/cert/redis/redis.crt \ + -e REDIS_TLS_KEY_FILE=/srv/cert/redis/redis.key \ + -e REDIS_TLS_CA_FILE=/srv/cert/redis/redisCA.crt \ + colovu/redis:latest + ``` + +2. 使用 `docker-compose.yml` 配置文件,确保包含以下类似内容: + + ```yaml + services: + redis: + ... + environment: + ... + - REDIS_TLS_ENABLED=yes + - REDIS_TLS_CERT_FILE=/srv/cert/redis/redis.crt + - REDIS_TLS_KEY_FILE=/srv/cert/redis/redis.key + - REDIS_TLS_CA_FILE=/srv/cert/redis/redisCA.crt + ... + volumes: + - /path/to/certs:/srv/cert/redis + - /path/to/redis-data:/srv/data/redis + ... + ``` + + + +### 应用配置文件 + +应用配置文件默认存储在容器内:`/srv/conf/redis/redis.conf`。 + +#### 使用已有配置文件 + +Redis 容器的配置文件默认存储在数据卷`/srv/conf`中,文件名及子路径为`redis/redis.conf`。有以下两种方式可以使用自定义的配置文件: + +- 直接映射配置文件 + +```shell +$ docker run -d --restart always --name redis -v $(pwd)/redis.conf:/srv/conf/redis/redis.conf colovu/redis:latest +``` + +- 映射配置文件数据卷 + +```shell +$ docker run -d --restart always --name redis -v $(pwd):/srv/conf colovu/redis:latest +``` + +> 第二种方式时,本地路径中需要包含 redis 子目录,且相应文件存放在该目录中 + + + +#### 生成配置文件并修改 + +对于没有本地配置文件的情况,可以使用以下方式进行配置。 + +##### 使用镜像初始化容器 + +使用宿主机目录映射容器数据卷,并初始化容器: + +```shell +$ docker run -d --restart always --name redis -v /host/path/to/conf:/srv/conf colovu/redis:latest +``` + +or using Docker Compose: + +```yaml +version: '3.1' + +services: + redis: + image: 'colovu/redis:latest' + ports: + - '6379' + volumes: + - /host/path/to/conf:/srv/conf +``` + +##### 修改配置文件 + +在宿主机中修改映射目录下子目录`redis`中文件`redis.conf`: + +```shell +$ vi /path/to/redis.conf +``` + +##### 重新启动容器 + +在修改配置文件后,重新启动容器,以使修改的内容起作用: + +```shell +$ docker restart redis +``` + +或者使用 Docker Compose: + +```shell +$ docker-compose restart redis +``` + + + +## 安全 + +### 用户认证 + +Redis 镜像默认禁用了无密码访问功能,在实际生产环境中建议使用用户名及密码控制访问;如果为了测试需要,可以使用以下环境变量启用无密码访问功能: + +```shell +REDIS_ALLOW_EMPTY_PASSWORD=yes +``` + + + +通过配置环境变量`REDIS_PASSWORD`,可以启用基于密码的用户认证功能。命令行使用参考: + +``` +$ docker run -it -e REDIS_PASSWORD=colovu \ + colovu/redis:latest +``` + +使用 Docker Compose 时,`docker-compose.yml`应包含类似如下配置: + +``` +services: + redis: + ... + environment: + - REDIS_PASSWORD=colovu + ... +``` + + + +### 持久化数据存储 + +Redis 镜像默认配置了用于存储数据及数据日志的数据卷 `/srv/data`和`/srv/datalog`。可以使用宿主机目录映射相应的数据卷,将数据持久化存储在宿主机中。 + +> 注意:将数据持久化存储至宿主机,可避免容器销毁导致的数据丢失。同时,将数据存储及数据日志分别映射为不同的本地设备(如不同的共享数据存储)可提供较好的性能保证。 + + + +## 日志 + +默认情况下,Docker 镜像配置为将容器日志直接输出至`stdout`,可以使用以下方式查看: + +```bash +$ docker logs redis +``` + +使用 Docker Compose 管理时,使用以下命令: + +```bash +$ docker-compose logs redis +``` + + + +实际使用时,可以配置将相应信息输出至`/var/log`或`/srv/datalog`数据卷的相应文件中。 + + + +## 容器维护 + +### 容器数据备份 + +默认情况下,镜像都会提供`/srv/data`数据卷持久化保存数据。如果在容器创建时,未映射宿主机目录至容器,需要在删除容器前对数据进行备份,否则,容器数据会在容器删除后丢失。 + +如果需要备份数据,可以使用按照以下步骤进行: + +#### 停止当前运行的容器 + +如果使用命令行创建的容器,可以使用以下命令停止: + +```bash +$ docker stop redis +``` + +如果使用 Docker Compose 创建的,可以使用以下命令停止: + +```bash +$ docker-compose stop redis +``` + +#### 执行备份命令 + +在宿主机创建用于备份数据的目录`/path/to/back-up`,并执行以下命令: + +```bash +$ docker run --rm -v /path/to/back-up:/backups --volumes-from redis busybox \ + cp -a /srv/data/redis /backups/ +``` + +如果容器使用 Docker Compose 创建,执行以下命令: + +```bash +$ docker run --rm -v /path/to/back-up:/backups --volumes-from `docker-compose ps -q redis` busybox \ + cp -a /srv/data/redis /backups/ +``` + + + +### 容器数据恢复 + +在容器创建时,如果未映射宿主机目录至容器数据卷,则容器会创建私有数据卷。如果是启动新的容器,可直接使用备份的数据进行数据卷映射,命令类似如下: + +```bash +$ docker run -v /path/to/back-up:/srv/data colovu/redis:latest +``` + +使用 Docker Compose 管理时,可直接在`docker-compose.yml`文件中指定: + +```yaml +redis: + volumes: + - /path/to/back-up:/srv/data +``` + + + +### 镜像更新 + +针对当前镜像,会根据需要不断的提供更新版本。针对更新版本(大版本相同的情况下,如果大版本不同,需要参考指定说明处理),可使用以下步骤使用新的镜像创建容器: + +#### 获取新版本的镜像 + +```bash +$ docker pull colovu/redis:TAG +``` + +这里`TAG`为指定版本的标签名,如果使用最新的版本,则标签为`latest`。 + +#### 停止容器并备份数据 + +如果容器未使用宿主机目录映射为容器数据卷的方式创建,参照`容器数据备份`中方式,备份容器数据。 + +如果容器使用宿主机目录映射为容器数据卷的方式创建,不需要备份数据。 + +#### 删除当前使用的容器 + +```bash +$ docker rm -v redis +``` + +使用 Docker Compose 管理时,使用以下命令: + +```bash +$ docker-compose rm -v redis +``` + +#### 使用新的镜像启动容器 + +将宿主机备份目录映射为容器数据卷,并创建容器: + +```bash +$ docker run --name redis -v /path/to/back-up:/srv/data colovu/redis:TAG +``` + +使用 Docker Compose 管理时,确保`docker-compose.yml`文件中包含数据卷映射指令,使用以下命令启动: + +```bash +$ docker-compose up redis ``` ## 注意事项 -- 容器中Redis启动参数不能配置为后台运行,只能使用前台运行方式,即:`daemonize no` +- 容器中 Redis 启动参数不能配置为后台运行,只能使用前台运行方式,即:`daemonize no` - 如果应用使用后台方式运行,则容器的启动命令会在运行后自动退出,从而导致容器退出 diff --git a/docker-compose-cluster.yml b/docker-compose-cluster.yml new file mode 100644 index 0000000..720dbd2 --- /dev/null +++ b/docker-compose-cluster.yml @@ -0,0 +1,27 @@ +version: '3.6' + +# 可以使用 scale 动态扩容容器:docker-compose up -d --scale redis-primary=1 --scale redis-replica=3 + +services: + redis-primary: + image: 'colovu/redis:latest' + ports: + - '6379:6379' + environment: + - REDIS_REPLICATION_MODE=master + - REDIS_PASSWORD=colovu + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + + redis-replica: + image: 'colovu/redis:latest' + ports: + - '6379' + environment: + - REDIS_REPLICATION_MODE=slave + - REDIS_MASTER_HOST=redis-primary + - REDIS_MASTER_PORT_NUMBER=6379 + - REDIS_MASTER_PASSWORD=colovu + - REDIS_PASSWORD=colovu + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + depends_on: + - redis-primary \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f04832d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: '3.6' + +services: + redis: + image: 'colovu/redis:latest' + ports: + - '6379:6379' + environment: + # REDIS_ALLOW_EMPTY_PASSWORD is recommended only for development. + - REDIS_ALLOW_EMPTY_PASSWORD=yes + - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL diff --git a/img/redis-white.png b/img/redis-white.png new file mode 100644 index 0000000000000000000000000000000000000000..df242116ab73728357219b296ac4b4122ec211cd GIT binary patch literal 2794 zcmaJ@c{CJi8=oP}l+0LSW{fe$zE4P&LWaS}@S*I?Si>j^S#CGWghVqUOKHlMgba$} zqA>O?TPWLQlqE8*LgbrszjN+i-?_hYp7;4Z=l7oX`JLxHf4sNth!)3>B8~z8fa6w{ zX7=3tjT?3#UhWCa0TBTJAi?guqdB)MmKL8>l{q{-{J*3{9{DfoKT(i#2%qe6iJJ79hRac%4A^WG7^;-i5D`kDh!+{3*&aL zm4&^Mg};(Typn^zmP0hkNjAzOn&lK2f;^{M?y`hHaI1A%qQn{{?{<@!Nbe617e zxJKf#i)wi$1V2CscKSUlzm({a@Dw(+#XI%PK3>1<8*aR%ZhOa243_6fA75SGm6zEU za_Q#{tCh<25%|zORJVTub?pjqib@>Na2K+nUX38{Ez~Rv%4&6fGxjZnG#U9W7W@Hz zq~k8UF_=-@6xkoMC<|reW(JxGdz3#q0ksqL;)$G|dx~;{ zYqZPW`t`Y`)e+e^Cfrk^v00L0s`v_DG@X6c<=V9P;qGGz`=iKN_uPZuBE_^@an&K~rt|E=O@+~pSoUdbpRRkXYCdfwNS4lolurs*Lp zab?-ponGGJMKO1VZ0;ww>~!{RX9j^RCyFTHC5HGp#!q75>O6<4bvOU#)_AtbL|c9A zr^LMtpN!C)IG&oR4p1Xjv1RJdcc7bF$0QwgD~#3j-7~&9(V2gIZmvzqf1jmwl`CqRZ* zBKwA8V)PNre0D(L99+@PsPb`rTV>gF(A>S$Yue$Lw_h)gT!0E~(<|i#?+`CJf4u~k zJb#VI$;KAu@>7d$NgNJBCB2Zgu<9#^{T0S4$AW{FL}MCPXt2bVbP8oG5oQ*mkV5EhSShbka_SRg*~@p_v~l2pv#>usHmRprZ$sgOsZR|WEijJ}_4>U)59KR_L1!du$Fwz4*ZqQymtRr8 zW$EsO(66HEH2=@`Nn}$9foj7^_gew0-{<8Oz0R;4$AH&f3Y*u74cV*3Mny`O90O~v zV%}#@48xbdFIFxJG#_a!O*}Hb@i9L zv8|dd7$+J6nFdJfdg<@v)e8b+o~5S(1C&TDNE@?bD~0Nf{#mee-WgJUpFEh10_7hN$r z96$8uMGkZHWPC`LsuW&r#yrI0yrT8!#mIoz@!{KPe(w}WcV*MEldr2eirfRxV7!BDyJZk%snhO%exoWN|RThoaWI{KJPBUn3ElVBtn zOo=s~3s0c}Krs#R1=O|)mT$51v{;Fiuq~wDGWgcR@~D_+xE}L5Rf}N}ifL0;vWfk* zM;iOTaX0F2Yo92dmG6k)E1uX5#hPrvGuKtG8c_;pMXrd;rpeRyljWI+ok06$AoNF4 z0tz|VDL6L^02zg4CjSAXo6Q19fQ)nnEMRC>H2KG&6it=qqIIaKsVEGX=BJGQwldFe zawZ^N1#y9N4jbA}tf)F|c*&D+9@ESV7Sy)|euRqe4JruOsPbRWsMV2)XJsYlwmYIw zGh&}Q??U2JmoSn;Eb-m+(p4Y#_1F}vsGFU4K7AF*DI3!8n(y!r02XPNTlyANy?Hh= zxuW*_x0|@Io5EqW`wx!QRkS%X&PiTB4ZmL9g`WaAzj1^mm8dQZBnE&2V3V-vNy&0; z10RtGHl5?$wV|aZj4Ox1D%OKsWy}9 zoCNC>aZXWe!<5AwdGI#L#(o>596w!CatC1c{VUgLc;tQG=ZC!0fCY%ZzrvNR;RC8I c48Jc>-ma&n>?yFx{bm8I%!y_%Oi2m<1)N(d$^ZZW literal 0 HcmV?d00001