1》什么是redis:

redis是一个开源的,支持网络交互的,可基于内存也可以持久化的key-value的数据库。
redis官网是redis.io

2》安装redis:

从redis.io下载最新版redis-X.Y.Z.tar.gz后解压,然后进入redis-X.Y.Z文件夹后直接make即可,安装非常简单。
make成功后会在src文件夹下产生一些二进制可执行文件,包括redis-server、redis-cli等等:

  1. $ find . -type f -executable
  2. ./redis-benchmark //用于进行redis性能测试的工具
  3. ./redis-check-dump //用于修复出问题的dump.rdb文件
  4. ./redis-cli //redis的客户端
  5. ./redis-server //redis的服务端
  6. ./redis-check-aof //用于修复出问题的AOF文件
  7. ./redis-sentinel //用于集群管理

3》redis的使用:

3.1 启动redis:

1) redis-server /usr/root/bin/redis.conf 启动服务端的命令,但是需要保持当前窗口状态。 打开新的窗口,使用clone session方法。
2) redis-cli -p 6379 启动客户端的命令,需要通过参数-p 指定端口号 输入ping 会返回pong 代表连接ok
3) set key1 “hello world” 设置key1的值为“hello world” 返回ok。
4) get key1 返回“hello world” ,说明数据可以正常的存取。
5) exit 退出当前的连接
6) shutdown 关闭当前的服务 然后再执行一次exit完全退出
7) redis-benchmark 压测命令 测试在不同命令下 10w次请求在多长时间内完成 官方标准是达到10w/s 的get/set

3.2 redis 数据库命令:

1) keys * 查看当前数据库所有的key值
系统会设置3个默认key额外使用
2) keys ? 匹配方式的使用 对于存在key1 key2 key3形式的key时 keys key? 可以找到 keys k??? 也可以找到 说明?是一个匹配符,并且有占位的作用
3) select 1 切换到1号数据库 get key1 返回nil,空的意思 通过127.0.0.1:6379[?]后面的括号中的值,可以判断当前所在的数据库编号
4) dbsize 展示数据库中key的个数
5) flushdb 删除当前数据库的数据 “慎用!”
6) flushall 删除所有数据库的数据 要怎么用 看着办
image.png

3.3 redis键值操作命令:

1)exists + key 判断键值是否存在
2)type + key 显示当前键值存储的数据类型
3)expire + key + n 设置可以值得有效时间为n秒,过了有效期,此key的值置为空
pexpire + key +n 有效时间单位为毫秒
4)ttl + key 查看还剩多长时间有效,正数代表未过期的剩余时间,单位为秒。
pttl + key 返回剩余时间为毫秒
负数情况下:
当返回为-2时,说明key不存在
当返回为-1时,说明没有设置时间
5) persist + key 设置数据一直有效,特别作用于错误设置了有效期之后。
6)del + key 删除一个key
7)rename + key + newKey 可以重命名key的值
8)randomkey 随机出一个key
9) move key + dbID 移动指定key到另一个数据库中,dbID是数据库编号 eg: move key5 1
image.png

4》Redis的数据类型:

4.1 String 字符串类型:

1) set key1 “hello world” 设置key1的值为“hello world” 返回ok。

2) get key1 返回“hello world” ,说明数据可以正常的存取。

3)strlen 查看字符串的长度
4)append 增加后缀,返回字符串的长度
eg: append key1 “222” -> “hello111222”
eg: set key1 “hello111222”

5) 当value的值是整数时,可以通过命令直接进行数学运算
incr 自增 ,返回最新的值。
decr 自减, 也返回最新的值。
incrby 增加,区别是增加计算的参数
如:incrby key11 3。 decrby 减少,同上。
6) 范围内操作的命令 getrange key start end 获取从初始位置到结束位置的值,从0计数 ==》 类似subString setrange key start newStr 设置从起始位置开始,替换指定位置为新的字符串
eg : “hello111222” -> setrange key1 5 333 -> “hello333222”

