技术之道

长风破浪会有时,直挂云帆济沧海

  • 首页
  • 分类
  • 归档
  • 标签

  • 搜索
服务治理 k8s tabnine cursor github copilot ai chatgpt chatgpt ai sop 技术选型 bigdata 工具 多进程多线程 docker 计算机网络 mysql 事务 基础架构 kafka nio 分布式 服务搭建 监控 jvm 管理/成长 jenkins devops 云原生 nginx 架构 故障处理 hive spark mapreduce apm redis memcached java 性能 linux

Redis On SSD方案

发表于 2022-08-23 | 分类于 中间件 | 0 | 阅读次数 465

Redis On SSD方案

基础组件

现状

Redislabs的Redis On Flash(https://redislabs.com/lp/redis-enterprise-flash/),

360的pika(https://github.com/Qihoo360/pika)

美图的kvrocks(https://github.com/bitleak/kvrocks),

技术选型

其中Redis On Flash是商业化的产品,无开源代码,pika市面上使用的公司比较多,但缺点也很明显:

  • 面向客户端的协议是Redis的二进制协议,而面向复制的却是基于google的protobuf格式,语义层面有割裂感。
  • 复制是基于Rsync的多进程模式,这种复制模式比较重,出现问题也不好定位。
  • 代码风格比较乱,此外网络类库也用的是360自家的pink,二次开发比较困难。

kvrocks和 Pika 有什么不一样?

  • API 设计上更加兼容 Redis 原始语义,全部数据类型在同一个 DB, 不允许同一个 key 在不同类型中重复出现。
  • 支持 Namespace 对不同业务数据做隔离
  • 主从同步不适用 Rsync, 同步设计简单且问题定位也简单
  • 支持对慢请求 profiling,问题定位更加简单
  • 代码更加简洁 (主观看法)

最终方案

kvrocks

kvrocks

安装部署

Supported platforms

  • centos 6/7
  • ubuntu
  • macosx

requirements

  • g++ (required by c++11, version >= 4.8)
  • autoconf automake libtool

Build

NOTE: You shoud install the snappy first:

# Centos/Redhat
sudo yum install -y snappy snappy-devel autoconf automake libtool

# Ubuntu
sudo apt-get install libsnappy-dev autoconf automake libtool

# MACOSX
brew install snappy
$ git clone --recursive https://github.com/bitleak/kvrocks.git
$ cd kvrocks
$ make -j4

run

$ ./src/kvrocks -c kvrocks.conf

支持命令

String Commands

Command Supported OR Not Desc
get √
getrange √
getset √
incr √
incrby √
incrbyfloat √
mget √
mset √
msetnx √
psetex √ only supports second
set √
setex √
setnx √
setrange √
strlen √

Hash Commands

Command Supported OR Not Desc
hdel √
hexists √
hget √
hgetall √
hincrby √
hincrbyfloat √
hkeys √
hlen √
hmget √
hmset √
hset √
hsetnx √
hstrlen √
hvals √
hscan √

List Commands

Command Supported OR Not Desc
blpop √
brpop √
brpoplpush X
lindex √ Caution: linsert is O(N) operation, don’t use it when list was extreme long
linsert √
llen √
lpop √
lpush √
lpushx √
lrange √
lrem √ Caution: lrem is O(N) operation, don’t use it when list was extreme long
lset √
ltrim √ Caution: ltrim is O(N) operation, don’t use it when list was extreme long
rpop √
rpoplpush √
rpush √
rpushx √

Set Commands

Command Supported OR Not Desc
sadd √
scard √
sdiff √
sdiffstore √
sinter √
sinterstore √
sismember √
smembers √
smove √
spop √ pop the member with key oreder
srandmember √ always first N members if not changed
srem √
sunion √
sunionstore √
sscan √

ZSet Commands

Command Supported OR Not Desc
bzpopmin X
bzpopmax X
zadd √
zcard √
zcount √
zincrby √
zinterstore √
zlexcount √
zpopmin √
zpopmax √
zrange √
zrangebylex √
zrangebyscore √
zrank √
zrem √
zremrangebylex √
zremrangebyrank √
zremrangebyscore √
zrevrange √
zrevrangebylex X
zrevrangebyscore √
zscan √
zscore √
zmscore √ multi zscore
zunionscore √

Key Commands

Command Supported OR Not Desc
del √
dump X
exists √
expire √
expireat √
keys √
persist √
pexpire √ precision is seconds
pexpireat √ precision is seconds
pttl √
ttl √
type √
scan √
rename X
randomkey √

Bit Commands

Command Supported OR Not Desc
getbit √
setbit √
bitcount √
bitpos √
bitfield X
bitop X

NOTE : String and Bitmap is different type in kvrocks, so you can’t do bit with string, vice versa.

Pub/Sub Commands

Command Supported OR Not Desc
psubscribe √
publish √
pubsub √
punsubscribe √
subscribe √
unsubscribe √

Sortedint Commands

Command Supported OR Not Desc
sicard √ like scard
siadd √ like sadd, but member is int
sirem √ like srem, but member is int
sirange √ sirange key offset count cursor since_id
sirevrange √ sirevrange key offset count cursor max_id
siexists √ siexists key member1 (member2 …)

Administrator Commands

Command Supported OR Not Desc
monitor √
info √
config √
dbsize √
namespace √
flushdb √
flushall √

NOTE : The db size was updated async after execute dbsize scan command

GEO Commands

Command Supported OR Not Desc
geoadd √
geodist √
geohash √
geopos √
georadius √
georadiusbymember √

Hyperloglog Commands

Not Supported

多租户

https://github.com/bitleak/kvrocks/blob/master/docs/multi-tenant.CN.md

名称空间用于隔离用户之间的数据。与通过requirepass访问所有redis数据库不同,我们为每个命名空间使用一个令牌。clients通过令牌来访问redis,而requirepass已升级为管理员令牌,只有管理员令牌才允许访问命名空间命令,以及某些命令,例如config,slaveof,bgave等…

# add token
127.0.0.1:6666>  namespace add ns1 mytoken
OK

# update token
127.0.0.1:6666> namespace set ns1 new_token
OK

# list namespace
127.0.0.1:6666> namespace get *
1) "ns1"
2) "new_token"
3) "__namespace"
4) "foobared"

