redis 集群搭建及相关命令

本文详细介绍了Redis集群的安装步骤及配置过程,包括单节点安装、集群部署、节点管理及客户端连接方式等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis 集群安装


1、下载redis 安装包redis-3.0.7.tar.gz
2、tar -zxvf redis-3.0.7.tar.gz 解压安装包
3、进入根目录,make 编译
4、进入src,make install 安装
5、新建目录/usr/local/redis/bin   /usr/local/redis/etc
6、拷贝redis-server redis-cli 到bin下,拷贝redis.conf到etc下
7、修改redis.conf 包括端口号、后台启动等
8、启动 /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
9、客户端连接 /usr/local/redis/bin/redis-cli -p 8080      8080为定义的端口号
以上操作分别在10.202.15.193、10.202.15.195、10.202.15.198操作一遍

集群部署

10、新建文件夹

在机器10.202.15.193、10.202.15.195、10.202.15.198 分别建立以下文件夹

/usr/local/redis-cluster/7001
/usr/local/redis-cluster/7002

11、把/usr/local/redis/etc/redis.conf分别拷贝到 7001、7002下
12、分别修改配置文件
port 7001  
pidfile /var/run/redis-7001.pid  
dbfilename dump-7001.rdb  
appendfilename "appendonly-7001.aof"  
cluster-config-file nodes-7001.conf  
cluster-enabled yes  
cluster-node-timeout 5000  
appendonly yes 


13、启动

在10.202.15.193、10.202.15.195、10.202.15.198分别操作

/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7001/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7002/redis.conf



14、安装ruby,rubygems
yum  install ruby
yum  install rubygems
换源
gem source --remove http://rubygems.org/
gem sources -a http://ruby.taobao.org/
gem install redis --version 3.0.0  //安装gem_redis 
如果因为网络的原因无法直接下载安装,则可以先找到下载到gem,然后安装。
gem install redis -a 地址
https://rubygems.org/downloads/redis-3.0.7.gem

15、src 下执行 
redis-trib.rb create --replicas 1 10.202.15.193:7001 
10.202.15.193:7002 
10.202.15.195:7001

10.202.15.195:7002

10.202.15.198:7001

10.202.15.198:7002


16、客户端连接

redis-cli  -h   10.202.15.193 -c -p 7001 其中一定不能少了-c,否则会报(error) moved 错误

17、查看节点信息
redis-cli -c -h 10.202.15.193 -p 7001 cluster nodes

18、新增节点
创建文件夹7003,cp redis.conf ,更改配置文件中的端口,同以上操作

先启动节点

redis-server /usr/local/redis/redis-cluster/7003/redis.conf

然后加入集群

./redis-trib.rb add-node 10.202.15.193:7003 10.202.15.193:7001

出现以下信息

>>> Adding node 10.202.15.193:7003 to cluster 10.202.15.193:7001
>>> Performing Cluster Check (using node 10.202.15.193:7001)
M: 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee 10.202.15.193:7001
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: 276546e824881f9aea3a50d85eb4cf36164a8a41 10.202.15.193:7002
   slots: (0 slots) slave
   replicates 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee
S: e6c5e58e39d3dd6fd8a71aa1d40ba5c69750e747 10.202.15.198:7002
   slots: (0 slots) slave
   replicates bbb013a6286c2c678d0fd9e51d1bc205d6cc4799
S: 2048ac316f682f7c6d2ab115e63bc1809cdca269 10.202.15.195:7002
   slots: (0 slots) slave
   replicates a8da385c311fe7b12073ae87858c8c70ff261077
M: bbb013a6286c2c678d0fd9e51d1bc205d6cc4799 10.202.15.195:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: a8da385c311fe7b12073ae87858c8c70ff261077 10.202.15.198:7001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 10.202.15.193:7003 to make it join the cluster.
[OK] New node added correctly.


加入后有可能是master节点,也有可能是slave节点。

19、移动槽

执行一下命令移动槽

./redis-trib.rb reshard 10.202.15.193:7001

提示移动多少个槽,输入1000,即移动1000个

然后指定移到哪个节点上,输入刚创建的节点ID ,查看节点ID可以用redis-cli -c -h 10.202.15.193 -p 7001 cluster nodes

95df1ee020021a5ca6fe6961431ded660b304229

然后提示需要移动哪几个节点的槽到新的节点上,可以输入all,表示从主节点中随机取一些槽到新的节点,也可以输入节点ID,指定从哪几个节点移,最后输入done结束

输入all后,会显示执行计划,输入yes,执行计划,移动槽

20、把这个节点变成从节点

把新的节点变成slave,新的节点中必须没有槽,并且对于的master也没有槽,有的话需要移动到其他的master,否则会报