7)整合命令
setex = set + expire
使用方式: setex + key + 时间 + value
setnx = set + exists = set if not exists
使用方式: setnx + key + value 如果key不存在,则设置数据,返回1。如果存在,不设置,返回0。
getset 先取出原来的值,再设置为新值
使用方式: getset + key + value 返回旧值。
8) 批量操作
mget = more get
使用方式 : mget + key1 + key2 + key3 参数接收多个key, 结果返回多个value
mset = more set 使用方式:mset + key1 + value1 + key2 + value2 一次设置多个key和value, 参数本身是个map msetnx 使用方式同上。
image.png

2 原理:

redis的字符串是动态字符串,内部结构类似ArrayList采用预分配冗余空间的方式减少内存的频繁分配。内部为字符串分配的实际空间一般高于字符串长度,当字符串长度<1MB时,扩容方式是直接加倍如果>1MB,一次扩容只扩1MB,直到扩大到512MB。

4.2 list(列表):

PS:redis中的lists在底层实现的并不是数组,而是链表优势是在头部和尾部的插入新的元素,复杂度是常数级别,速度快,弊端是链表型lists定位速度比较慢

4.2.1 存取操作 push pop range:

1) lpush : 从左侧存入数据 —》 栈结构
2) lpop (从左侧弹出)
3)rpush: 从右侧存入数据 —》 队列结构
4)lpop (从左侧弹出)
5)lrange: 范围内查看数据 使用方式:lrange key start end

image.png

4.2.2 对list本身的操作 :

1) llen 查看长度 lindex 获取某一个位置的值,下角标从0开始
2) lrem 删除n个value的值
使用方式: lrem key N value
3)ltrim 截取某个范围的数据重新赋值给key
使用方式: ltrim key start end (下角标从0开始)
4)linsert 插入数据到某个位置的前后
使用方式: linsert key before/after oldValue newValue
如果要插入数据到头部,还可以使用 lpushx
使用方式:lpushx key value 同理,如果要插入数据到尾部,可以使用 rpushx, 使用方式同上。
5)lset 可以更改指定位置的值 使用方式: lset key index value

4.2.3 lists的应用相当广泛,例子:

1.我们可以利用lists来实现一个消息队列,而且可以确保先后顺序,不像MySQL那样还需要通过ORDER BY来进行排序。
2.利用LRANGE还可以很方便的实现分页的功能。
3.在博客系统中,每片博文的评论也可以存入一个单独的list中。

4.3 Hash (哈希):

HashMap ==》 string
HashMap ==》 List
HashMap ==》 Hash
HashMap> ==》 Set
HashMap> ==》 ZSet

4.3.1 Hash命令:

4.3.1.1 存取数据:

1)hset
使用方式:hset hashname key1 value1
2)hget:
使用方式:hget hash1 key1 => “value1”
3) hsetnx :
如果不存在即set新的key值
使用方式:hsetnx hashname key1 value1
4)hmset/hmget :
批量处理更便捷
使用方式:hmset hashname key1 value1 key2 value2
hmget hashname key1 key2

4.3.1.2 遍历数据:

1)hkeys:查看所有的key值
2)hvals:查看所有的value值
3)hlen :查看数据长度
4)hgetall: 返回全部的key和value
5)hexists :判断是否存在某个key, 存在返回1,不存在返回0

4.3.1.3 变更数据:

1)hdel: 删除数据 ,
使用方式 :hdel hashname key
2)hincrby :对整数的增加操作,指定增加的范围
使用方式: hincrby hashname field_key num

4.4 set(集合):

java的集合中有list/set/map list可以存储有序的重复数据, 而set可以存储无序的不重复数据。

4.4.1 set集合 命令:

4.4.1.1 读写操作:

1)sadd :创建set类型的value,
eg: sadd setName 1 2 3 4 4 3 2 1
2)scard keyName :查看set的大小
eg:scard setName
3)smembers keyName: 查询set中的所有值
eg:smembers keyName
4)sismember keyName value: 判断value是否在key所对应的set中, 如果在返回1,如果不在返回0
eg:sismember keyName value

4.4.1.2 更新操作:

1)srem keyName value1 value2: 删除set中一至多个数据的值
2)srandmember keyName num :可以在set中随机出num个元素
3)spop keyName num :可以随机弹出num个元素返回