# delete namespace
127.0.0.1:6666> namespace del ns1
OK

kvrocks 允许通过一个实例在线增加或者减少 token, 每个 token 之间的数据是隔离的。 实现上也比较简单,在分配 token 的时候关联一个业务标识(Namespace), 在业务写入数据的时候会自动在 key 前面增加这个标识,读取数据 key 的时候自动去掉标识。

假设我们配置了一个 namespace N1 对应 token T1, 当业务使用这个 token 执行 SET a 1, 那么在存储里面实际上会变成类似 T1|a => 1 ,读取数据 key 的时候会自动去掉 T1。

对应Java代码实现:

public static void testRedis() {
    //连接本地的 Redis 服务
    Jedis jedis = new Jedis("192.168.8.95", 6379);
    // 如果 Redis 服务设置来密码,需要下面这行,没有就不需要
    jedis.auth("T1");
    System.out.println("连接成功");
    //查看服务是否运行
    System.out.println("服务正在运行: " + jedis.ping());
    jedis.set("a", "1");
    System.out.println(jedis.get("a"));
}

参数定义

参数名 默认值 描述 需要调整
bind 0.0.0.0 默认情况下,kvrocks监听来自所有网络接口的连接在服务器上可用。可以只听一个或多个接口使用“bind”配置指令,后面跟着一个or更多IP地址。 是
port 6666 接受指定端口上的连接 是
timeout 0 在客户端空闲N秒后关闭连接
workers 8 工作线程的数量的增加或减少会影响性能.一般CPU核数-2 是
repl-workers 1 复制工作线程的数量,增加或减少它将影响复制性能 否
daemonize no 默认情况下,kvrocks不作为守护进程运行。如果你需要的话,用yes。注意kvrocks将在/var/run/kvrocks.中写入一个pid文件当监控pid 是
maxclients 10000 设置同时连接的客户端的最大数量。默认情况下这个限制被设置为10000个客户端,但是如果配置超过操作系统进程文件限制,此配置无效。一旦达到限制,服务器将关闭所有发送的新连接,错误“达到的最大客户数量” 是
requirepass foobared redis-cli操作管理员密码 是
masterauth foobared master-slave之间身份验证。如果配置了requirepass, 必须配置此参数=requirepass 是
db-name change.me.db 主缓冲复制将检查数据库名称是否匹配。如果没有,slave应该拒绝从主服务器同步数据库。不要使用默认值,设置db-name来标识集群 是
dir /tmp/kvrocks 工作目录。DB将写入到这个目录中,注意,这里必须指定目录,而不是文件名。 是
pidfile /var/run/kvrocks.pid 当以daemonized运行时,kvrocks在${CONFIG_DIR}/kvrocks中写入一个pid文件。您可以在这里指定自定义pid文件位置。 是
slave-read-only yes 从节点只读 否
slave-priority 100 用来主从选举参数, 较低优先级可升级为master。如果有三个优先级为10,100,25的slave,哨兵就会选择优先级为10的那一个,那是最低的 否
tcp-backlog 511 backlog是tcp一个连接队列,tcp三次握手后先添加到队列中再处理 是
repl-bind 0.0.0.0 绑定从节点 否
slave-serve-stale-data yes 当从服务器失去与主服务器的连接时,或者当复制时仍在进行中,slave可以以两种不同的方式行动:
1) 如果slave-serve- stal- data设置为‘yes’(默认),那么slave将会仍然回复客户端请求,可能使用过期的数据,或者如果是第一次同步,数据集可能是空的。
2)如果slave-serve- stal- data设置为“no”,slave将回答为所有类型的命令都出现了“与正在进行中的主同步”的错误
否
max-replication-mb 0 复制应该使用的最大允许速率(MB/s)。如果速率超过最大复制mb,复制将会变慢。默认值:0(即没有限制) 否
max-io-mb 500 允许的刷新和压缩的最大聚合写入速率(MB/s)。如果速率超过最大io-mb, io将会变慢。0没有限制,默认值:500 否
max-db-size 0 RocksDB应该使用的最大允许空间(GB)。如果SST文件的总大小超过max_allowed_space,写入RocksDB将会失败。
请参见:https://github.com/facebook/rocksdb/wiki/Managing-Disk-Space-Utilization
默认值:0(即没有限制)
否
max-backup-to-keep 1 要保留的最大备份,服务器cron将每分钟运行一次,以检查当前的数量备份,如果超过要保留的最大备份num,则清除旧备份。如果为0,则不保留备份。 否
max-backup-keep-hours 168 保存备份的最长时间。如果max-backup-keep-hours为0,则不会清除任何备份。
默认值:1周
否
codis-enabled no 使kvrocks支持codis协议,如果db在第一次打开时启用了codis模式,此选项在重启后不能被禁用,反之亦然 codis集群使用
slowlog-log-slower-than 100000 慢查时间 是
slowlog-max-len 128 慢查存储长度 是
compact-cron 0 3 * * * 每天凌晨3点,压缩DB,执行bgsave保存DB数据 是
compaction-checker-range 0-7 压缩检查器将处于活动状态的时间范围。意味压缩检测会再每天0~7点时间段 否
rocksdb.metadata_block_cache_size 2048MB
rocksdb.subkey_block_cache_size 2048MB
rocksdb.max_open_files 4096
rocksdb.write_buffer_size 64MB
rocksdb.target_file_size_base 256MB
rocksdb.max_write_buffer_number 4
rocksdb.max_background_flushes 4
rocksdb.max_sub_compactions 2
rocksdb.wal_ttl_seconds 3600
rocksdb.wal_size_limit_mb 100GB
rocksdb.block_size 4KB
rocksdb.cache_index_and_filter_blocks no
rocksdb.compression snappy
rocksdb.compaction_readahead_size 2MB
rocksdb.delayed_write_rate 0
rocksdb.enable_pipelined_write no
rocksdb.level0_slowdown_writes_trigger 20
rocksdb.stats_dump_period_sec 0
rocksdb.disable_auto_compactions no

