Redis

安装Redis

1
2
3
yum install centos-release-scl scl-utils-build
yum install -y devtoolset-8-toolchain
scl enable devtoolset-8 bash
1
2
3
4
5
6
7
yum install gcc
wget http://download.redis.io/releases/redis-6.0.8.tar.gz
tar -zxvf redis.tar.gz
cd redis
make
make install
cd /usr/local/bin

后台启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd /home/redis
cp redis.conf /etc/redis.conf
#修改etc下的配置文件
#将 daemonize no 改为 yes
cd /usr/local/bin
redis-server /etc/redis.conf
ps -ef | grep redis
#连接redis
redis-cli
#关闭redis
#1、进入服务输入shutdown
shutdown
#2、退出服务关闭进程
exit
ps -ef | grep redis
kill -9 进程号

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看所有key
keys *
# 查看key是否存在
exist key
# 查看key类型
type key
# 删除key
del key
unlink key
# 设置时限
expire key seconds
# 查看时限 -1永不过期 -2已经过期
ttl key
# 查看key数量
dbsize
# 清空库
flushdb
flushall

常用数据类型

字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 存值
set <key> <value>
setnx <key> <value> #只有key不存在的情况下才能存数据
mset <k1> <v1> <k2> <v2> <k3> <v3>
setrange <key> <startIndex> <value>
setex <key> <expireTime> <value> #存值时就设置过期时间
# 取值
get <key>
mget <k1> <k2> <k3>
gerrange <key> <startIndex> <endIndex>
getset <key> <newValue>
# 追加
append <key>
# 获取字符串长度
strlen <key>
# 对数字值+1
incr <key>
incrby <key> Interage #自定义增加数
# 对数字值-1
decr <key>
decrby <key> Interage #自定义减少数

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 存值
lpush/rpush <k1> <v1> <k2> <v2> <k3> <v3>
linsert <key> before/after <value> <insertValue>
# 吐值
lpop/rpop <key> #取出值后列表就删除了
# 产看值
lrange <key> <startIndex> <stopIndex>
lrange <key> 0 -1 # 查看所有
lindex <key> <index>
# 获取列表长度
llen <key>
# 删除
lrem <key> <n> <value> #删除n个value的值,列表可以有重复的值
# 替换
lset <key> <index> <value>

集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 存值
sadd <key> <v1> <v2> <v3>
# 取值
smembers <key>
srandmember <key> <n> # 随机取出n个值
# 判断 有1.无0
sismember <key> <value> # 判断key中是否有value值
# 查询个数
scard <key>
# 删除
srem <key> <v1> <v2>
# 吐值
spop <key> # 随机从该集合中吐出一个值
# 移动
smove <source> <destination> value
# 交集
sinter <key1> <key2>
# 并集
sunion <key1> <key2>
# 差集
sdiff <key1> <key2> # key1独有的

哈希

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 赋值
hset <key> <field> <value>
hmset <key> <f1> <v1> <f2> <v2>
hsetnx <key> <field> <value>
hincrby <key> <field> <increment>
# 取值
hget <key> <field>
# 判断
hexist <key> <field>
# 取出所有field
hkeys <key>
# 取出所有的value
hvals <key>

有序集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 存值
zadd <key> <score1> <value1> <score2> <value2
# 取值
zrange <key> <startIndex> <stopIndex> [withscores]
zrangebyscore <key> <startScore> <stopIndex> [withscores]
# 转换排序方式
zrevrange <key>
# 增加分数
zincrby <key> <increment> <value>
# 删除
zrem <key> <value>
# 统计
zcount <key> <startScore> <stopIndex>
# 查看排名
zrank <key> <value>

配置文件

  • 改为#bind 127.0.0.1 -::1支持远程访问
  • protected-mode no关闭保护模式
  • port 6379
  • tcp-backlog 511
  • timeout 00:永不超时,以秒为单位
  • tcp-keepalive 300
  • daemonize yes 支持后台启动
  • pidfile /var/run/redis_6379.pid
  • loglevel debug verbose notice warning
  • logfile
  • databases 16Redis默认有16个库
  • requirepasss设置密码

发布订阅

  1. 打开一个客户端订阅channel1

    subscribe channel1

  2. 打开另一个客户端,发送消息

    publish chanenl1 hello

  3. 打开第一个客户端查看信息

新数据类型

Bitmaps

