[关闭]
@guodong 2020-11-06T13:04:05.000000Z 字数 10651 阅读 907

Redis 5.0.7集群的搭建及使用

Redis



【redis集群搭建】

下载redis的tar包,解压并且编译

  1. #下载
  2. cd /opt/ && wget http://download.redis.io/releases/redis-5.0.7.tar.gz
  3. #解压
  4. tar xzf redis-5.0.7.tar.gz
  5. #进入
  6. cd redis-5.0.7
  7. #编译
  8. make

单机部署

1.修改redis的配置文件,为搭建集群做准备

  1. #创建集群所需的配置文件组
  2. cd /opt/redis-5.0.7 && mkdir 7000 7001 7002 7003 7004 7005
  3. #复制配置文件到各个文件目录下,并分别修改每个配置文件的参数
  4. for i in 7000 7001 7002 7003 7004 7005;
  5. do cp redis.conf $i;
  6. sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;
  7. sed -i "s|6379|$i|g" $i/redis.conf ;
  8. sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;
  9. sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;
  10. sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;
  11. sed -i "s|bind 127.0.0.1|bind 192.168.1.109|g" $i/redis.conf ;
  12. done
  13. #启动各个节点
  14. for i in 7000 7001 7002 7003 7004 7005; do /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/$i/redis.conf; done

2.创建一个redis集群

  1. /opt/redis-5.0.7/src/redis-cli --cluster create 192.168.1.109:7000 192.168.1.109:7001 192.168.1.109:7002 192.168.1.109:7003 192.168.1.109:7004 192.168.1.109:7005 --cluster-replicas 1

3.查看集群配置

  1. /opt/redis-5.0.7/src/redis-cli --cluster check 192.168.1.109:7000

4.连接节点

  1. /opt/redis-5.0.7/src/redis-cli -c -h 192.168.1.109 -p 7000

多机部署

1.修改redis的配置文件,为搭建集群做准备

  1. # 机器1
  2. #创建集群所需的配置文件组
  3. cd /opt/redis-5.0.7 && mkdir 7000 7001 7002
  4. #复制配置文件到各个文件目录下,并分别修改每个配置文件的参数
  5. for i in 7000 7001 7002;
  6. do cp redis.conf $i;
  7. sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;
  8. sed -i "s|6379|$i|g" $i/redis.conf ;
  9. sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;
  10. sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;
  11. sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;
  12. sed -i "s|bind 127.0.0.1|bind 192.168.1.109|g" $i/redis.conf ;
  13. done
  14. #启动各个节点
  15. for i in 7000 7001 7002;
  16. do /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/$i/redis.conf;
  17. done
  18. # 机器2
  19. #创建集群所需的配置文件组
  20. cd /opt/redis-5.0.7 && mkdir 7003 7004 7005
  21. #复制配置文件到各个文件目录下,并分别修改每个配置文件的参数
  22. for i in 7003 7004 7005;
  23. do cp redis.conf $i;
  24. sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;
  25. sed -i "s|6379|$i|g" $i/redis.conf ;
  26. sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;
  27. sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;
  28. sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;
  29. sed -i "s|bind 127.0.0.1|bind 192.168.1.108|g" $i/redis.conf ;
  30. done
  31. #启动各个节点
  32. for i in 7003 7004 7005;
  33. do /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/$i/redis.conf;
  34. done

2.创建一个redis集群

  1. /opt/redis-5.0.7/src/redis-cli --cluster create 192.168.1.109:7000 192.168.1.109:7001 192.168.1.109:7002 192.168.1.108:7003 192.168.1.108:7004 192.168.1.108:7005 --cluster-replicas 1

3.查看集群配置

  1. /opt/redis-5.0.7/src/redis-cli --cluster check 192.168.1.108:7005

4.连接节点

  1. /opt/redis-5.0.7/src/redis-cli -c -h 192.168.1.108 -p 7005

【redis 5.0的改进】

