Redis

1 NoSql

1.1 单机MySQL

  • 数据量超过300w条,需要建立索引,单机无法存储索引
  • 访问量读写混合,一台服务器无法承受
  • 数据量过大,一太机器无法存放

1.2 mysql+缓存+垂直拆分

由于80%以上的网站工作量是读,所以引入了缓存,并进行(垂直拆分)读写数据库的分离。

1.3 分库分表+mysql集群+水平拆分

1.4 新型数据库

在这里插入图片描述

1.5 Not only Sql

特点

  • 方便扩展(数据之间没有关系)
  • 大数据量高性能(每秒写8w次,读11w次)
  • 数据类型是多种多样的

1.6 大数据时代

3v:

  • 海量Volume
  • 多样Variety
  • 实时Velocity
    3高
  • 高并发
  • 高可用
  • 高可扩展

1.7 数据库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.8 NoSQL的四大分类

- KV键值对
在这里插入图片描述
在这里插入图片描述
敬畏之心可以使人进步!

2 Redis入门

2.1 基本概念

Remote Directory Server
远程字典服务
是当下最热门的NoSQL之一,也被人们称之为结构化数据库
在这里插入图片描述
在这里插入图片描述

2.2 安装配置

在这里插入图片描述

2.3 基本知识

redis默认有16个数据库
在这里插入图片描述
不同的数据库有不同的值
redis为什么是6379?

对应的一个女明星的名字

redis为什么是单线程?

redis是基于内存操作的,CPU不是redis的性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程实现,所以就直接使用单线程了。

redis单线程为什么还快?

redis是基于内存进行操作的,而多线程会发生上下文的切换,耗时,对于内存系统来说,如果没有上下文切换,效率就是最高的。多次读写都是在一个CPU上的。

2.4 五大数据类型

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

2.4.1 redis-key

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set name zy
OK
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> exists name #判断当前key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> move name 0 #移除当前key,但一般不会这么用
(error) ERR source and destination objects are the same
127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name zy
OK
127.0.0.1:6379> expire name 10  # 设置key的过期时间
(integer) 1
127.0.0.1:6379> ttl name #查看当前key的剩余时间
(integer) 5
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> type age #查看当前key的类型
string

直接查阅命令

2.4.2 String

1) "age"
127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> append key1 hello
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1
(integer) 7
##################################
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incrby views 10
(integer) 11
127.0.0.1:6379> decrby views 5
(integer) 6
################################
127.0.0.1:6379> set k1 hello,zy
OK
127.0.0.1:6379> get k1
"hello,zy"
127.0.0.1:6379> getrange k1 0 5
"hello,"
127.0.0.1:6379> getrange k1 0 4
"hello"
127.0.0.1:6379> getrange k1 0 -1 #获取全部的字符串
"hello,zy"
127.0.0.1:6379> setrange k1 1 xxxx #替换
(integer) 8
127.0.0.1:6379> get k1
"hxxxx,zy"
############################################
127.0.0.1:6379> setex key2 30 hello  #设置过期时间
OK
127.0.0.1:6379> ttl key2
(integer) 25
127.0.0.1:6379> keys *
1) "key2"
2) "k1"
127.0.0.1:6379> setnx key3 "redis"#不存在才会设置
(integer) 1
127.0.0.1:6379> setnx key3 "mongoDB"#已经存在,所以不进行设置
(integer) 0
127.0.0.1:6379> keys *
1) "key3"
2) "k1"
###########################################
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 #是一个原子性的操作,要么一起成功,要么一起失败
(integer) 0
######################################################
127.0.0.1:6379> mset user:1:name "zs" user:1:age 20
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "user:1:age"
4) "k1"
5) "user:1:name"
127.0.0.1:6379> mset user:2 {name:"zy",age:20}
Invalid argument(s)

###
127.0.0.1:6379> getset k4 "redis"
(nil)
127.0.0.1:6379> get k4
"redis"
127.0.0.1:6379> getset k4 "redis02"
"redis"

2.4.3 List

在redis中,可以把redis当成栈或者队列
所有的list命令都是以L开头的