主从同步

原理

Redis的主从复制模式可以将主节点的数据改变同步给从节点, 这样从节点就可以起到两个作用: 第一, 作为主节点的一个备份, 一旦主节点出了
故障不可达的情况, 从节点可以作为后备“顶”上来, 并且保证数据尽量不丢失(主从复制是最终一致性) 。 第二, 从节点可以扩展主节点的读能力, 一
旦主节点不能支撑住大并发量的读操作, 从节点可以在一定程度上帮助主节点分担读压力

架构图

一主一从

image-20200824115337402

一主多从(星形结构)

image-20200824121526523

一主多从(树状主从结构)

image-20200824121801004!

主从命令

image-20200824140835087

kvrocks2个进程,分别占用6379、6679 2个端口。

image-20200824141000284

设置主从

image-20200824141117372

主从切换操作:

image-20200824141808743-1661219502592

缺点

  • 一旦主节点出现故障, 需要手动将一个从节点晋升为主节点, 同时需要修改应用方的主节点地址, 还需要命令其他从节点去复制新的主节点, 整
    个过程都需要人工干预
  • 主节点的写能力受到单机的限制
  • 主节点的存储能力受到单机的限制

哨兵

原理

  • 监控: Sentinel节点会定期检测Redis数据节点、 其余Sentinel节点是否可达
  • 通知: Sentinel节点会将故障转移的结果通知给应用方
  • 主节点故障转移: 实现从节点晋升为主节点并维护后续正确的主从关系
  • 配置提供者: 在Redis Sentinel结构中, 客户端在初始化的时候连接的是Sentinel节点集合, 从中获取主节点信息