4.4.1.3 交互操作:

1) smove keyName1 keyName2 value: 移动元素value从key1到key2
image.png

4.4.1.4 并集、交集和差集:

  1. 1)**sinter keyName1 keyName2 :**代表求两个集合的交集(两者都有的元素)。 <br /> 2)**sdiff keyName1 keyName2 :**返回存在在key1中但不存在在key2中的元素,两者的差集 <br /> 3 **sunion keyName1 keyName2:** 返回并集(两个集合中的所有元素)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/13022516/1636685670144-c7c44c6b-38b7-4097-8ff0-68716189579a.png#clientId=uf96f4c57-93ec-4&from=paste&height=893&id=uff7734f8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=893&originWidth=1142&originalType=binary&ratio=1&size=57433&status=done&style=none&taskId=u8879f9fd-d5e7-43dc-a247-da11603d63f&width=1142)

4.5 ZSet (有序集合):

4.5.1 命令:

4.5.1.1 读取操作:

1)zadd :创建或增加zset的元素值,每一个元素值都包含 <分数,value>
使用方式: zadd keyName score1 value1 score2 value2 …
2)zrange keyName start end :指定在start到end的范围内查看元素 如果要查看分数 ,加上withscores
3)zrangebyscore keyName minScore maxScore :指定分数范围内查询 元素 参数说明 分数前增加“(” 代表开区间(不包含当前值) 支持limit分页 limit + offset(偏移量) + num(返回的数量)
4)zrem keyName + value: 删除指定的value值
image.png

4.5.1.2 统计操作:

1)zcard + keyName: 统计元素个数
2)zcount + keyName + minScore + maxScore:统计给定分数范围内的元素个数 比如统计及格人数等需求。
3)zscore + keyName + member :查询指定成员的分数
4)zrank + keyName + member :返回指定成员的索引位置(因为有序,所以位置代表排名)
5)zrevrank + keyName + member: 默认从低到高排序,逆序正好代表排名
6)zrevrange + keyName: 原来是从小到大排列,逆序后从大到小排列
image.png

4.6 Geo (位置信息):

4.6.1 命令:

1) geoadd + key + 经度 + 维度 + 成员名 : 通过经纬度存储地址,支持存储多个

2) geodist + key + member1 + member2 + 距离单位 :查询两个地点之间的相对距离 距离单位支持:m(米)、km(千米)、mi(英里)、ft(英尺)
3)geopos :查询成员经纬度数据
4)geohash :进行哈希编码 ,得到编码结果
image.png
5)georadius :以某个经纬度的位置为中心,划一个指定距离的半径,返回集合中满足条件的地址。 这就是“附近的XXX”的一种实现方式。 使用方式: georadius + key + 中心的经度 + 中心的纬度 + 半径的距离 + 半径的单位 可选参数: withdist 返回距离; withcoord 返回经纬度 ; withhash 返回哈希编码;
image.png

5》Redis配置:

image.png

5.1 linux命令:

1) cd: 更改目录
cd ~ 回到初始目录
cd .. 回到上级目录
2) mkdir 创建目录 eg: mkdir myredis
3) cp 拷贝文件 eg: cp redis-5.0.6/redis.conf myredis/
4) ll 查看目录内的文件
5) vim 文本编辑器 两种模式: 命令模式 、 编辑模式 打开文件时,默认是命令模式,可以查看文件的内容。
输入i(insert),可以切换为编辑模式,此时才可以更改文件。
按ESC,可以从编辑模式再切换为命令模式 (此时才可以退出)。
退出方式
输入 : q (如果文件被修改,会提醒未保存) 不保存,
输入 : q! 保存,
输入 : wq

5.2 redis.conf配置文件:

1) 单位的问题: 1k / 1kb / 1m / 1mb / 1g / 1gb 是不同的,没有b的时候取整。 单位的大小写是不敏感的 1GB=1gB=1Gb

网络相关:

2) bind 127.0.0.1 绑定ip地址(能够访问服务端的地址) 当前的redis服务只能被本机访问
3) protect-mode yes 开启保护模式 当bind没有配置且登录不需要密码时,启动保护模式(只能被本地访问)
4) port 6379 端口号
5) timeout 0 客户端超时时间 ,0代表一直保持
6) tcp-keepalive 300 单位是秒,每300s去检查一次客户端是否健康,避免服务端阻塞。
7) tcp-backlog 511 队列数量(未完成握手和已完成握手的)

通用相关:

8) daemonize no 后台运行开关 改为yes后,重启redis验证。 redis启动指定配置文件的方式为: redis-server /root/myredis/redis.conf
9) pidfile /var/run/redis_6379.pid 当守护进程开启时,写入进程id的文件地址
10) loglevel notice 四种级别,notice对应生产环境
11) logfile “” 日志存储的位置
12) databases 16 初始化数据库是16个

5.3 安全和限制

config命令是一种从客户端查看配置项信息的方式,使用config get属于危险命令,可以限制使用。
安全校验配置 requirepass 代表是否设置密码 如果需要
设置密码 config set requirepass + 此时输入命令前,需要先
校验 anth + 然后才能执行其他操作 恢复初始状态,只需要重新设置为空串
image.png

5.4 危险命令限制 :

包含 config / flushdb / flushall / keys
rename-command + 命令 + “” 将此命令置为不可用

5.5 其他限制 :

maxclients 10000 客户端并发数的限制
maxmemory 最大内存
maxmemory-policy 缓存淘汰策略
默认值 noeviction (不删除只报错)
其他策略主要分为两种情况
allkeys(所有的键值都可能删除)
volatile(只删除设置了过期时间的键值)

image.png
image.png

6》 Redi s缓存淘汰策略 :

六种策略:

1) noeviction:

不删除策略, 达到最大内存限制时, 如果需要更多内存, 直接返回错误信息。 大多数写 命令都会导致占用更多的内存(有极少数会例外, 如 DEL )。

2) allkeys -lru:

所有key通用; 优先删除最近最少使用(less recently used ,LRU) 的 key。

3)volatile-lru:

优先删除最近最少使用(less recently used ,LRU) 的 key(限于会过期的key)。

4)allkeys -random:

所有key通用; 随机删除一部分 key。

5)volatile-random:

随机删除一部分 key(限于会过期的key)。

6)volatile-ttl:

优先删除剩余时间(time to live,TTL) 短的key(限于会过期的key)。 ps:Redi s缓存淘汰策略 如果分为热数据与冷数据, 推荐使用 allkeys-lru 策略
image.png

7》Redis持久化(RDB&AOF):

7.1 什么是持久化:

持久化——将数据(如内存中的对象)保存到可永久保存的存储设备中

7.2 持久化的两种方式:

7.2.1 RDB持久化:

含义: 在指定的时间间隔内对数据进行快照存储。先将数据集写入临时文件,写入成功后, 再替换之前的文件,用二进制压缩存储,是一次的全量备份。

7.2.1.1 命令触发:

  1. save,会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
    2. bgsave,该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork 子进程的时候

    7.2.1.2 自动触发:

  2. 根据我们的 save m n 配置规则自动触发;
    2. 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave;
    3. 执行 debug reload 时;
    4. 执行 shutdown时,如果没有开启aof,也会触发

    7.2.1.3 恢复方式:

    将备份文件(dump.rdb)移动到redis安装目录并启动服务即可
    image.png

    image.png

    7.2.1.4 RDB性能分析(优缺点):

    优点:
    1)通过rdb文件恢复数据比较快。
    2) rdb文件非常紧凑,适合于数据备份。
    3)通过RDB进行数据备份,由于使用 子进程生成,所以对Redis服务器性 能影响较小 。
    缺点:
    1)采用RDB的方式可能会造成某个时段内数据的丢失,比如还没达到 触发条件时服务器死机了,那么这个时间段的数据会丢失。
    2)使用save命令会造成服务器阻塞,直接数据同步完成才能接收后 续请求。
    3)使用bgsave命令在forks子进程时,如果数据量太大,forks的过 程也会发生阻塞,另外,forks子进程会耗费内存。

7.2.2 AOF 持久化:

含义: 以日志文本的形式记录服务器所处理的每一个数据更改指令,然后通过重放来恢复 数据,是连续的增量备份 。
image.png
image.png