1.新的Stream数据类型。
2.新的Redis模块API:Timers and Cluster API。
3.RDB 现在可存储 LFU 和 LRU 信息
4.集群管理器从Ruby(redis-trib.rb)迁移到C。redis-cli —cluster help了解更多。
5.新sorted set命令:ZPOPMIN / MAX 和 (blocking variants)
6.升级 Active defragmentation V2。
7.增强HyperLogLog实现。
8.更好的内存统计报告。
9.许多带有子命令的命令现在都有一个HELP子命令。
10.改进客户端经常连接断开时的性能
11.错误修复和改进。
12. 升级Jemalloc到5.1版
13. 引入 CLIENT UNBLOCK 和 CLIENT ID
14. 新增 LOLWUT 命令 http://antirez.com/news/123
15. 在不存在需要保持向后兼容性的地方,弃用 "slave" 术语
16. 网络层优化
17. Lua 相关的改进
18. 引入 Dynamic HZ 平衡CPU空闲时的使用率和响应性
19. 重构了Redis 核心代码,并进行多方面改进

关于redis的key
1.key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且会降低查找的效率;
2.key也不要太短,太短的话,key的可读性会降低;
3.在一个项目中,key最好使用统一的命名模式,例如user:10000:passwd。

【redis数据结构 – LIST(底层实现为链表)】

1新建一个列表名为mylist,并在其头部(左侧)插入一个元素

  1. lpush mylist "1"

2 在其尾部(右侧)插入一个元素

  1. rpush mylist "1"

3 查询元素

  1. #查询从0开始到下标为1的元素
  2. lrange mylist 0 1
  3. #列出mylist中从编号0到倒数第一个元素
  4. lrange mylist 0 -1

4 lists的应用相当广泛:

1.可以利用lists来实现一个消息队列,而且可以确保先后顺序
2.利用LRANGE还可以很方便的实现分页的功能。
3.在博客系统中,每片博文的评论也可以存入一个单独的list中。

【redis数据结构 – 集合】

redis的集合,是一种无序的集合,集合中的元素没有先后顺序。
1 在set中添加一个元素

  1. #向集合myset中加入一个新元素"one"
  2. sadd myset "one"

2 遍历set中的所有元素

  1. #列出集合myset中的所有元素
  2. smembers myset

3 判断myset中是否包含该元素

  1. #判断元素1是否在集合myset中,返回1表示存在
  2. sismember myset "one"

4 两个集合求并集

  1. #myset为集合1,yourset为集合2
  2. sunion myset yourset

【redis数据结构 – 有序集合】

zset(有序集合)中的每个元素都关联一个序号(score),这便是排序的依据。
1 在myzset中添加一个元素baidu.com 编号为1

  1. zadd myzset 1 baidu.com

2 列出myzset的所有元素,同时列出其序号(有序)。

  1. zrange myzset 0 -1 with scores

3 只列出myzset的元素

  1. zrange myzset 0 -1

【redis数据结构 – 哈希】

1 在hashtable中,添加一个元素

  1. HMSET user:001 username antirez password P1pp0 age 34

2 列出hash中的内容

  1. HGETALL user:001

3 更改hash中的值(将密码修改为12345)

  1. HSET user:001 password 12345

【redis持久化 – RDB】

RDB,是快照式的持久化方法。
通过配置文件中配置 save ,每seconds的时间如果有changes的key发生改变,就触发持久化。
优势:单独创建一个子进程进行持久化,确保性能好。如果需要进行大规模数据的恢复,非常高效。
缺点:对数据的完整性不够敏感,当redis故障时,仍然会有近5分钟的数据丢失。

【redis持久化 – AOF】

只允许追加不允许改写的文件。
通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。
默认的AOF持久化策略是每秒钟fsync一次。如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复。

【redis客户端 – jedis和redission的对比】

jedis集群模式下
优点:支持全部官方API
缺点:没有高层封装,不支持读写分离,不支持pipeline操作,不支持scan操作

redission集群模式下
优点:高层封装调用,对用户屏蔽了底层实现,实现了读写分离,pipeline,支持scan操作,每个操作都有同步和异步两种实现方式。redissionPro提供了编排集群和移动槽的功能

【redis客户端 – jedis】

pom依赖

  1. <!--redis客户端依赖-->
  2. <dependency>
  3. <groupId>redis.clients</groupId>
  4. <artifactId>jedis</artifactId>
  5. <version>2.9.0</version>
  6. </dependency>