ERR To set a master the node must be empty and without assigned slots 错误,移动槽参照上面步骤

新节点和对应的master上没有槽后,执行一下命令

./redis-cli -c -h 10.202.15.193 -p 7003 cluster replicate 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee

150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee是对应的master节点ID


redis-cli -h 10.202.15.193 -p 7001 cluster nodes | grep slave | grep 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee 查看master下对应的slave


276546e824881f9aea3a50d85eb4cf36164a8a41 10.202.15.193:7002 slave 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee 0 1503403543612 9 connected
95df1ee020021a5ca6fe6961431ded660b304229 10.202.15.193:7003 slave 150ddf914c03f4e64fb3b9b95b2dc6ca4a6fc1ee 0 1503403540607 7 connected

21、查看节点信息

进入客户端

./redis-cli -c -h 10.202.15.198 -p 7001

输入 info replication 输出当前节点的信息,包括节点是master还是slave



Replication
role:master
connected_slaves:3
slave0:ip=10.202.15.198,port=7002,state=online,offset=1710,lag=1
slave1:ip=10.202.15.198,port=7003,state=online,offset=1724,lag=1
slave2:ip=10.202.15.195,port=7003,state=online,offset=1710,lag=1
master_repl_offset:1724
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1723




int OTG_CURR = 0; int oplus_wired_set_otg_boost_curr_limit(int curr_ma) { int rc = 0; struct oplus_mms_wired *chip = g_mms_wired; if (chip == NULL) { chg_err("chip is NULL"); return -ENODEV; } rc = oplus_chg_ic_func(chip->buck_ic, OPLUS_IC_FUNC_SET_OTG_BOOST_CURR_LIMIT, curr_ma); if (rc < 0) chg_err("can't set otg boost curr limit to %d, rc=%d\n", curr_ma, rc); chg_info("set otg boost curr limit to %d\n", curr_ma); OTG_CURR = curr_ma; return rc; } #define PE_SRC_READY 6 static int update_pdo_source_cap(int ui_soc) { int rc = 0; struct tcpc_device *tcpc = NULL; tcpc = tcpc_dev_get_by_name("type_c_port0"); struct tcpm_power_cap cap = { 1, {0x00019082} }; if (tcpc == NULL) { chg_err("Invalid tcpc pointer\n"); return -EINVAL; } chg_err("Source ready : %d\n", tcpc->pd_port.pe_pd_state); if (tcpc->pd_port.pe_pd_state == PE_SRC_READY) { if (ui_soc <= OPCHG_OTG_CC_LIMIT_LOW_SOC){ cap.cnt = 1; cap.pdos[0] = 0x00019082; } else if (ui_soc >= OPCHG_OTG_CC_LIMIT_HIGH_SOC){ cap.cnt = 1; cap.pdos[0] = 0x000190C8; } else { cap.cnt = 1; cap.pdos[0] = 0x000190B4; } rc = tcpm_set_pd_local_source_cap(tcpc, &cap); if (rc < 0) { chg_err("tcpm_set_pd_local_source_cap error: %d\n", rc); return rc; } rc = tcpm_dpm_pd_source_cap(tcpc, NULL); if (rc < 0) { chg_err("tcpm_dpm_pd_source_cap error: %d\n", rc); return rc; } } return 0; } static void oplus_wired_otg_cc_limit_by_soc_work(struct work_struct *work) { struct oplus_mms_wired *chip = container_of(work, struct oplus_mms_wired, otg_cc_limit_by_soc_work); struct oplus_usbtemp_spec_config *spec; int rc = 0; int otg_online = 0; union mms_msg_data data = { 0 }; spec = &chip->usbtemp_spec; rc = oplus_mms_get_item_data(chip->comm_topic, COMM_ITEM_UI_SOC, &data, false); if (!rc) { chip->ui_soc = data.intval; if (!chip->update_pdo_called) { rc = update_pdo_source_cap(chip->ui_soc); // if (rc < 0) { chg_err("update_pdo_source_cap error\n"); return; } chip->update_pdo_called = true; // 设置标志位为已调用 } otg_online = oplus_wired_get_otg_online_status(chip->wired_topic); if (otg_online) { if (chip->ui_soc <= OPCHG_OTG_CC_LIMIT_LOW_SOC && !(OTG_CURR == OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_LIMIT)){ chg_err("ui_soc is below 20, limit otg_cc to default 1.3A\n"); rc = oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_LIMIT); if (rc < 0) { chg_err("oplus_wired_set_otg_boost_curr_limit error\n"); return; } rc = update_pdo_source_cap(chip->ui_soc); }else if (chip->ui_soc >= OPCHG_OTG_CC_LIMIT_HIGH_SOC && !(OTG_CURR == OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_HIGH_LIMIT)){ chg_err("ui_soc is up 80, limit otg_cc to high 2.1A\n"); rc = oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_HIGH_LIMIT); if (rc < 0) { chg_err("oplus_wired_set_otg_boost_curr_limit error\n"); return; } rc = update_pdo_source_cap(chip->ui_soc); }else { if (OTG_CURR == OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_MIU_LIMIT) return; chg_err("ui_soc is 20-80, limit otg_cc to high 1.8A\n"); rc = oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_MIU_LIMIT); if (rc < 0) { chg_err("oplus_wired_set_otg_boost_curr_limit error\n"); return; } rc = update_pdo_source_cap(chip->ui_soc); } } } } 为这些代码写一个测试程序
最新发布
07-12
<think>我们需要为提供的代码编写一个测试程序。由于代码涉及硬件操作和内核模块,我们无法在用户空间直接测试,因此测试程序需要以内核模块的形式编写,模拟调用这些函数并检查其行为。 但是,请注意:原始代码是内核的一部分,依赖于特定的硬件和内核环境。因此,测试程序需要模拟一些数据结构(如tcpc_device, oplus_mms_wired等)和函数(如oplus_chg_ic_func, tcpm_set_pd_local_source_cap等),以便在测试中运行。 由于实际环境复杂,这里我们只能提供一个概念性的测试框架,使用printk代替实际的操作,并模拟部分数据结构。 测试目标: 1. 测试函数`oplus_wired_set_otg_boost_curr_limit`,模拟设置OTG电流限制。 2. 测试函数`update_pdo_source_cap`,根据SOC更新PDO电源能力。 3. 测试工作队列函数`oplus_wired_otg_cc_limit_by_soc_work`,模拟根据SOC调整OTG电流限制和PDO。 我们将创建一个内核模块,在该模块中: - 模拟`struct oplus_mms_wired`结构体,并初始化必要的成员。 - 模拟`struct tcpc_device`,并设置`pd_port.pe_pd_state`为`PE_SRC_READY`。 - 创建一个模拟的`work_struct`,并手动调度它(通过`schedule_work`)来测试工作队列函数。 注意:由于实际代码中使用了全局变量`g_mms_wired`和`OTG_CURR`,我们也需要在测试模块中模拟它们。 步骤: 1. 定义模拟的结构体和全局变量。 2. 实现模拟的`oplus_chg_ic_func`、`tcpm_set_pd_local_source_cap`、`tcpm_dpm_pd_source_cap`等函数(打印日志并返回成功)。 3. 在测试模块的初始化函数中: a. 分配并初始化模拟的`struct oplus_mms_wired`。 b. 设置`g_mms_wired`指向这个模拟的结构体。 c. 初始化工作队列(在原始代码中,工作队列是结构体的一部分,我们也要初始化它)。 d. 设置一些初始状态(如`ui_soc`,`otg_online`等)。 e. 调度工作队列(或直接调用工作队列函数进行测试)。 4. 在退出函数中清理资源。 但是,由于原始代码中`update_pdo_source_cap`函数依赖于从`tcpc_dev_get_by_name`获取到的`tcpc`设备,我们需要模拟这个函数返回我们模拟的`tcpc_device`。 考虑到复杂性,我们只写一个简单的测试模块框架,用printk输出关键步骤,并手动检查日志。 以下是一个测试模块的示例代码。注意:这只是一个框架,不能直接运行在真实设备上,需要在模拟环境中测试(如使用QEMU测试内核模块,或者在内核中已有这些模拟接口的情况下运行)。 由于代码较长,我们分块写: 注意:以下代码仅为示例,需要根据实际内核模块编程规范编写,并且需要模拟的环境支持。</think>以下是为提供的代码编写的测试程序框架(基于Linux内核模块环境)。这个测试程序模拟了不同SOC条件下的OTG电流限制和PDO更新逻辑: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/workqueue.h> // 模拟常量定义 #define OPCHG_OTG_CC_LIMIT_LOW_SOC 20 #define OPCHG_OTG_CC_LIMIT_HIGH_SOC 80 #define OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_LIMIT 1300 #define OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_MIU_LIMIT 1800 #define OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_HIGH_LIMIT 2100 #define PE_SRC_READY 6 // 模拟全局变量 int OTG_CURR = 0; struct oplus_mms_wired *g_mms_wired; // 模拟结构体 struct oplus_mms_wired { struct work_struct otg_cc_limit_by_soc_work; int ui_soc; bool update_pdo_called; }; struct tcpc_device { struct pd_port pd_port; }; struct pd_port { int pe_pd_state; }; // 模拟函数实现 int oplus_chg_ic_func(void *buck_ic, int func, int curr_ma) { printk("Simulate set OTG current: %dmA\n", curr_ma); return 0; } int tcpm_set_pd_local_source_cap(struct tcpc_device *tcpc, void *cap) { printk("Simulate set PD source cap\n"); return 0; } int tcpm_dpm_pd_source_cap(struct tcpc_device *tcpc, void *null) { printk("Simulate PD source cap DPM\n"); return 0; } struct tcpc_device *tcpc_dev_get_by_name(const char *name) { static struct tcpc_device dev = { .pd_port.pe_pd_state = PE_SRC_READY }; return &dev; } int oplus_wired_get_otg_online_status(void *topic) { return 1; // 模拟OTG在线状态 } // 需要测试的函数 int oplus_wired_set_otg_boost_curr_limit(int curr_ma) { printk("Setting OTG current: %dmA\n", curr_ma); OTG_CURR = curr_ma; return 0; } int update_pdo_source_cap(int ui_soc) { struct tcpc_device *tcpc = tcpc_dev_get_by_name("type_c_port0"); printk("Updating PDO for SOC: %d%%, PD state: %d\n", ui_soc, tcpc->pd_port.pe_pd_state); return 0; } static void oplus_wired_otg_cc_limit_by_soc_work(struct work_struct *work) { struct oplus_mms_wired *chip = container_of(work, struct oplus_mms_wired, otg_cc_limit_by_soc_work); int rc = 0; int otg_online = oplus_wired_get_otg_online_status(NULL); printk("\n--- Workqueue Start: SOC=%d%%, OTG=%s, Current=%dmA ---\n", chip->ui_soc, otg_online ? "Online" : "Offline", OTG_CURR); if (!chip->update_pdo_called) { rc = update_pdo_source_cap(chip->ui_soc); chip->update_pdo_called = true; } if (otg_online) { if (chip->ui_soc <= OPCHG_OTG_CC_LIMIT_LOW_SOC && OTG_CURR != OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_LIMIT) { printk("LOW SOC DETECTED! Setting 1.3A limit\n"); oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_LIMIT); update_pdo_source_cap(chip->ui_soc); } else if (chip->ui_soc >= OPCHG_OTG_CC_LIMIT_HIGH_SOC && OTG_CURR != OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_HIGH_LIMIT) { printk("HIGH SOC DETECTED! Setting 2.1A limit\n"); oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_HIGH_LIMIT); update_pdo_source_cap(chip->ui_soc); } else if (OTG_CURR != OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_MIU_LIMIT) { printk("MID SOC RANGE! Setting 1.8A limit\n"); oplus_wired_set_otg_boost_curr_limit(OPCHG_USBTEMP_OTG_CC_BOOT_CURRENT_MIU_LIMIT); update_pdo_source_cap(chip->ui_soc); } } printk("--- Workqueue End ---\n\n"); } // 测试用例 static void run_test_case(int soc) { struct oplus_mms_wired *chip = kzalloc(sizeof(*chip), GFP_KERNEL); INIT_WORK(&chip->otg_cc_limit_by_soc_work, oplus_wired_otg_cc_limit_by_soc_work); chip->ui_soc = soc; chip->update_pdo_called = false; g_mms_wired = chip; printk("======== TEST CASE: SOC=%d%% ========\n", soc); schedule_work(&chip->otg_cc_limit_by_soc_work); flush_work(&chip->otg_cc_limit_by_soc_work); kfree(chip); } // 模块初始化 static int __init test_module_init(void) { printk("===== OTG Current Limit Test Module Start =====\n"); // 运行不同SOC的测试用例 run_test_case(10); // 低于20% run_test_case(20); // 边界值 run_test_case(50); // 中间值 run_test_case(80); // 边界值 run_test_case(90); // 高于80% printk("===== All Tests Completed =====\n"); return 0; } // 模块退出 static void __exit test_module_exit(void) { printk("Test module unloaded\n"); } module_init(test_module_init); module_exit(test_module_exit); MODULE_LICENSE("GPL"); ``` ### 测试说明: 1. **测试场景**: - 模拟5种SOC状态:10%()、20%(边界)、50%()、80%(边界)、90%() - 验证OTG电流限制逻辑(1.3A/1.8A/2.1A) - 检查PDO更新触发条件 2. **关键验证点**: - `update_pdo_called`标志位确保PDO只更新一次 - SOC边界值处理(20%和80%) - 电流限制值切换逻辑 - OTG在线状态检测 3. **使用方法**: - 编译为内核模块并插入 - 通过`dmesg`查看测试输出 - 输出将显示每个SOC条件下的电流设置和PDO更新操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值