127.0.0.1:6379> Lpush list one
(integer) 1
127.0.0.1:6379> Lpush list two
(integer) 2
127.0.0.1:6379> Lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 0
1) "three"
127.0.0.1:6379> rpush list four
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
127.0.0.1:6379> LPOP list
"three"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "four"
127.0.0.1:6379> rpop list
"four"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> rindex list 0
(error) ERR unknown command `rindex`, with args beginning with: `list`, `0`, 
127.0.0.1:6379> llen list
(integer) 2
127.0.0.1:6379> lrem list 1 one
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
127.0.0.1:6379> lpush list three three
(integer) 3
127.0.0.1:6379> rpush list one one
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
5) "one"
127.0.0.1:6379> lrem list 2 three #删除2个“three”
(integer) 2
127.0.0.1:6379> lpush list1 1 2 3 4
(integer) 4
127.0.0.1:6379> ltrim list1 2 3 #通过下标截取长度,同时list被改变了
OK
127.0.0.1:6379> lrange list1 0 -1
1) "2"
2) "1"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "one"
127.0.0.1:6379> rpoplpush list list
"one"
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
3) "one"
127.0.0.1:6379> exists list
(integer) 1
127.0.0.1:6379> lset list 0 item
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
2) "two"
3) "one"
127.0.0.1:6379> lset list 1 three
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
2) "three"
3) "one"
127.0.0.1:6379> linsert list before 0 two
(integer) -1
127.0.0.1:6379> lrange list 0 -1
1) "item"
2) "three"
3) "one"
127.0.0.1:6379> linsert list before item two
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "item"
3) "three"
4) "one"
127.0.0.1:6379> linsert list after item four
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "item"
3) "four"
4) "three"
5) "one"
  • list实际上是一个链表,左右都可以插入值
  • 如果key不存在,则在插入的时候会新建链表
  • 如果移除了所有值,空链表,代表不存在
  • 在两边插入或者改动值,效率最高

消息排队!消息队列!

2.4.4 Set

set集合是无序不重复集合
抽随机!

127.0.0.1:6379> sadd myset 'zy'
(integer) 1
127.0.0.1:6379> sadd myset 'set' 'set1'
(integer) 2
127.0.0.1:6379> smembers myset
1) "set1"
2) "zy"
3) "set"
127.0.0.1:6379> sismember myset set
(integer) 1
127.0.0.1:6379> sismember myset set2
(integer) 0
127.0.0.1:6379> scard myst
(integer) 0
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> srem myset set
(integer) 1
127.0.0.1:6379> srem myset set1
(integer) 1
127.0.0.1:6379> scard myset#计数
(integer) 1
127.0.0.1:6379> sadd myset 1 2 3 4 5 6 7 8 9 10
(integer) 10
127.0.0.1:6379> scard myset
(integer) 11
127.0.0.1:6379> SRANDMEMBER myset #随机获取一个值
"zy"
127.0.0.1:6379> SRANDMEMBER myset
"10"
127.0.0.1:6379> SRANDMEMBER myset
"2"
127.0.0.1:6379> SRANDMEMBER myset
"zy"
127.0.0.1:6379> SRANDMEMBER myset
"8"
127.0.0.1:6379> SRANDMEMBER myset
"9"
127.0.0.1:6379> SRANDMEMBER myset
"6"
127.0.0.1:6379> SRANDMEMBER myset
"5"
127.0.0.1:6379> SRANDMEMBER myset 5
1) "zy"
2) "1"
3) "3"
4) "4"
5) "10"
127.0.0.1:6379> SRANDMEMBER myset 5
1) "1"
2) "2"
3) "9"
4) "8"
5) "6"
127.0.0.1:6379> SRANDMEMBER myset 5
1) "1"
2) "10"
3) "7"
4) "5"
5) "2"
127.0.0.1:6379> 
127.0.0.1:6379> SMEMBERS myset #获取全部的值
 1) "3"
 2) "1"
 3) "zy"
 4) "10"
 5) "4"
 6) "7"
 7) "5"
 8) "2"
 9) "9"
