@guodong
2020-11-06T13:04:05.000000Z
字数 10651
阅读 907
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为集合2
sunion 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);
//最小空闲连接数, 默认0
jedisPoolConfig.setMinIdle(0);
// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
jedisPoolConfig.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的stream
Stream<String> keysStreamByPattern = redisson.getKeys().getKeysStreamByPattern("key*");
//redisson.getKeys().getKeysStream()扫描 以Stream的形式返回全部的key
Stream<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.StringCodec
config.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节点的连接池中连接数最大为500
clusterConfig.setSlaveConnectionPoolSize(500);//设置对于slave节点的连接池中连接数最大为500
clusterConfig.setIdleConnectionTimeout(10000);//如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
clusterConfig.setConnectTimeout(30000);//同任何节点建立连接时的等待超时。时间单位是毫秒。
clusterConfig.setTimeout(3000);//等待节点回复命令的时间。该时间从命令发送成功时开始计时。
clusterConfig.setRetryAttempts(3);//设置失败重试次数,默认为3
clusterConfig.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的值为value
keyObject.set("value");
//最后关闭RedissonClient
redisson.shutdown();
}
}