获取当前redis集群的状况列表(可用于自行修改客户端配置)

  1. private static String getRedisStructure() {
  2. final Map<String, JedisPool> clusterNodes = jedis.getClusterNodes();
  3. Set<Map.Entry<String, JedisPool>> entries = clusterNodes.entrySet();
  4. JedisPool jedisPool = null;
  5. String jedisStructure = null;
  6. for (Map.Entry<String, JedisPool> entry : entries) {
  7. String key = entry.getKey();
  8. if (entry.getValue() != null && entry.getKey() != null) {
  9. jedisPool = entry.getValue();
  10. break;
  11. }else {
  12. }
  13. }
  14. Jedis resource = jedisPool.getResource();
  15. //jedis集群结构
  16. jedisStructure = resource.clusterNodes();
  17. System.out.println("jedis集群主备情况: "+jedisStructure);
  18. return jedisStructure;
  19. }

Jedis-cluster模式配置Demo

  1. package RedisUtils;
  2. import org.apache.logging.log4j.LogManager;
  3. import org.apache.logging.log4j.Logger;
  4. import org.junit.Test;
  5. import redis.clients.jedis.HostAndPort;
  6. import redis.clients.jedis.JedisCluster;
  7. import redis.clients.jedis.JedisPoolConfig;
  8. import redis.clients.jedis.SortingParams;
  9. import java.util.HashMap;
  10. import java.util.HashSet;
  11. import java.util.Map;
  12. import java.util.Set;
  13. import java.util.concurrent.TimeUnit;
  14. /**
  15. * 集群环境下Jedis操作
  16. */
  17. public class Cluster {
  18. private static JedisCluster jedis;
  19. private static final Logger logger = LogManager.getLogger(Cluster.class);
  20. static {
  21. // 添加集群的服务节点Set集合
  22. Set<HostAndPort> hostAndPortsSet = new HashSet<HostAndPort>();
  23. // 添加节点
  24. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7000));
  25. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7001));
  26. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7002));
  27. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7003));
  28. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7004));
  29. hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7005));
  30. logger.info("添加节点完成");
  31. System.out.println("添加节点完成");
  32. // Jedis连接池配置
  33. JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
  34. // 最大空闲连接数, 默认8个
  35. jedisPoolConfig.setMaxIdle(100);
  36. // 最大连接数, 默认8个
  37. jedisPoolConfig.setMaxTotal(500);
  38. //最小空闲连接数, 默认0
  39. jedisPoolConfig.setMinIdle(0);
  40. // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
  41. jedisPoolConfig.setMaxWaitMillis(2000); // 设置2秒
  42. //对拿到的connection进行validateObject校验
  43. jedisPoolConfig.setTestOnBorrow(true);
  44. jedis = new JedisCluster(hostAndPortsSet, jedisPoolConfig);
  45. logger.info("初始化完成");
  46. System.out.println("初始化完成");
  47. }
  48. public static void main(String[] args) {
  49. Long mylist = jedis.lpush("mylist", "1");
  50. System.out.println(mylist);
  51. }

【redis客户端 – jedission】

pom

  1. <dependency>
  2. <groupId>org.redisson</groupId>
  3. <artifactId>redisson</artifactId>
  4. <version>3.10.7</version>
  5. </dependency>

redission通过配置实现读写分离

  1. clusterConfig.setReadMode(ReadMode.SLAVE);
  2. //(默认)SLAVE只在从服务节点里读取;MASTER只在主服务节点里读取;MASTER_SLAVE在主从服务节点里都可以读取。

redission返回的每个对象都提供了同步和异步执行两种方法:

  1. RAtomicLong longObject = redisson.getAtomicLong("myLong");
  2. // 同步执行方式
  3. longObject.compareAndSet(3, 401);
  4. // 异步执行方式
  5. RFuture<Boolean> result = longObject.compareAndSetAsync(3, 401);

redission实现的scan方法,返回一个Stream,支持匹配规则

  1. //redisson.getKeys().getKeysStreamByPattern("key*")传入匹配规则,得到key的stream
  2. Stream<String> keysStreamByPattern = redisson.getKeys().getKeysStreamByPattern("key*");
  3. //redisson.getKeys().getKeysStream()扫描 以Stream的形式返回全部的key
  4. Stream<String> keysStream = redisson.getKeys().getKeysStream();
  5. AtomicReference<Integer> a= new AtomicReference<>(1);
  6. keysStream.forEach(i -> {
  7. a.updateAndGet(v -> v + 1);
  8. System.out.println(i+":"+ a);}
  9. );