10) "6"
11) "8"
127.0.0.1:6379> spop myset
"6"
127.0.0.1:6379> smove myset myset1 5 # 移除
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "3"
2) "1"
3) "zy"
4) "10"
5) "4"
6) "7"
7) "2"
8) "9"
9) "8"
127.0.0.1:6379> SMEMBERS myset1
1) "5"
127.0.0.1:6379> sdiff myset myset1 #差集
1) "1"
2) "3"
3) "zy"
4) "2"
5) "7"
6) "10"
7) "4"
8) "9"
9) "8"
127.0.0.1:6379> sinter myset myset1 # 交集
(empty list or set)
127.0.0.1:6379> sadd myset1 4
(integer) 1
127.0.0.1:6379> sinter myset myset1
1) "4"
127.0.0.1:6379> sunion myset myset1 #并集
 1) "9"
 2) "zy"
 3) "3"
 4) "1"
 5) "4"
 6) "10"
 7) "7"
 8) "5"
 9) "2"
10) "8"

2.4.5 Hash

和String没有太大区别

127.0.0.1:6379> hset hash k1 v1
(integer) 1
127.0.0.1:6379> hmset hash k2 v2 k3 v3
OK
127.0.0.1:6379> hget hash k1
"v1"
127.0.0.1:6379> hmget hash k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> hgetall hash
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"
127.0.0.1:6379> hdel hash k2
(integer) 1
127.0.0.1:6379> hgetall hash
1) "k1"
2) "v1"
3) "k3"
4) "v3"
127.0.0.1:6379> hlen hash
(integer) 2
127.0.0.1:6379> hexists hash k1
(integer) 1
127.0.0.1:6379> hexists hash k2
(integer) 0
127.0.0.1:6379> hkeys hash
1) "k1"
2) "k3"
127.0.0.1:6379> hset hash k2 5
(integer) 1
127.0.0.1:6379> hincrby hash k2 5
(integer) 10
127.0.0.1:6379> hget hash k2
"10"
127.0.0.1:6379> hsetnx hash k45
(error) ERR wrong number of arguments for 'hsetnx' command
127.0.0.1:6379> hsetnx hash k4 5
(integer) 1
127.0.0.1:6379> hsetnx hash k3 5
(integer) 0

用户信息的保存,或者经常变动的信息!
hash更适合于对象的存储,String更加适合字符串的存储!

2.4.6 ZSet

127.0.0.1:6379> zadd zs 1 one
(integer) 1
127.0.0.1:6379> zadd zs 2 two 3 three
(integer) 2
127.0.0.1:6379> zrange zs 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zadd salary 500 q 2500 w 5000 e
(integer) 3
127.0.0.1:6379> zrange salary 0 -1
1) "q"
2) "w"
3) "e"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "q"
2) "w"
3) "e"
127.0.0.1:6379> ZRANGEBYSCORE salary +inf -inf
(empty list or set)
127.0.0.1:6379> ZRANGEBYSCORE salary 0 -1
(empty list or set)
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores
1) "q"
2) "500"
3) "w"
4) "2500"
5) "e"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores 
1) "q"
2) "500"
3) "w"
4) "2500"
127.0.0.1:6379> zrem salary xiaohong
(integer) 0
127.0.0.1:6379> zrem salary w
(integer) 1
127.0.0.1:6379> zcrad salary
(error) ERR unknown command `zcrad`, with args beginning with: `salary`, 
127.0.0.1:6379> zcard salary
(integer) 2
127.0.0.1:6379> zcount salary 500 2500
(integer) 1
127.0.0.1:6379> ZREVRANGE salary 0 -1
1) "e"
2) "q"
127.0.0.1:6379> 

在这里插入图片描述

2.5 三种特殊数据类型

2.5.1 geospatial

朋友的定位,附近的人,打车距离计算等。
Geo

#规则,两级无法导入,一般通过java程序直接导入
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing 121.47 31.23 shanghai 106.50 29.53 chongqi 114.05 22.52 shenzhen 120.16 30.24 hongzhou 106.98 34.26 xiAn
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"
127.0.0.1:6379> geoadd china:city 118.90 39.42 laoting 103.99 30.77 chengdu 121.644576 29.896 ningbo
(integer) 3
127.0.0.1:6379> geodist china:city laoting chengdu km
"1659.7163"
127.0.0.1:6379> geodist china:city laoting ningbo km
"1088.5090"
127.0.0.1:6379> geodist china:city chengdu ningbo km
"1695.8717"
127.0.0.1:6379> georadius china:city 110 30 1000 km 
1) "chengdu"
2) "chongqi"
3) "xiAn"
4) "shenzhen"
5) "hongzhou"
127.0.0.1:6379> georadius china:city 110 30 500 km 
1) "chongqi"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist
1) 1) "chongqi"
   2) "341.9374"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist
1) 1) "chengdu"
   2) "582.9024"
2) 1) "chongqi"
   2) "341.9374"
3) 1) "xiAn"
   2) "552.5745"
4) 1) "shenzhen"
   2) "924.6408"
5) 1) "hongzhou"
   2) "977.5143"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist count 2
1) 1) "chongqi"
   2) "341.9374"
2) 1) "xiAn"
   2) "552.5745"
   # 底层的实现原理是zset
   127.0.0.1:6379> zrange china:city 0 -1
1) "chengdu"
2) "chongqi"
3) "xiAn"
4) "shenzhen"
5) "hongzhou"
6) "ningbo"
7) "shanghai"
8) "beijing"
9) "laoting"
   127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 200 km withdist
1) 1) "hongzhou"
   2) "166.7613"
2) 1) "ningbo"
   2) "149.3147"
3) 1) "shanghai"
   2) "0.0000"
127.0.0.1:6379> geohash china:city ningbo shanghai 
1) "wtqd046uu40"
2) "wtw3sj5zbj0"

2.5.2 Hyperloglog

在这里插入图片描述

127.0.0.1:6379> pfadd k1 a b c d e f g
(integer) 1
127.0.0.1:6379> pfadd k2 1 5 9 8 5 6 a
(integer) 1
127.0.0.1:6379> PFMERGE k3 k1 k2
OK
127.0.0.1:6379> PFCOUNT k3
(integer) 12

在这里插入图片描述

2.5.3 BitMaps

在这里插入图片描述
在这里插入图片描述

2.6 事务

redis单条命令是保证原子性的,但是事务不保证原子性!

redis事务的本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务的执行过程中,会按照顺序执行!
一次性、顺序性、排他性
redis事务没有隔离级别的概念
所有的命令在事务中并没有被执行,只有发起命令后才会执行

redis的事务:

  • 开启事务(multi)
  • 命令入队(其它命令)
  • 执行事务(exec)

锁:Redis可以实现乐观锁
执行事务

127.0.0.1:6379> multi
OK
127.0.0.1:6379> mset k1 v1 k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) "v2"

取消事务

127.0.0.1:6379> multi
OK
127.0.0.1:6379> mset k3 v3 k4 v4
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"

编译型异常(代码有问题!),事务中所有的命令都不会被执行

运行时异常,执行命令的时候其它命令可以正常执行,错误命令抛出异常

2.7 监控

2.7.1 悲观锁

无论什么时候都要加锁

2.7.2 乐观锁

更新数据的时候,判断一下在此期间是否有人修改过这个数据,version

  • 获取version
  • 更新的时候比较version

事务正常结束

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> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20

事务加锁多线程操作

127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby money 100
QUEUED
127.0.0.1:6379> decrby out 100
QUEUED
127.0.0.1:6379> exec
(nil)

可以使用watch进行乐观锁的操作
在这里插入图片描述

3 客户端

3.1 JRedis

<dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.4.0</version>
    </dependency>
public static void main(String[] args) {
        final Transaction multi;
        final Jedis jedis = new Jedis("192.168.1.10", 6379);
        multi = jedis.multi();
        try {
            jedis.flushDB();
            final JSONObject jsonObject = new JSONObject();
            jsonObject.put("name","zy");
            jsonObject.put("pwd",123456);
            final String s = jsonObject.toJSONString();
            multi.set("user1",s);
            multi.set("user2",s);
            int i=1/0;
        } catch (Exception e) {
            multi.discard();
            e.printStackTrace();
        }finally {
            multi.exec();
            System.out.println(jedis.get("user1"));
        }

    }

3.2 SpringBoot

在这里插入图片描述

 @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )//我们需要自己定义一个Redistemplate来替换默认的
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    	//默认的redistemplate没有过多的操作,redis 对象都是需要序列化的
    	//两个泛型都是object的类型,我们使用都需要强制转换
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    //由于我们的String类型是redis中最长使用的类型,所以说单独提出此方法
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

