Redis
1.redis基础知识
切换数据库
select 3
查看数据库内存
DBSIZE
查看数据库所有的key
keys *
清空当前数据库内容
flushdb
清除所有数据库内容
flushall
2.redis五大数据类型
Redis-key
# 获取全部的key
keys *
# 设置key-val
set name dhn
# 获取key对应的value
get name
# 移除key
move name 1
# 设置过期时间 10代表十秒
expire name 10
# 查看过期时间 (-2代表过期)
ttl name
# 查看当前key的类型
type name
# 是否存在key
exists key
String类型
# 追加字符串,如果当前key不存在,相当于setkey
append key1 hello
# 自增
incr views
# 自减
decr views
# 设置步长
incrby views 10
decrby views 10
# 获取范围的字符串
getrange key1 0 3
# 替换字符串
setrange key2 1 xx
# setex (set with expire) 设置过期时间
# setnx (set if not exist) 如果不存在设置
# 设置多个key-value
mset k1 v1 k2 v2
# 获取多个
mget k1 k2
# 设计对象
mset user:1:name zhangsan user:1:age 18
# 先get再set,不存在值则为nil,如果存在先获取当前值再更改新值
getset db redis
List类型
所有的list命令都是用l开头
# 一个或多个插入列表头部
lpush list one
lpush list two
lpush list three
# 获取多个值
lrange list 0 -1 # 获取全部
# 从右边插入
rpush list right
# 从左边弹出
lpop list
# 从右边弹出
rpop list
# 用下标获取值
lindex list 0
# 获取长度
llen list
# 移除指定得值
lrem list 1 two # 移除一个two
# 截取值
ltrim list 1 2
# 移动列表的最后一个元素,将他移动到新的列表中
rpoplpush mylist myotherlist
# 将列表中指定下标的值替换为另外的值
lset list 0 item
# 在列表前后插入值
linsert list before/after item2 item3
Set类型
不能重复添加
# 设置键值
sadd myset "hello"
# 读取
smembers myset
# 查看是否存在
sismember myset hello
# 获取元素个数
scard myset
# 移除某一个元素
srem myset hello
# 随机抽选一个元素
srandmember myset
# 随机移除元素
spop myset
# 将一个指定的值移动到另外的set中
smove myset myset2 hello
#################################
# 差集、交集、并集
sdiff key1 key2
sinter key1 key2
sunion key1 key2
Hash类型
Map集合,key-value
# 设置key value
hset myhash field1 dhn
# 获取值
hset myhash field1
# 设置多个key-value
hmset myhash field1 hello field2 world
# 获取多个key
hmget myhash field1 field2
# 获取hash中所有的key-value
hgetall myhash
# 删除指定的key字段
hrem myhash field1
# 获取长度
hlen myhash
# 判断hash中的指定字段是否存在
hexists myhash field2
# 获取所有的字段和值
hkeys myhash
hvals myhash
# 自增
hincrby myhash field3 1
# 设置一个hash,如果不存在则创建
hsetnx myhash field4 hello
Zset类型
有序集合,在set的基础上,增加了一个值,
# 设置值
zset myset 1 one
zset myset 2 two
# 获取某些下标的值
zrange myset 0 -1
# 获取范围的值
zadd salary 2500 zs
zadd salary 5000 ls
zadd salary 500 ww
zrangebyscore salary -inf +inf #获取所有的范围
# 读取带key的遍历范围,从小到大排序
zrangebyscore salary -inf +inf withscores
zrangebyscore salary -inf 5000 withscores
# 从大到小排序
zrevrange salary 0 -1
# 移除指定元素
zrem salary zs
# 获取有序集合中的个数
zcard salary
# 计算区间变量的个数
zcount salary 2000 5000
3.Geospatial地理位置详解
# geoadd添加地理位置
127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> GEOADD china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen
(integer) 2
127.0.0.1:6379> GEOADD china:city 120.16 30.24 hangzhou 108.96 34.26 xian
# 获取指定城市的经度和纬度
geopos china:city shenzhen
# 返回两个给定位置之间的距离
GEODIST china:city beijing shanghai
# georadius以给定的经纬度为中心,找出某一半径内的元素
georadius china:city 110 30 1000 km
withdist:显示经度
withcoord:显示经度和纬度
count 1 限制查询一个
# georadiusbymember:找出指定范围内的元素,中心点是由给定的位置元素决定
georadiusbymember china:city shanghai 1000 km
4.redis事务
Redis事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!
一次性、顺序性、排他性
Redis事务没有隔离级别的概念
Redis单条命令保存原子性,但是事务不保证原子性
Redis事务:
- 开启事务()
- 命令入队()
- 执行事务()
正常执行事务
127.0.0.1:6379> MULTI #开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec #执行事务
1) OK
2) OK
3) "v2"
4) OK
放弃事务
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> DISCARD # 放弃事务
编译型异常(代码有问题!命令有错!),事务中的所有命令都不会被执行
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> getset k3 #错误的命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 所有的命令都不会被执行
运行时异常(1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> incr k1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
5.Redis实现乐观锁
监控:Watch
- 悲观锁:什么时候都会出问题,无论做什么都会加锁
- 乐观锁:认为什么时候都不回出现问题,所以不会加锁,更新数据的时候去判断一下,在此期间是否修改过这个数据
正常执行成功
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec # 事务正常结束,数据期间没有发生变动,这个时候就正常执行成功
1) (integer) 80
2) (integer) 20
测试多线程,使用watch可以当作redis的乐观锁操作
unwatch #解除监视
6.Jedis
我Jedis是redis官方推荐的java连接开发工具!使用java操作redis中间件。
1.导入对应的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.10</version>
</dependency>
</dependencies>
2.编码测试
- 连接数据库
- 操作命令
- 断开连接
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.31.97",6379);
jedis.set("k1","v1");
System.out.println(jedis.get("k1"));
}
7.Springboot集成Redis
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置连接
spring.redis.host=192.168.21.131
spring.redis.port=6379
3.测试
@Test
void contextLoads() {
redisTemplate.opsForValue().set("mykey","dhn");
String mykey = (String) redisTemplate.opsForValue().get("mykey");
System.out.println(mykey);
}
8.自定义RedisTemplate
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//Json序列化配置
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);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用string的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value徐丽华也采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
测试
@Test
public void test01() throws JsonProcessingException {
User user = new User("代浩楠", 24);
// String jsonUser = new ObjectMapper().writeValueAsString(user);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
8.Redis.conf详解
- 大小写不敏感
-
可以包含多个配置文件(即,这些文件导入到主配置文件
Redis.conf
中) -
网络
bind 0.0.0.0 # IP(默认127.0.0.1) protected-mode no # 保护模式(默认yes) port 6379 # 端口设置(默认6379)
-
通用
daemonize yes # 以守护进程方式运行,即后台运行(默认no) pidfile /var/run/redis_6379.pid # 如果以后台运行,必须指定一个pid文件 # 日志 # Specify the server verbosity level. # This can be one of: # debug (大量信息, 使用于测试或开发阶段) # verbose (许多很少有用的信息,但不像调试级别那样混乱) # notice (比较冗长,你可能想在生产环境中使用) # warning (只有非常重要/关键的消息被记录下来) loglevel notice # 默认notice logfile "" # 日志的文件位置名 databases 16 # 数据库的数量(默认16) always-show-logo yes # 是否开启 logo (默认yes)
-
持久化,在规定时间内,执行了多少次操作,会被持久化到文件(.rdb,.aof)
save 900 1 # 900秒内(15分钟),如果至少有1个Key进行修改,我们就进行持久化操作 save 300 10 # 300秒内(5分钟),如果至少有10个Key进行修改,我们就进行持久化操作 save 60 10000 # 60秒内(1分钟),如果至少有10000个Key进行修改,我们就进行持久化操作 stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作(默认yes) rdbcompression yes # 是否压缩rdb文件(默认yes),会消耗一些CPU资源 rdbchecksum yes # 保存rdb文件时,进行错误检查检验 dir ./ # rdb文件保存的目录
requirepass 你的密码 # 设置密码(默认被注释着需要自己解开注释)
-
安全 security
requirepass 你的密码 # 设置密码(默认被注释着需要自己解开注释)
当然可以通过命令行配置(临时,服务重启失效)
-
客户端限制
# maxclients 10000 # 限制最多10000个客户端访问(默认注释)
-
内存管理
# maxmemory <bytes> # 最大内存设置(默认注释) # maxmemory-policy noeviction # 内存达到上限之后的处理策略(默认noeviction) # 1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) # 2、allkeys-lru : 删除lru算法的key # 3、volatile-random:随机删除即将过期key # 4、allkeys-random:随机删除 # 5、volatile-ttl : 删除即将过期的 # 6、noeviction : 永不过期,返回错误
-
APPEND ONLY MODE (AOF配置)
appendonly no # 默认是不开启aof的,默认使用rdb方式持久化 appendfilename "appendonly.aof" # 持久化的文件名 # appendfsync always # 每次修改都会同步,销耗性能 appendfsync everysec # 每秒执行一次同步,可能会丢失这1秒的数据 # appendfsync no # 不同步,操作系统自己同步数据,速度最快
9.redis持久化
1.RDB(Redis DataBase)
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。 保存文件格式
dump.rdb
设置RDB文件保存条件
9.Redis订阅发布
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。微信、微博、关注系统!
Redis客户端可以订阅任意数量的频道
订阅/发布消息图:
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
命令
这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播、实时提醒等。
测试
# 订阅端
SUBSCRIBE dhn
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "dhn"
3) (integer) 1
1) "message"
2) "dhn"
3) "hahhaha"
# 发布端
127.0.0.1:6379> publish dhn hahhaha
(integer) 1
10.Redis主从复制
概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。
主从复制的主要作用
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础。
一般来说,要将Redis运用与工程项目中,只使用一台Redis是万万不能的(避免宕机,一主二从),原因如下:
从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台服务器最大使用内存不超过20G。
环境配置
只配置从库,不用配置主库
127.0.0.1:6379> info replication # 查看当前库的信息
# Replication
role:master # 角色 master
connected_slaves:0 # 没有从机
master_failover_state:no-failover
master_replid:826a2581d6908aad3410e0f1b2f6dbd60ca4d6db
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础。
一般来说,要将Redis运用与工程项目中,只使用一台Redis是万万不能的(避免宕机,一主二从),原因如下:
从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台服务器最大使用内存不超过20G。
环境配置
只配置从库,不用配置主库
127.0.0.1:6379> info replication # 查看当前库的信息
# Replication
role:master # 角色 master
connected_slaves:0 # 没有从机
master_failover_state:no-failover
master_replid:826a2581d6908aad3410e0f1b2f6dbd60ca4d6db
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0