架构图

image-20200824145157401

安装部署

  1. 下载redis安装包,拷贝sentinel到/usr/local/bin下

image-20200824145800782

  1. 修改配置

    port 26379 # 端口
    daemonize yes # 后台运行
    pidfile "/root/sentinel-01/redis-sentinel.pid" # 进程ID
    dir "/root/sentinel-01" # 工作目录
    sentinel monitor mymaster 192.168.8.95 6379 2 # Sentinel节点要监控的是一个名字叫做<master-name>, ip地址和端口为<ip><port>的主节点。 <quorum>代表要判定主节点最终不可达所需要的票数。<quorum>参数用于故障发现和判定, 例如将quorum配置为2, 代表至少有2个Sentinel节点认为主节点不可达, 那么这个不可达的判定才是客观的。对于<quorum>设置的越小, 那么达到下线的条件越宽松, 反之越严格。 一般建议将其设置为Sentinel节点的一半加1。
    
    
  2. 启动哨兵

    redis-sentinel /root/sentinel-01/sentinel.conf
    

常用命令

sentinel masters

展示所有被监控的主节点状态以及相关的统计信息

sentinel master

展示指定的主节点状态以及相关的统计信息

sentinel slaves

展示指定的从节点状态以及相关的统计信息

sentinel sentinels

展示指定的Sentinel节点集合(不包含当前Sentinel节点)

sentinel failover

对指定主节点进行强制故障转移(没有和其他Sentinel节点“协商”) , 当故障转移完成后, 其他Sentinel节点按照故障转移的结果更新自身配置, 这个命令在Redis Sentinel的日常运维中非常有用

sentinel ckquorum

检测当前可达的Sentinel节点总数是否达到的个数。 例如quorum=3, 而当前可达的Sentinel节点个数为2个, 那么将无法进行故障转移, Redis Sentinel的高可用特性也将失去

sentinel flushconfig

将Sentinel节点的配置强制刷到磁盘上, 这个命令Sentinel节点自身用得比较多, 对于开发和运维人员只有当外部原因(例如磁盘损坏) 造成配置文件损坏或者丢失时, 这个命令是很有用的

sentinel remove

取消当前Sentinel节点对于指定主节点的监控

注:这个命令仅仅对当前Sentinel节点有效

sentinel monitor

这个命令和配置文件中的含义是完全一样的, 只不过是通过命令的形式来完成Sentinel节点对主节点的监控

Redis Sentinel客户端的基本步骤

  1. 遍历Sentinel节点集合获取一个可用的Sentinel节点, 后面会介绍Sentinel节点之间可以共享数据, 所以从任意一个Sentinel节点获取主节点信息都是可以的