image.png
image.png

8》Jedis的使用:

8.1 修改redis.conf配置文件:

首先需要在redis.conf配置文件中修改配置。需要重启Redis服务才可以生效:
bind 192.168.31.329 =>绑定本机Linux的IP地址
image.png

8.2 绑定主机地址:

修改之后,必须指定绑定的主机地址方可使用Redis
redis-cli -h 192.168.31.329 -p 6379 =>启动时指定绑定的主机地址
image.png

8.3 开放6379端口:

firewall-cmd —permanent —add-port=6379/tcp
firewall-cmd —reload
firewall-cmd —query-port=6379/tcp
image.png

8.4 创建java项目并导入jar包:

image.png

8.5 创建redis.properties配置文件:

  1. #最大连接数
  2. redis.maxTotal=50
  3. #默认开启的活跃连接数
  4. redis.maxIdel=10
  5. #Linux的ip地址
  6. redis.host=192.168.200.130
  7. #redis的端口号
  8. redis.port=6379

8.6 创建Jedis的工具类 JedisUtils:

  1. public class JedisUtils {
  2. // 将从配置文件读取的配置信息赋予如下变量
  3. private static int maxTotal;
  4. private static int maxIdel;
  5. private static String host;
  6. private static int port; // 端口号为int类型
  7. // Jedis的连接池配置
  8. private static JedisPoolConfig jedisPoolConfig;
  9. // Jedis连接池
  10. private static JedisPool jedisPool;
  11. static {
  12. // 读取redis.properties配置文件
  13. ResourceBundle bundle = ResourceBundle.getBundle("redis");
  14. maxTotal = Integer.parseInt(bundle.getString("redis.maxTotal"));
  15. maxIdel = Integer.parseInt(bundle.getString("redis.maxIdel"));
  16. host = bundle.getString("redis.host");
  17. port = Integer.parseInt(bundle.getString("redis.port"));
  18. // Jedis连接池配置
  19. jedisPoolConfig = new JedisPoolConfig();
  20. jedisPoolConfig.setMaxTotal(maxTotal);
  21. jedisPoolConfig.setMaxIdle(maxIdel);
  22. jedisPool = new JedisPool(jedisPoolConfig, host, port);
  23. }
  24. public static Jedis getJedis() {
  25. return jedisPool.getResource();
  26. }
  27. }

8.7 测试:

  1. public class JedisTest {
  2. public static void main(String[] args) {
  3. // 1. 获取Jedis对象
  4. Jedis jedis = JedisUtils.getJedis();
  5. // 2. 执行操作,Jedis中操作的方法名与Linux中命令行工具中的指令同名
  6. jedis.sadd("key1", "abc", "abc", "def");
  7. Long key1 = jedis.scard("key1");
  8. System.out.println("运行结果:" + key1);
  9. // 3.关闭连接
  10. jedis.close();
  11. }
  12. }

9》Redis主从复制:

9.1 主从复制的概念:

1)为了避免单点Redis服务器故障,准备多台服务器,互相连通。将数据复制多个副本保存在不同的服务器上,连接在一起,并保证数据是同步的;即使有其中一台服务器宕机,其他服务器依然继续提供服务,实现redis高可用,同事实现数据的备份。
2)多台服务器的连接方案:
image.png
3)主从复制即将master中的数据即时、有效的复制到slave中

4)一个master可以拥有多个slave,一个slave只对应一个master

5)master和slave各自的职责不一样

6)master:写数据、执行写操作时,将出现变化的数据自动同步到slave
7)slave:读数据

9.2 主从复制的作用:

(1) 读写分离:master写、slave读,提高服务器的读写负载能力

(2) 负载均衡:slave分担master负载,并根据需求的变化,可改变slave的数量,大大提高Redis服务器并发量与数据吞吐量

(3) 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复

(4) 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式

(5) 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案

9.2 主从复制的流程:

image.png
指令有四种发送方式:
image.png

9.2.1 建立连接(slave主动连接master):

9.2.1.1 建立slave到master的连接:

  • 建立slave到master的连接,使master能够识别slave,并保存slave端口号。

S