依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.9.0</version>
</dependency>
配置
spring:
redis:
database: 0
#cluster:集群模式
#sentinel:哨兵模式
host: localhost
port: 6379
# 有密码填密码,没有密码不填
password:
# 连接超时时间
timeout: 1000ms
# 高版本springboot中使用lettuce
lettuce:
pool:
# 连接池最大连接数(负值表示无限制)
max-active: 8
# 连接池最大阻塞等待时间(负值无限制)
max-wait: 5000ms
# 最大空闲链接数
max-idle: 8
# 最小空闲链接数
min-idle: 0
配置类
package ws.util;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
//自定义RedisTemplate,Jackson2JsonRedisSerializer
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//自定义RedisTemplate
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(redisConnectionFactory);
//序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//String序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash采用String序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value采用jackson序列化方式
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value序列化采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
/**
* 重写Redis序列化方式,使用fastJson方式:
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//自定义RedisTemplate
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(redisConnectionFactory);
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
//String序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash采用String序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value采用jackson序列化方式
template.setValueSerializer(fastJsonRedisSerializer);
//hash的value序列化采用jackson
template.setHashValueSerializer(fastJsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
/**
* redis string
*
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
ValueOperations<String, Object> redisString = redisTemplate.opsForValue();
return redisString;
}
/**
* redis hash
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* redis list
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* redis set
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* redis zset
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
测试
package ws;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;
import ws.boot;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = boot.class)
public class test{
@Autowired
private ValueOperations<String, Object> s;
@Test
public void t(){
s.set("1",1);
System.out.println(s.get("1"));
}
}
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
</dependency>
spring:
redis:
database: 0
# cluster:
# nodes:
# - localhost:6379
# max-redirects: 3 # 获取失败 最大重定向次数
#password:
host: localhost
port: 6379
# 连接超时时间
timeout: 1000ms
# 高版本springboot中使用lettuce
lettuce:
pool:
# 连接池最大连接数(负值表示无限制)
max-active: 8
# 连接池最大阻塞等待时间(负值无限制)
max-wait: 5000ms
# 最大空闲链接数
max-idle: 8
# 最小空闲链接数
min-idle: 0
##Redisson其它配置可以看RedissonAutoConfiguration自动配置的代码
redisson:
# cluster-servers-config:
# cluster-nodes: ${spring.redis.cluster.nodes}
# load-balancer-mode: RANDOM
# #password: ${spring.redis.password}
# slave-connection-minimum-idle-size: 8
# slave-connection-pool-size: 16
# sslEnableEndpointIdentification: false
config: |
singleServerConfig:
address: redis://localhost:6379
threads: 8
nettyThreads: 8
transportMode: NIO
@Autowired
private RedissonClient redissonClient;
@Autowired
RedisTemplate redisTemplate;
@RequestMapping("/a")
public String a() {
RLock a = redissonClient.getLock("a");
//设置key过期时间默认30s,会开启守护线程续期,剩余时间还剩1/3
a.lock();
a.unlock();
// 加锁以后10秒钟自动解锁,无需调用unlock方法手动解锁,不续期
a.lock(10, TimeUnit.SECONDS);
//尝试获取锁,做多等待十秒钟,续期
a.tryLock(10,TimeUnit.SECONDS);
//尝试获取锁,做多等待5秒钟,锁存在10s,不续期
a.tryLock(5,10,TimeUnit.SECONDS);
redisTemplate.opsForValue().set("b",3);
System.out.println(redisTemplate.opsForValue().get("b"));
System.out.println("a");
return "a";
}
/**redis位图,基于Redis的Redisson集群分布式BitSet通过RClusteredBitSet
RBitSet set = redissonClient.getBitSet("simpleBitset");
set.set(0, true);
System.out.println(set.get(0));
set.set(1812, false);
set.clear(0);
**/
/*
*代码配置Redisson
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.setTransportMode(TransportMode.NIO);
SingleServerConfig singleServerConfig = config.useSingleServer();
//可以用"rediss://"来启用SSL连接
singleServerConfig.setAddress("redis://127.0.0.1:6379");
singleServerConfig.setPassword("123456");
RedissonClient redisson = Redisson.create(config);
return redisson;
}**/
Redis实现实时排名有序集合zset常用命令
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,
不同的是每个元素都会关联一个double类型的分数。
ZADD key score1 member1 [score2 member2]
向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARD key
获取有序集合的成员数
ZCOUNT key min max
计算在有序集合中指定区间分数的成员数
ZINCRBY key increment member
有序集合中对指定成员的分数加上增量 increment
ZLEXCOUNT key min max
在有序集合中计算指定字典区间内成员数量元素成员前加 [ 符号
ZRANGE key start stop [WITHSCORES]
通过索引区间返回有序集合成指定区间内的成员,下标从0开始,-1代表倒数第一个;参数WITHSCORES表示显示元素的分数;
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]
通过分数返回有序集合指定区间内的成员
ZRANK key member
返回有序集合中指定成员的索引
ZREM key member [member …]
移除有序集合中的一个或多个成员
ZREMRANGEBYLEX key min max
移除有序集合中给定的字典区间的所有成员
ZREMRANGEBYRANK key start stop
移除有序集合中给定的排名区间的所有成员
ZREMRANGEBYSCORE key min max
移除有序集合中给定的分数区间的所有成员
ZREVRANGE key start stop [WITHSCORES]
返回有序集中指定区间内的成员,通过索引,分数从高到底
ZREVRANGEBYSCORE key max min [WITHSCORES]
返回有序集中指定分数区间内的成员,分数从高到低排序
ZREVRANK key member
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
ZSCORE key member
返回有序集中,成员的分数值
设置值SETBIT key offset value,setbit命令设置的vlaue只能是0或1两个值
获取值GETBIT key offset
获取Bitmaps指定范围值为1的个数BITCOUNT key [start end]
Bitmaps间的运算 BITOP operation destkey key [key, …]
bitop是一个复合操作, 它可以做多个Bitmap的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中
reids在版本 3.2.0之后,引入了geo功能,基于zset可用于处理地理位置。涉及到的相关命令有:
geoadd:添加地理位置的坐标。
GEOADD key longitude latitude member [longitude latitude member …]
GEOADD keyname 13.361389 38.115556 “name” 15.087269 37.502669 “name1”
geopos:获取地理位置的坐标。
GEOPOS key member [member …]
geodist:计算两个位置之间的距离。
GEODIST key member1 member2 [m|km|ft|mi]
georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
GEORADIUS mykey 15 37 200 km WITHDIST WITHCOORD
georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
geohash:返回一个或多个位置对象的 geohash 值
GEOHASH key member [member …]
如果想删除可以用操作zset的方法
ops=redisTemplate.opsForGeo()
添加位置信息
ops.add(key, point, name);
获取位置
ops.position(key, name);
获取两个位置之间的距离
ops.distance(key, name1, name2, Metric metric) Metric单位信息, 可以是 null默认使用米
根据给定地理位置坐标获取指定范围内的地理位置集合
ops.radius(key, Circle within)
在redis当中,提供了两种数据持久化的方式,分别为RDB以及AOF,默认开启RDB方式
RDB持久化方案
Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机
save [seconds] [changes]意为在seconds秒内如果发生了changes次数据修改,则进行一次RDB快照保存
可以配置多条save指令,让Redis执行多级的快照保存策略。也可以通过SAVE或者BGSAVE命令手动触发RDB快照保存.
SAVE 阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
BGSAVE 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。 Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。
AOF持久化方案
AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新
开启进行如下配置
appendonly yes
appendfsync no:不进行fsync,将flush文件的时机交给OS决定,速度最快
appendfsync always:每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢
appendfsync everysec:折中的做法,交由后台线程每秒fsync一次
定时过期
每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据
惰性过期
只有当访问一个key时,才会判断该key是否已过期,过期则清除节省CPU资源,却对内存非常不友好
定期过期
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果
redis采用定期过期+惰性过期
配置定时时间
hz 10 取值范围是 1~500,通常不建议超过 100,只有在请求延时非常低的情况下可以将值提升到 100
指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据
配置maxmemory-policy volatile-lru
maxmemory-policy 六种方式
volatile-lru:只对设置了过期时间的key进行LRU(默认值)
allkeys-lru : 删除lru算法的key
volatile-random:随机删除即将过期key
allkeys-random:随机删除
volatile-ttl : 删除即将过期的
noeviction : 永不过期,返回错误
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点
主节点配置
设置为后台运行
daemonize yes
保存pid的文件
pidfile /var/run/redis_6379.pid
绑定的主机地址,这里注释掉,开放ip连接
bind 127.0.0.1
指定日志文件
logfile “6379.log”
从节点配置额外配置
配置master的IP和端口号
replicaof 127.0.0.1 6379
配置master的密码
masterauth 123456
配置从节点是只读模式
replica-read-only yes
重启服务
info replication
Sentinel(哨兵)是Redis的高可用性解决方案:由一个或多个Sentinel实例 组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器.
修改redis-sentinel配置文件 sentinel.conf,没有就创建一个
Redis 集群完全去中心化。Redis 把所有的 Key 分成了 16384 个 slot,每个 Redis 实例负责其中一部分 slot 。集群中的所有信息(节点、端口、slot等),都通过节点之间定期的数据交换而更新。
redis集群必须要求有6个实例,也就是说至少要启动6个redis-server进程
redis.config配置
port 9001(每个节点的端口号)
daemonize yes
bind 127.0.0.1(绑定当前机器 IP)
dir /data/(数据文件存放位置)
pidfile /var/run/redis.pid
cluster-enabled yes(启动集群模式)
cluster-config-file nodesport.conf(这不是用户可编辑的配置文件,而是Redis群集节点每次发生更改时自动保留群集配置)
cluster-node-timeout 15000 #Redis群集节点不可用的最长时间
appendonly yes
启动所有redis-server实例
执行创建集群命令:
./bin/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.01:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
replicas设置为1,副本和主节点比值
比如6个节点,设置1,6*(1/2)=3个master,6*(1/2)=3个slave;
slot(槽点)是用来进行写指令的,只分配给master,一共16384个槽点,均匀分配给各个master。slave只是作为备份,不执行写指令,不需要槽点,所以分配0个槽点。
redis-cli -c #连接到集群节点,c即cluster
>cluster info
>info replication
redis cluster 不可用的几种情况
1 集群主库半数宕机(无论是否从库存活)
2 集群某一节点的主从全数宕机。