完整Demo

  1. package com.bitnei.main.Redission;
  2. import org.redisson.Redisson;
  3. import org.redisson.api.*;
  4. import org.redisson.config.ClusterServersConfig;
  5. import org.redisson.config.Config;
  6. import org.redisson.config.ReadMode;
  7. import org.redisson.config.SubscriptionMode;
  8. import reactor.core.publisher.Mono;
  9. public class RedissionApi {
  10. public static void main(String[] args) {
  11. /************************************************程序化配置集群*****************************************************/
  12. //创建配置
  13. Config config = new Config();
  14. //指定编码,默认编码为org.redisson.codec.JsonJacksonCodec
  15. //之前使用的spring-data-redis,用的客户端jedis,编码为org.springframework.data.redis.serializer.StringRedisSerializer
  16. //改用redisson后为了之间数据能兼容,这里修改编码为org.redisson.client.codec.StringCodec
  17. config.setCodec(new org.redisson.client.codec.StringCodec());
  18. //指定使用集群部署方式,集群模式的使用方法
  19. ClusterServersConfig clusterConfig = config.useClusterServers();
  20. //添加节点
  21. clusterConfig
  22. //集群状态扫描间隔时间,单位是毫秒,默认1000
  23. .setScanInterval(2000)
  24. //cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用)
  25. .addNodeAddress("redis://127.0.0.1:6379" )
  26. .addNodeAddress("redis://127.0.0.1:6380")
  27. .addNodeAddress("redis://127.0.0.1:6381")
  28. .addNodeAddress("redis://127.0.0.1:6382")
  29. .addNodeAddress("redis://127.0.0.1:6383")
  30. .addNodeAddress("redis://127.0.0.1:6384");
  31. /**********************************************集群模式参数配置*****************************************************/
  32. //读取操作的负载均衡
  33. clusterConfig.setReadMode(ReadMode.SLAVE);//(默认)SLAVE只在从服务节点里读取;MASTER只在主服务节点里读取;MASTER_SLAVE在主从服务节点里都可以读取。
  34. //订阅操作的负载均衡
  35. clusterConfig.setSubscriptionMode(SubscriptionMode.SLAVE);//(默认)SLAVE只在从服务节点里订阅;MASTER 只在master节点;MASTER_SLAVE 在主从服务节点里都可以订阅
  36. //config.setPassword("password")//设置密码
  37. clusterConfig.setMasterConnectionPoolSize(500);//设置对于master节点的连接池中连接数最大为500
  38. clusterConfig.setSlaveConnectionPoolSize(500);//设置对于slave节点的连接池中连接数最大为500
  39. clusterConfig.setIdleConnectionTimeout(10000);//如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
  40. clusterConfig.setConnectTimeout(30000);//同任何节点建立连接时的等待超时。时间单位是毫秒。
  41. clusterConfig.setTimeout(3000);//等待节点回复命令的时间。该时间从命令发送成功时开始计时。
  42. clusterConfig.setRetryAttempts(3);//设置失败重试次数,默认为3
  43. clusterConfig.setPingTimeout(30000);
  44. clusterConfig.setReconnectionTimeout(3000);//当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。
  45. RedissonClient redisson = Redisson.create(config); //RedissonClien本身是线程安全的,建客户端(发现创建RedissonClient非常耗时)
  46. /***********************************************Redisson提供的所有对象都包含了同步和异步执行方式*************************************************/
  47. RAtomicLong longObject = redisson.getAtomicLong("myLong");
  48. longObject.compareAndSet(3, 401);// 同步执行方式
  49. RFuture<Boolean> result = longObject.compareAndSetAsync(3, 401);// 异步执行方式
  50. //首先获取redis中的key-value对象,key不存在没关系
  51. RBucket<String> keyObject = redisson.getBucket("key");
  52. //如果key存在,就设置key的值为新值value
  53. //如果key不存在,就设置key的值为value
  54. keyObject.set("value");
  55. //最后关闭RedissonClient
  56. redisson.shutdown();
  57. }
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注