1
2
3
4
5
6
7
8
# 存值
setbit <key> <offset> <value> # value为0或1
# 取值
getbit <key> <offset>
# 统计字符串被设置为1的个数
bitcount <key> [startIndex] [stopIndex] # Redis最小单位是byte,每个byte有8bit,所以一个index是8bit
# 位运算
bitop and <newkey> <key1> <key2>

HyperLogLog

1
2
3
4
5
6
# 存值
pfadd <key> <value>
# 统计
pfcount <key>
# 格式合并
pfmerge <destinationKey> <sourceKey1> <sourceKey2>

Geospatial

1
2
3
4
5
6
7
8
# 存值
geoadd <key> <longitude> <latitude> <member> #经度 维度 名称
# 取值
geopos <key> <member>
# 两直线距离
geodist <key> <member1> <member2> [m|km|ft|mi] # 默认为米
# 以某中心半径内的元素
georadius <key> <longitude> <latitude> <radius>

Jedis

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.0-alpha2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

1
2
3
4
5
6
public class JedisDemo01 {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.80.66",6379);
System.out.println(jedis.ping());
}
}

springboot

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Redis
# Redis服务器地址
spring.redis.host=192.168.80.66
# Redis服务器默认端口
spring.redis.port=6379
# Redis数据库索引
spring.redis.database=0
# 连接超时时间
spring.redis.timeout=1800000
# 连接池最大连接数(使用负值则表示没有限制)
spring.redis.lettuce.pool.max-active=20
# 最大阻塞等待时间(使用负值则表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中最大空闲连接
spring.redis.lettuce.pool.max-idle=5
# 连接池中最小空闲连接
spring.redis.lettuce.pool.min-idle=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
template.setKeySerializer(redisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory){
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;

}
}

事务

队列

multi、exec、discard

悲观锁

watch、unwatch

乐观锁

持久化

RDB

在指定的时间间隔内将内存中的数据集快照写入磁盘

默认持久化文件名称dump.rdb

1
2
3
4
5
6
# 当redis无法写入磁盘的话,直接关掉redis的写操作
stop-writes-onbgsave-error yes
# 压缩文件
rdbcompression yes
# 完整性检查
rebchecksum yes

AOF

AOF和RDB同时开启,系统默认读取AOF的数据

以日志的形式来记录每个写操作(增量保存),将redis执行过的所有写指令记录下来(读操作不记录),只许追加文件不可以改写文件

默认持久化文件名称appendonly.aof

1
2
3
4
5
6
7
# 开启aof
appendonly yes
# 修复aof文件
redis-check-aof --fix appendonly.aof

# 同步频率设置
appendfsync [always、everysec、no]

主从复制

常规模式

一主二仆、薪火相传、反客为主

在redis从机上执行 slavaof 主redis的IP 主redis的端口

slaveof no one 当主服务器宕机后,从机成为主机

哨兵模式

反客为主的自动版

  1. 新建sentinel.conf文件

    sentinel monitor mymaster 主机ip 主机端口 哨兵同意迁移的数量

  2. redis-sentinel sentinel.conf

  3. 从机配置文件中replica-priority的值越小越容易成为新的主机,如果相同会选取runid小的成为新的主机,runid为redis服务启动时生成的随机数

集群

  1. cluster-enable yes 打开集群模式

  2. cluster-config-file nodes-6379.conf 设置节点配置文件名

  3. cluster-node-timeout 15000 设置节点失联时间,超过该时间,自动进行主从互换

  4. 进入安装包解压的目录

    1
    2
    cd ./src
    redis-cli --cluster create --cluster-replicas 1 多个ip地址
  5. 通过集群方式连接redis

    1
    2
    redis-cli -c
    cluster nodes #查看集群节点
    1
    2
    3
    cluster keyslot key #查看插槽值
    cluster countkeysinslot
    cluster getkeysinslot

常见问题

缓存穿透

  • 对空值缓存
  • 设置可访问的名单
  • 采用布隆过滤器
  • 进行实时监控

缓存击穿

  • 预先设置热门数据
  • 实时调整
  • 使用锁

缓存雪崩

  • 构建多级缓存架构
  • 使用锁或队列
  • 设置过期标志更新缓存
  • 将缓存失效时间分散开

分布式锁

新功能

acl setuser 名称 [on/off] >password ~关键字 + get

auto Username password