image-20200824152341996

  1. 通过sentinel get-master-addr-by-name master-name这个API来获取对应主节点的相关信息

image-20200824152402490

  1. 验证当前获取的“主节点”是真正的主节点, 这样做的目的是为了防止故障转移期间主节点的变化

  2. 保持和Sentinel节点集合的“联系”, 时刻获取关于主节点的相关“信息”

image-20200824152447745

相关代码调用

public static void sentinel() {
    Set<String> sentinels = new HashSet<>();
    sentinels.add("192.168.8.95:26379");
    sentinels.add("192.168.8.95:26380");
    sentinels.add("192.168.8.95:26381");
    //创建JedisSentinelPool
    JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
    int count=0;
    //测试死循环的情况下主服务器出现宕机的情况下sentinel发生故障转移的测试
    while(true){
        count ++;
        Jedis jedis = null;
        try{
            jedis = sentinelPool.getResource();
            int index = new Random().nextInt();
            //对redis保存key和value
            String key = "k-" + index;
            String value = "v-" + index;
            jedis.set(key,value);
            if (count % 100 == 0) {
                //打印日志信息
                System.out.println(String.format("key:%s,value:%s", key, jedis.get(key)));
            }
            //睡眠时间
            TimeUnit.MILLISECONDS.sleep(10);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis!=null){
                jedis.close();
            }
        }

    }

}

缺点

  • 主节点的写能力受到单机的限制
  • 主节点的存储能力受到单机的限制

扩缩容(主从/哨兵模式)

  1. 新购集群,集群同步slave2节点数据

image-20200824152447745-1661219611060

  1. 判断slave2节点数据offset与新建集群offset基本一致

image-20200827183159594

  1. 切换slave2为master, 移除原集群master和slave-1

image-20200827183524674

  1. 从新集群选Master节点,移除slave-2

image-20200827183619828

Codis

由于zk和codis的组建开销,该方案比较适合做大集群多租户方案

如何使用

  1. 客户端直接通过域名+端口连接和单机redis连接没有区别
  2. 也可以通过zk获取可用proxy进行连接 - 备选
  3. codis也提供java版客户端jodis - 备选

部署方案

lADPD4d8qRPbRavNA9nNBEE_1089_985.jpg_720x720q90g

Codis 分片原理

  • Codis会把所有的key分成1024个槽, 这1024个槽对应着的就是Redis的集群(Group),这个在Codis中是会在内存中维护着这1024个槽与Redis实例的映射关系
  • 槽是可以配置,可以设置成 2048 或者是4096个。Redis的节点数量偏多的话,可以设置槽多一些
  • 分片算法,先是把key进行CRC32 后,得到一个32位的数字,然后再hash%1024后得到一个余数,这个值就是这个key对应着的槽

Codis 3.x 组件简介

  1. Codis Server:基于 redis-3.2.8 分支开发。增加了额外的数据结构,以支持 slot 有关的操作以及数据迁移指令
  2. Codis Proxy:客户端连接的 Redis 代理服务, 实现了 Redis 协议。 除部分命令不支持以外(不支持的命令列表),表现的和原生的 Redis 没有区别(就像 Twemproxy)。
    • 对于同一个业务集群而言,可以同时部署多个 codis-proxy 实例;
    • 不同 codis-proxy 之间由 codis-dashboard 保证状态同步。
  3. Codis Dashboard:集群管理工具,支持 codis-proxy、codis-server 的添加、删除,以及据迁移等操作。在集群状态发生改变时,codis-dashboard 维护集群下所有 codis-proxy 的状态的一致性。
    • 对于同一个业务集群而言,同一个时刻 codis-dashboard 只能有 0个或者1个;
    • 所有对集群的修改都必须通过 codis-dashboard 完成。
  4. Codis Admin:集群管理的命令行工具。
    • 可用于控制 codis-proxy、codis-dashboard 状态以及访问外部存储。
  5. Codis FE:集群管理界面。
    • 多个集群实例共享可以共享同一个前端展示页面;
    • 通过配置文件管理后端 codis-dashboard 列表,配置文件可自动更新。
  6. Storage:为集群状态提供外部存储。
    • 提供 Namespace 概念,不同集群的会按照不同 product name 进行组织;
    • 目前仅提供了 Zookeeper、Etcd、Fs 三种实现,但是提供了抽象的 interface 可自行扩展。