在这里插入图片描述
在这里插入图片描述
关于对象的保存,需要将对象序列化
在企业中,我们的pojo都会进行序列化
RedisConfig

package com.zy.redispro01.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.val;
import org.springframework.cache.annotation.EnableCaching;
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.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.net.UnknownHostException;

@EnableCaching
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        final ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectJackson2JsonRedisSerializer.setObjectMapper(om);
        final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(objectJackson2JsonRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(objectJackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

配置

spring.redis.host=192.168.1.10
spring.redis.port=6379
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

在这里插入图片描述

4 高阶

4.1 配置文件

对大小写不敏感

在这里插入图片描述

包含了别的文件

在这里插入图片描述

网络

bind 127.0.0.1  #绑定的ip
protected-mode no   #保护模式
port 6379 #端口

通用配置

daemonize yes #以守护进程的方式运行
pidfile /var/run/redis_6379.pid #如果以后台的方式运行,我们需要制定一个指定的pid文件
#日志级别
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
#生成的日志文件名
logfile ""
#默认的数据库数量
databases 16
#是否显示logo
always-show-logo yes

SNAPSHOTTING
在规定的时间内,执行了多少次操作,会持久化到文件.rdb .aof
redis是内存数据库,需要持久化,断电及失

#   save ""
# 900秒内,如果至少有一个key进行了修改,我们就进行持久化操作
save 900 1
# 300秒内,超过10个key进行修改,持久化
save 300 10
# 60秒内,超过10000个key进行修改,持久化
save 60 10000
#持久化出错,继续工作
stop-writes-on-bgsave-error yes
#是否压缩rdb文件,需要消耗一些cpu资源
rdbcompression yes
# 保存rdb文件时,检查是否会出错
rdbchecksum yes
#rdb文件保存的目录
dir ./

REPLICATION
赋值

SECURITY

requirepass foobared #设置密码

在这里插入图片描述

限制 CLIENTS

maxclients 10000 #最大的客户端
maxmemory <bytes> #最大的内存容量
maxmemory-policy noeviction # 内存满的应对策略

在这里插入图片描述

APPEND ONLY MODE
aof 基本配置

appendonly no #默认不开启aof模式,默认使用rdb持久化方式,大部分情况下,rdb完全够用
appendfilename "appendonly.aof" #持久化的aof文件的名字
# appendfsync always #每次修改执行一次,效率较慢
appendfsync everysec # 每秒执行一次
# appendfsync no #不同步,os自己同步

4.2 Redis持久化

面试和工作,持久化都是重点

4.2.1 RDB

Redis DataBase
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
保存的是dump.rdb

dbfilename dump.rdb

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在生产环境将rdb备份一下

4.2.2 AOF

Append Only File
将我们的所有命令都记录下来,恢复的时候就把这个全部在执行一遍
在这里插入图片描述
在这里插入图片描述

如果配置文件出现错误,使用以下两个工具修复配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2.3 扩展

在这里插入图片描述
在这里插入图片描述

4.3 Redis发布订阅

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

127.0.0.1:6379> SUBSCRIBE zy
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "zy"
3) (integer) 1
1) "message"
2) "zy"
3) "hello"
127.0.0.1:6379> PUBLISH zy "hello"
(integer) 1

4.4 主从复制

在这里插入图片描述
主从复制,读写分离。最低配:一主二从
在这里插入图片描述
在这里插入图片描述
环境配置
只配置从库,不配置主库

127.0.0.1:6379> info replication
# Replication
role:master #角色 master
connected_slaves:0 #没有从机
master_replid:483e9226224ae70d7bbf5599dd02b8f47ccc1d18
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服务器都是主节点。
在这里插入图片描述
在这里插入图片描述
主机负责写,从机负责读!主机中所有的数据会自动被从机保存!
如果主机宕机后重新连接,从机依旧可以获得主机的数据。
如果没有配置到配置文件,每次启动会默认自己为主机。主要变为从机,立马从主机获取值。
在这里插入图片描述
手动修改
在这里插入图片描述
是自己变成主机,其它的节点可以手动连接到此节点。
在这里插入图片描述

4.5 哨兵模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.6 Redis缓存穿透和雪崩

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5 视频链接

blibli:狂神说Java
链接:https://www.bilibili.com/video/BV1S54y1R7SB?p=1

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值