@guodong
2020-11-06T05:04:05.000000Z
字数 10651
阅读 1067
Redis
下载redis的tar包,解压并且编译
#下载cd /opt/ && wget http://download.redis.io/releases/redis-5.0.7.tar.gz#解压tar xzf redis-5.0.7.tar.gz#进入cd redis-5.0.7#编译make
1.修改redis的配置文件,为搭建集群做准备
#创建集群所需的配置文件组cd /opt/redis-5.0.7 && mkdir 7000 7001 7002 7003 7004 7005#复制配置文件到各个文件目录下,并分别修改每个配置文件的参数for i in 7000 7001 7002 7003 7004 7005;do cp redis.conf $i;sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;sed -i "s|6379|$i|g" $i/redis.conf ;sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;sed -i "s|bind 127.0.0.1|bind 192.168.1.109|g" $i/redis.conf ;done#启动各个节点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集群
/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.查看集群配置
/opt/redis-5.0.7/src/redis-cli --cluster check 192.168.1.109:7000
4.连接节点
/opt/redis-5.0.7/src/redis-cli -c -h 192.168.1.109 -p 7000
1.修改redis的配置文件,为搭建集群做准备
# 机器1#创建集群所需的配置文件组cd /opt/redis-5.0.7 && mkdir 7000 7001 7002#复制配置文件到各个文件目录下,并分别修改每个配置文件的参数for i in 7000 7001 7002;do cp redis.conf $i;sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;sed -i "s|6379|$i|g" $i/redis.conf ;sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;sed -i "s|bind 127.0.0.1|bind 192.168.1.109|g" $i/redis.conf ;done#启动各个节点for i in 7000 7001 7002;do /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/$i/redis.conf;done# 机器2#创建集群所需的配置文件组cd /opt/redis-5.0.7 && mkdir 7003 7004 7005#复制配置文件到各个文件目录下,并分别修改每个配置文件的参数for i in 7003 7004 7005;do cp redis.conf $i;sed -i "s|# cluster-enabled yes|cluster-enabled yes|g" $i/redis.conf ;sed -i "s|6379|$i|g" $i/redis.conf ;sed -i "s|daemonize no|daemonize yes|g" $i/redis.conf ;sed -i "s|appendonly no|appendonly yes|g" $i/redis.conf ;sed -i "s|dir ./|dir ./$i|g" $i/redis.conf ;sed -i "s|bind 127.0.0.1|bind 192.168.1.108|g" $i/redis.conf ;done#启动各个节点for i in 7003 7004 7005;do /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/$i/redis.conf;done
2.创建一个redis集群
/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.查看集群配置
/opt/redis-5.0.7/src/redis-cli --cluster check 192.168.1.108:7005
4.连接节点
/opt/redis-5.0.7/src/redis-cli -c -h 192.168.1.108 -p 7005
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。
1新建一个列表名为mylist,并在其头部(左侧)插入一个元素
lpush mylist "1"
2 在其尾部(右侧)插入一个元素
rpush mylist "1"
3 查询元素
#查询从0开始到下标为1的元素lrange mylist 0 1#列出mylist中从编号0到倒数第一个元素lrange mylist 0 -1
4 lists的应用相当广泛:
1.可以利用lists来实现一个消息队列,而且可以确保先后顺序
2.利用LRANGE还可以很方便的实现分页的功能。
3.在博客系统中,每片博文的评论也可以存入一个单独的list中。
redis的集合,是一种无序的集合,集合中的元素没有先后顺序。
1 在set中添加一个元素
#向集合myset中加入一个新元素"one"sadd myset "one"
2 遍历set中的所有元素
#列出集合myset中的所有元素smembers myset
3 判断myset中是否包含该元素
#判断元素1是否在集合myset中,返回1表示存在sismember myset "one"
4 两个集合求并集
#myset为集合1,yourset为集合2sunion myset yourset
zset(有序集合)中的每个元素都关联一个序号(score),这便是排序的依据。
1 在myzset中添加一个元素baidu.com 编号为1
zadd myzset 1 baidu.com
2 列出myzset的所有元素,同时列出其序号(有序)。
zrange myzset 0 -1 with scores
3 只列出myzset的元素
zrange myzset 0 -1
1 在hashtable中,添加一个元素
HMSET user:001 username antirez password P1pp0 age 34
2 列出hash中的内容
HGETALL user:001
3 更改hash中的值(将密码修改为12345)
HSET user:001 password 12345
RDB,是快照式的持久化方法。
通过配置文件中配置 save ,每seconds的时间如果有changes的key发生改变,就触发持久化。
优势:单独创建一个子进程进行持久化,确保性能好。如果需要进行大规模数据的恢复,非常高效。
缺点:对数据的完整性不够敏感,当redis故障时,仍然会有近5分钟的数据丢失。
只允许追加不允许改写的文件。
通过配置redis.conf中的appendonly yes就可以打开AOF功能。如果有写操作(如SET等),redis就会被追加到AOF文件的末尾。
默认的AOF持久化策略是每秒钟fsync一次。如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复。
jedis集群模式下
优点:支持全部官方API
缺点:没有高层封装,不支持读写分离,不支持pipeline操作,不支持scan操作
redission集群模式下
优点:高层封装调用,对用户屏蔽了底层实现,实现了读写分离,pipeline,支持scan操作,每个操作都有同步和异步两种实现方式。redissionPro提供了编排集群和移动槽的功能
pom依赖
<!--redis客户端依赖--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency>
获取当前redis集群的状况列表(可用于自行修改客户端配置)
private static String getRedisStructure() {final Map<String, JedisPool> clusterNodes = jedis.getClusterNodes();Set<Map.Entry<String, JedisPool>> entries = clusterNodes.entrySet();JedisPool jedisPool = null;String jedisStructure = null;for (Map.Entry<String, JedisPool> entry : entries) {String key = entry.getKey();if (entry.getValue() != null && entry.getKey() != null) {jedisPool = entry.getValue();break;}else {}}Jedis resource = jedisPool.getResource();//jedis集群结构jedisStructure = resource.clusterNodes();System.out.println("jedis集群主备情况: "+jedisStructure);return jedisStructure;}
Jedis-cluster模式配置Demo
package RedisUtils;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.junit.Test;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.SortingParams;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;/*** 集群环境下Jedis操作*/public class Cluster {private static JedisCluster jedis;private static final Logger logger = LogManager.getLogger(Cluster.class);static {// 添加集群的服务节点Set集合Set<HostAndPort> hostAndPortsSet = new HashSet<HostAndPort>();// 添加节点hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7000));hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7001));hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7002));hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7003));hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7004));hostAndPortsSet.add(new HostAndPort("192.168.1.109", 7005));logger.info("添加节点完成");System.out.println("添加节点完成");// Jedis连接池配置JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 最大空闲连接数, 默认8个jedisPoolConfig.setMaxIdle(100);// 最大连接数, 默认8个jedisPoolConfig.setMaxTotal(500);//最小空闲连接数, 默认0jedisPoolConfig.setMinIdle(0);// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1jedisPoolConfig.setMaxWaitMillis(2000); // 设置2秒//对拿到的connection进行validateObject校验jedisPoolConfig.setTestOnBorrow(true);jedis = new JedisCluster(hostAndPortsSet, jedisPoolConfig);logger.info("初始化完成");System.out.println("初始化完成");}public static void main(String[] args) {Long mylist = jedis.lpush("mylist", "1");System.out.println(mylist);}
pom
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.10.7</version></dependency>
redission通过配置实现读写分离
clusterConfig.setReadMode(ReadMode.SLAVE);//(默认)SLAVE只在从服务节点里读取;MASTER只在主服务节点里读取;MASTER_SLAVE在主从服务节点里都可以读取。
redission返回的每个对象都提供了同步和异步执行两种方法:
RAtomicLong longObject = redisson.getAtomicLong("myLong");// 同步执行方式longObject.compareAndSet(3, 401);// 异步执行方式RFuture<Boolean> result = longObject.compareAndSetAsync(3, 401);
redission实现的scan方法,返回一个Stream,支持匹配规则
//redisson.getKeys().getKeysStreamByPattern("key*")传入匹配规则,得到key的streamStream<String> keysStreamByPattern = redisson.getKeys().getKeysStreamByPattern("key*");//redisson.getKeys().getKeysStream()扫描 以Stream的形式返回全部的keyStream<String> keysStream = redisson.getKeys().getKeysStream();AtomicReference<Integer> a= new AtomicReference<>(1);keysStream.forEach(i -> {a.updateAndGet(v -> v + 1);System.out.println(i+":"+ a);});
完整Demo
package com.bitnei.main.Redission;import org.redisson.Redisson;import org.redisson.api.*;import org.redisson.config.ClusterServersConfig;import org.redisson.config.Config;import org.redisson.config.ReadMode;import org.redisson.config.SubscriptionMode;import reactor.core.publisher.Mono;public class RedissionApi {public static void main(String[] args) {/************************************************程序化配置集群*****************************************************///创建配置Config config = new Config();//指定编码,默认编码为org.redisson.codec.JsonJacksonCodec//之前使用的spring-data-redis,用的客户端jedis,编码为org.springframework.data.redis.serializer.StringRedisSerializer//改用redisson后为了之间数据能兼容,这里修改编码为org.redisson.client.codec.StringCodecconfig.setCodec(new org.redisson.client.codec.StringCodec());//指定使用集群部署方式,集群模式的使用方法ClusterServersConfig clusterConfig = config.useClusterServers();//添加节点clusterConfig//集群状态扫描间隔时间,单位是毫秒,默认1000.setScanInterval(2000)//cluster方式至少6个节点(3主3从,3主做sharding,3从用来保证主宕机后可以高可用).addNodeAddress("redis://127.0.0.1:6379" ).addNodeAddress("redis://127.0.0.1:6380").addNodeAddress("redis://127.0.0.1:6381").addNodeAddress("redis://127.0.0.1:6382").addNodeAddress("redis://127.0.0.1:6383").addNodeAddress("redis://127.0.0.1:6384");/**********************************************集群模式参数配置*****************************************************///读取操作的负载均衡clusterConfig.setReadMode(ReadMode.SLAVE);//(默认)SLAVE只在从服务节点里读取;MASTER只在主服务节点里读取;MASTER_SLAVE在主从服务节点里都可以读取。//订阅操作的负载均衡clusterConfig.setSubscriptionMode(SubscriptionMode.SLAVE);//(默认)SLAVE只在从服务节点里订阅;MASTER 只在master节点;MASTER_SLAVE 在主从服务节点里都可以订阅//config.setPassword("password")//设置密码clusterConfig.setMasterConnectionPoolSize(500);//设置对于master节点的连接池中连接数最大为500clusterConfig.setSlaveConnectionPoolSize(500);//设置对于slave节点的连接池中连接数最大为500clusterConfig.setIdleConnectionTimeout(10000);//如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。clusterConfig.setConnectTimeout(30000);//同任何节点建立连接时的等待超时。时间单位是毫秒。clusterConfig.setTimeout(3000);//等待节点回复命令的时间。该时间从命令发送成功时开始计时。clusterConfig.setRetryAttempts(3);//设置失败重试次数,默认为3clusterConfig.setPingTimeout(30000);clusterConfig.setReconnectionTimeout(3000);//当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。RedissonClient redisson = Redisson.create(config); //RedissonClien本身是线程安全的,建客户端(发现创建RedissonClient非常耗时)/***********************************************Redisson提供的所有对象都包含了同步和异步执行方式*************************************************/RAtomicLong longObject = redisson.getAtomicLong("myLong");longObject.compareAndSet(3, 401);// 同步执行方式RFuture<Boolean> result = longObject.compareAndSetAsync(3, 401);// 异步执行方式//首先获取redis中的key-value对象,key不存在没关系RBucket<String> keyObject = redisson.getBucket("key");//如果key存在,就设置key的值为新值value//如果key不存在,就设置key的值为valuekeyObject.set("value");//最后关闭RedissonClientredisson.shutdown();}}