Codis 主从切换问题

  • 对下层的 redis 实例来说,当一个 group 的 master 挂掉的时候,应该让管理员清楚,并手动的操作,因为这涉及到了数据一致性等问题(redis的主从同步是最终一致性的)
  • 因此 codis 不会自动的将某个 slave 升级成 master。
  • 关于外部 codis-ha 工具(具体可以参考之前的章节),这是一个通过 codis-dashboard 开放的 RESTful API 实现自动切换主从的工具。
  • 该工具会在检测到 master 挂掉的时候主动应用主从切换策略,提升单个 slave 成为新的 master。
  • 需要注意,codis 将其中一个 slave 升级为 master 时,该组内其他 slave 实例是不会自动改变状态的,这些 slave 仍将试图从旧的 master 上同步数据,因而会导致组内新的 master 和其他 slave 之间的数据不一致。因此当出现主从切换时,需要管理员手动创建新的 sync action 来完成新 master 与 slave 之间的数据同步(codis-ha 不提供自动操作的工具,因为这样太不安全了)。

Codis-dashboard配置

coordinator_name = "zookeeper"
coordinator_addr = "127.0.0.1:2181"
coordinator_auth = ""
# Set Codis Product Name/Auth.
product_name = "codis-ouyang"
product_auth = "teddy"
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:18080"
# Set arguments for data migration (only accept 'sync' & 'semi-async').
migration_method = "semi-async"
migration_parallel_slots = 100
migration_async_maxbulks = 200
migration_async_maxbytes = "32mb"
migration_async_numkeys = 500
migration_timeout = "30s"
# Set configs for redis sentinel.
sentinel_client_timeout = "1s"
# 将这个主服务器判断为失效至少需要 1 个 Sentinel 同意
sentinel_quorum = 1
# 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步
sentinel_parallel_syncs = 1
# 指定了 Sentinel 认为服务器已经断线所需的毫秒数(判定为主观下线SDOWN)。
sentinel_down_after = "2s"
sentinel_failover_timeout = "5m"

codis-dashboard启动

nohup /root/codis3.2.2/codis-dashboard --ncpu=4 --config=dashboard.toml --log=./dashboard.log --log-level=DEBUG &

Codis- Proxy配置

# Set Codis Product Name/Auth.
product_name = "codis-ouyang"
product_auth = "teddy"

# Set auth for client session
#   1. product_auth is used for auth validation among codis-dashboard,
#      codis-proxy and codis-server.
#   2. session_auth is different from product_auth, it requires clients
#      to issue AUTH <PASSWORD> before processing any other commands.
session_auth = "codis-client-auth-teddy"

# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:11080"

# Set bind address for proxy, proto_type can be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
proto_type = "tcp4"
proxy_addr = "0.0.0.0:19000"

# Set jodis address & session timeout
#   1. jodis_name is short for jodis_coordinator_name, only accept "zookeeper" & "etcd".
#   2. jodis_addr is short for jodis_coordinator_addr
#   3. jodis_auth is short for jodis_coordinator_auth, for zookeeper/etcd, "user:password" is accepted.
#   4. proxy will be registered as node:
#        if jodis_compatible = true (not suggested):
#          /zk/codis/db_{PRODUCT_NAME}/proxy-{HASHID} (compatible with Codis2.0)
#        or else
#          /jodis/{PRODUCT_NAME}/proxy-{HASHID}
jodis_name = "zookeeper"
jodis_addr = "127.0.0.1:2181"
jodis_auth = ""
jodis_timeout = "20s"
jodis_compatible = false

# Set datacenter of proxy.
proxy_datacenter = ""

# Set max number of alive sessions.
proxy_max_clients = 1000

# Set max offheap memory size. (0 to disable)
proxy_max_offheap_size = "1024mb"

# Set heap placeholder to reduce GC frequency.
proxy_heap_placeholder = "256mb"

# Proxy will ping backend redis (and clear 'MASTERDOWN' state) in a predefined interval. (0 to disable)
backend_ping_period = "5s"

# Set backend recv buffer size & timeout.
backend_recv_bufsize = "128kb"
backend_recv_timeout = "30s"

# Set backend send buffer & timeout.
backend_send_bufsize = "128kb"
backend_send_timeout = "30s"

# Set backend pipeline buffer size.
backend_max_pipeline = 20480

# Set backend never read replica groups, default is false
backend_primary_only = false

# Set backend parallel connections per server
backend_primary_parallel = 1
backend_replica_parallel = 1

# Set backend tcp keepalive period. (0 to disable)
backend_keepalive_period = "75s"

# Set number of databases of backend.
backend_number_databases = 16

# If there is no request from client for a long time, the connection will be closed. (0 to disable)
# Set session recv buffer size & timeout.
session_recv_bufsize = "128kb"
session_recv_timeout = "30m"

# Set session send buffer size & timeout.
session_send_bufsize = "64kb"
session_send_timeout = "30s"

# Make sure this is higher than the max number of requests for each pipeline request, or your client may be blocked.
# Set session pipeline buffer size.
session_max_pipeline = 10000

# Set session tcp keepalive period. (0 to disable)
session_keepalive_period = "75s"

# Set session to be sensitive to failures. Default is false, instead of closing socket, proxy will send an error response to client.
session_break_on_failure = false

# Set metrics server (such as http://localhost:28000), proxy will report json formatted metrics to specified server in a predefined period.
metrics_report_server = ""
metrics_report_period = "1s"

# Set influxdb server (such as http://localhost:8086), proxy will report metrics to influxdb.
metrics_report_influxdb_server = ""
metrics_report_influxdb_period = "1s"
metrics_report_influxdb_username = ""
metrics_report_influxdb_password = ""
metrics_report_influxdb_database = ""

# Set statsd server (such as localhost:8125), proxy will report metrics to statsd.
metrics_report_statsd_server = ""
metrics_report_statsd_period = "1s"
metrics_report_statsd_prefix = ""

Codis- Proxy启动

# 启动
nohup /root/codis3.2.2/codis-proxy --ncpu=4 --config=proxy.toml --log=proxy.log --log-level=WARN &
# 加入集群
./codis-admin --dashboard=127.0.0.1:18080  --create-proxy --addr=192.168.8.96:11080

容灾

  • 多个实例部署codis-proxy保证服务器可用
  • codis-proxy由SLB提供负载均衡,提供健康检测
  • kvrocks一主一从,redis-sentinal保证主从切换服务可用

扩容

新实例部署完kvrocks后通过codis-admin执行如下命令进行扩容, 也可以通过Codis-FE管理界面操作

# 创建组
./codis-admin --dashboard=127.0.0.1:18080 --create-group --gid=4 ## gid 新组id, 递增
# 将kvrocks加入组  
./codis-admin --dashboard=127.0.0.1:18080 --group-add --gid=4 --addr=192.168.8.95:6379 # master
./codis-admin --dashboard=127.0.0.1:18080 --group-add --gid=4 --addr=192.168.8.96:6379 # slave
# slot 自动负载均衡
./codis-admin --dashboard=127.0.0.1:18080 --rebalance --confirm
# sentinel 监控同步新的group
 ./codis-admin --dashboard=127.0.0.1:18080 --sentinel-resync

多租户

kvrocks本身支持多租户但由于codis不支持多租户所以需要进行二次开发支持, 根据不同的requirepass区分不同用户

优点

  • 支持 slot 同步迁移、异步迁移和并发迁移,对 key 大小无任何限制

  • 基于 redis-sentinel 实现主备自动切换

  • 提供了更加友好的 dashboard 和 fe 界面

  • 配置简单、扩容方便,可以实现自动扩容迁移分桶数据

缺点

  • 不再支持更新,最近一次更新在2018.7.29
  • 不支持多租户,无法配合使用kvrocks的多租户功能
  • 集群配置中心使用 zk 来实现,意味着在部署上增加了 zk 运维的代价
  • 增加了 Proxy 作为中转层,所有在网络开销上要比单个 Redis 大

问题

  1. 当业务出现故障出现大量生产消耗连接数可能会对其他业务有影响
  2. Codis需要二次开发,包括支持多租户,Proxy健康检测等功能

成本核算

初步建议配置:

Codis、ZK组件规格:2 vCPU 2 GiB,密集计算型 ic5,Centos 8.2 64,高效云盘100GB ¥143.5每月

KVRocks实例规格:2 vCPU 2 GiB,密集计算型 ic5,Centos 8.2 64,ESSD云盘100GB,PL1 IOPS五万,¥189每月

  • 1台实例部署: codis-dashboard、codis-fe、codis-admin
  • 3台实例部署:codis-proxy + redis-sentinel + zookeeper
  • 6台实例部署:3个kvrocks集群(一主一从)
  • 负载均衡SLB: 标准2, 支持连接数: 100000,新建连接数 (CPS): 10000,每秒查询数 (QPS): 10000, ¥285.00每月

总计: 1426

差不多价格的Redis规格 ¥1,610 :

  • Redis 5.0架构类型:集群版分片数:4分片节点类型:双副本实例规格:24G集群版(4节点)
  • 40000 最大连接数:40000 每分片带宽:96MByte 最大内网带宽:384MByte

数据迁移

  • 迁移redis数据到kvrocks

    redis-migrate-tool

    ​ kvrocks官方文档介绍方案,但通过测试数据迁移不成功

    RedisShake

    redis-shake是阿里云Redis&MongoDB团队开源的用于redis数据同步的工具。

    ​ 支持源redis到目的redis数据同步

监控

kvrocks监控

redis_exporter方案

https://github.com/oliver006/redis_exporter

codis-proxy监控

性能压测

基本压测

测试环境

8vCPU, 8G内存 SSD磁盘 ECS 2台;

搭建主从环境

操作系统: Centos 7.6 64位

redis版本:5.0.8

kvrocks版本: 1.1.27

测试工具

redis-benchmark

测试所在机器:从节点

测试结果
  1. 1024个客户端,10 万随机 key 连续 执行10 万次命令

    redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 1024 -r 100000 -n 100000 -q
    

    执行结果:

image-20200828144437387
image-20200828144828926

减少客户端个数 512,10 万随机 key 连续 执行10 万次命令。CPU同样出现占用高的问题

单独测试命令:

[root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -t set,get  -r 100000 -n 1000000 -q
SET: 85222.43 requests per second
GET: 86752.84 requests per second

[root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -t lpush,rpush  -r 100000 -n 1000000 -q
LPUSH: 30162.27 requests per second
RPUSH: 33840.95 requests per second

[root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -t lpop,rpop  -r 100000 -n 1000000 -q
LPOP: 23703.98 requests per second
RPOP: 25206.06 requests per second

执行push、pop等命令CPU都有相应提升,证明:kvrocks在push、pop命令上性能存在问题

image-20200828151709461

  1. kvrocks不同数据大小(bit)下GET、SET响应时间

    [root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -d 128 -t get,set  -r 100000 -n 1000000 -q
    SET: 84040.67 requests per second
    GET: 81973.93 requests per second
    
    [root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -d 512 -t get,set  -r 100000 -n 1000000 -q
    SET: 78179.97 requests per second
    GET: 77845.24 requests per second
    
    [root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 512 -d 1024 -t get,set  -r 100000 -n 1000000 -q
    SET: 58271.66 requests per second
    GET: 76946.75 requests per second
    
    [root@ba-test-kvrocks-02 ~]# redis-benchmark -h 192.168.24.43 -p 6379 -a kvs -c 4096 -d 1024 -t get,set  -r 100000 -n 1000000 -q
    SET: 49490.25 requests per second
    GET: 52391.68 requests per secon
    

image-20200828160003438

# redis
Redis标准化部署
EMR Apache Spark参数调优
  • 文章目录
  • 站点概览
lw‘Blogs

lw‘Blogs

自信人生二百年,会当水击三千里

80 日志
8 分类
40 标签
RSS
Github E-mail
Creative Commons
© 2025 京ICP备2022025426号-1