Redis


一、Redis入门

1.1 redis介绍

  1. -- 1. redis是什么?
  2. remote dictionary server 远程字典服务器,是一种'基于内存'的数据结构存储系统,所以对于内存要求很高。
  3. 字典:就是map
  4. 使用c语言写的,非常轻巧。
  5. -- 2. 能用来干什么?
  6. 1. 作为数据库
  7. 2. 作为缓存
  8. 3. 作为消息的中间件,kafka也是消息中间件
  9. 我们主要是用来做缓存,客户端访问数据时,不用直接访问mysql数据,而是访问redis,提高响应的速度,同时缓解mysql的压力。
  10. -- 3. 数据结构说明:
  11. 1. 是一个kv键值对的数据结构,nosql
  12. 2. k固定为string类型,v的类型有很多,我们主要学习如下5大数据类型
  13. 1. 字符串
  14. 2. list:有序可重复
  15. 3. set:无序不重复,可用来对value进行去重,'作用非常大'
  16. 4. hash:类型map<string,string>
  17. 5. sorted set = zset ,带分数的set,排序后的set
  18. 3. v不支持嵌套,所以listsetmap中的数据都是string
  19. -- 4. 典型场景
  20. 1.缓存:使用Redis可以建立性能非常出色的缓存服务器,查询请求先在Redis中查找所需要的数据,如果能够查询到(命中)则直接返回,大大减轻关系型数据库的压力。
  21. 2.数据临时存储位置:使用token(令牌)作为用户登录系统时的身份标识,这个token就可以在Redis中临时存储。
  22. 3.流式数据去重:在Redis中有一种数据类型是"set",和Java中的Set集合很像,不允许存储重复数据。借助这个特性我们可以在Redis中使用set类型存储流式数据达到去重的目的(重点)。
  23. -- 5. 不适合场景
  24. 1.直接查询valueRedis是一个严格的Key-value数据库,所有数据都必须通过key去找到valueRedis没有提供直接根据查询条件匹配value的方法。
  25. 2.用多键一值表示特定关系:Redis中一个key对应一个value,没有多个key对应同一个value的情况。
  26. 3.事务中回滚:Redis不支持回滚。如果一个命令在加入队列时没有检测出问题,那么队列执行时不会因为某一条命令失败而回滚。

1.2 安装

说明:安装和启动redis均使用root用户

  1. 第一步: redis-3.2.5.tar.gz 上传到 opt/sofeware
  2. 第二步: 解压到opt/module
  • 第三步: 安装gcc环境:我们需要将源码编译后再安装,因此需要安装c语言的编译环境!不能直接make!
  1. yum install y gcc-c++
  • 第四步:查看安装是否成功
  1. rpm qa|grep gcc
  1. -- 此时安装的常见错误
  2. 错误1 在没有安装gcc环境下,如果执行了make,不会成功!安装环境后,第二次make有可能报错
  3. 'Jemalloc/jemalloc.h:没有那个文件'
  4. 解决方案:运行 make distclean之后再make
  • 第五步:编译,执行make命令,安装gcc
  • 第六步:编译完成后,安装,执行make install命令!

1.3 启动

1.3.1 启动服务端

  1. 设置后台启动,修改/opt/module/redis-3.2.5/redis.conf文件
  1. [atguigu@hadoop105 redis-3.2.5]$ vim redis.conf
  2. 修改:daemonize no 给为 daemonize yes

redis - 图1

  1. 启动redis服务端
  1. [root@hadoop105 redis-3.2.5]# redis-server redis.conf
  1. 查询服务端是否开启
  1. [root@hadoop105 redis-3.2.5]# netstat -nap |grep 6379
  1. 关闭服务端
  1. redis的客户端中,使用shutdown,关闭服务器。
  1. redis服务端的端口号为:6379

redis - 图2

1.3.2 客户端登入

  1. -- 1. 客户端说明:
  2. 1. 由于rediskv的数据存储结构,那么k是不能重复的,所以redis默认有16个数据库,以便可以存储相同的k
  3. 2. 数据库的dbid0-15,默认情况下是使用0号数据库。
  1. --2. 连接客户端:
  2. '方式1'redis-cli :此时默认是使用本机的hostlocal用户登入redis
  3. '方式2': redis-cli -h hadoop102 -p 6379 --hadoop102也可以使用具体的ip地址
  4. 说明:默认情况下仅支持通过localhost的方式登录,如果想要其他的网卡也能登入,
  5. 需要修改如下/opt/module/redis-3.2.5/redis.conf文件:
  6. blind 127.0.0.1 改为 0.0.0.0 ,则支持所有的网卡连接。
  7. -- 3. 退出客户端:
  8. 'exit'
  9. -- 4. 进入客户端以后测试是否连通:
  10. 'ping'

二、redis基本操作

2.1 基本操作

通过前缀或者后缀判断技巧:

NX:not exist 判断是否存在
EX:expire 设置过期时间
M:mult 多个

  1. -- 1. 切换数据库(默认有16个)
  2. 1. select + dbid
  3. 默认是0号数据库
  4. -- 2. 清空数据库
  5. 1. flushdb:清空当前数据库
  6. 2. flushall:清空所有数据库
  7. -- 3. 查看当前数据的数据个数
  8. 1. dbsize

2.2 key操作

redis所有的数据都是存储在内存中

  1. -- 1. 获取当前数据库key
  2. 1. keys * --> 获取所有的key
  3. 2. keys k* --> 获取以k开头的所有的key
  4. 3. keys ? --> 单个匹配
  5. -- 2. 判断key是否存在
  6. 1. exists key --> 如果存在返回1,不存在返回0
  7. -- 3. 判断keyvalue的数据类型
  8. 1. type key
  9. -- 4. 删除key
  10. 1. del key
  11. -- 5. 获取指定keyvalue
  12. 1. get key --> 只使用于value的类型为string
  13. -- 6. 获取一个随机的key
  14. 1. randomkey
  15. -- 7. 设置kv键的过期时间
  16. 1. expire key time --> 单位为s,过了指定的时间以后,该数据就过期了,不再存在
  17. 2. ttl key --> 查看该key还能存活的时长:
  18. 如果返回-1,说明永久有效
  19. 如果返回-2,说明已过期
  20. 如果返回其他正数,说明还能存活的时长。
  21. 3.PERSIST KEY -->移除过期时间,变成永久key
  22. -- 8. 重命名key
  23. 1. rename oldkey newkey :直接改,如果newkey存在,直接覆盖。
  24. 2. renamenx oldkey newkey : 如果newkey已经存在,则不会做任何操作

2.3 value的五大常用类型(重点)

key value
String 字符串
list 可以重复的集合
set 不可以重复的集合
hash 类似于Map
zset(sorted set) 带分数的set

2.3.1 String

  1. -- 1. 说明
  2. 1. String类型是Redis中最基本的类型,它是key对应的一个单一值
  3. 2. redisstring可以包含任何数据,比如jpg图片或者序列化的对象(二进制安全binary safe
  4. 3. Redis中一个字符串值的最大容量是512M
  • 具体的操作
  1. -- 1. 添加数据
  2. 1. set key value
  3. 2. setnx key value --> 如果key存在,则添加失败
  4. 3. setex key time value --> 添加数据的同时设置过期时间,单位是s(推荐使用)
  5. 4. setrange key startindex endindex --> 在原有的value进行修改
  6. -- 2. 批量添加数据
  7. 1. mset key1 value1 key2 value2 ...
  8. 2. msetnx key1 value1 key2 value2 ... --> 只要有一个key之前已经存在,则添加失败
  9. -- 3. 获取数据
  10. 1. get key
  11. 2. mget key1 key2 key3 ..
  12. -- 4. 在原有的value基础上进行追加数据
  13. 1. append key value
  14. -- 5. 获取value的字符长度
  15. 1. strlen key
  16. -- 6. 获取vlaue指定字符索引的数据
  17. 1. getrange key startindex endinx --> 左闭右闭
  18. 例如:getrange key 0 -1 -->全部 类似于between...and
  19. -- 7. 获取后重置value
  20. 1. getset key newvalue --> 先获取指定keyvalue后,再将原来的value使用newvalue进行替换
  21. -- 8. ++ --
  22. 1. incr key --> key对应的value自增1,要求value具体的值为"数值类型"
  23. 2. decr key --> 自减1
  24. -- 9. 按步长增、减
  25. 1. incrby key num --> key对应的value + num
  26. 2. decrby key num --> key对应的value - num

2.3.2 list(列表)

  1. -- 1. list结构说明
  2. 1. '在Java中'list 一般是单向链表,如常见的Arraylist,只能从一侧插入。
  3. 2. '在Redis中'list是双向链表。可以从两侧插入
  4. -- 2. 常见操作
  5. 1. 遍历: 从左往右取值
  6. 2. 删除: 弹栈 pop lpop rpop
  7. 3. 添加: 压栈 push lpushrpush
  8. 注意:区别压栈和队列
  9. -- 说明:
  10. l:从左边
  11. r:从右边
  • 具体的操作
  1. -- 1. 添加数据
  2. 1. lpush key value --> 从左边加数据
  3. 2. lpush key value1 value2 ...
  4. --> 从左边开始,添加多个数据,但是先添加value1,再添加value2,所以value2value1的左边。
  5. 3. rpush key value --> 从右边加数据
  6. 4. lrange list 0 -1 -->全部取出
  7. -- 2. 遍历数据
  8. '说明':在redislist中的数据有序的,所以有索引,但是索引角标的方式有两种
  9. '案例' list中的数据: "b" "c" "b"
  10. 正数角标: 0 1 2
  11. 负数角标: -3 -2 -1
  12. 如上正数角标和负数角标的索引值均可以获取到list集合中数据。
  13. 1. lindex key 角标 --> 从左边开始数,获取指定角标的数据,如果是负数,那么获取倒数第几个数据
  14. 如:lindex list 2 --> 从左往右看,获取第三个数据
  15. lindex list -1 --> 从左往右看,获取倒数第一个数据
  16. 2. lrange key 0 -1 --> 获取所有的数据,左闭右闭
  17. -- 3. 删除数据
  18. 1. lpop key --> 从左往右看,删除第一个数据 (弹出=返回+删除)
  19. -- 4. 获取key对应valuelist集合的长度
  20. 1. llen key
  21. -- 5. 在某个value的前面或者后面插入数据
  22. 1. linsert key before/after value newvalue --> 如果value值不存在,则插入数据失败
  23. -- 6. 删除多个value
  24. 1. LREM key count value --> 删除countvalue
  25. -- 7. 删除首尾的数据
  26. 1. LTRIM key start stop --> 保留[startnum ,endnum ]数据 ,两边的数据被删除
  27. -- 8. 删除list1最后一个数据插入到list2集合中的第一个位置
  28. 1. rpoplpush list1 list2

2.3.3 set(集合)

  1. -- 1. set:无序不可重复
  2. -- 2. 基本操作如下:
  1. -- 1. 添加数据
  2. 1. sadd key [member...]
  3. -- 2. 获取set中所有数据
  4. 1. SMEMBERS key --> 获取当前key中的所有value
  5. -- 3. 删除数据
  6. 1. spop key --> 删除一个数据
  7. 2. spop key count --> 删除多个
  8. -- 4. 判断数据是否存在
  9. 1. SISMEMBER key member
  10. -- 5. 获取随机的值
  11. 1. srandmember key count --> 随机获取key中的countvalue
  12. -- 6. 求两个set的交集
  13. 1. sinter key1 key2 ... --> 求多个keyvalue的交集
  14. 2. sinterstore destination key1 key2 ... --> 求多个keyvalue的交集并存放到destination中的value
  15. -- 7. 求两个set的差集
  16. 1. sdiff key1 key2 --> 求两个keyvalue的差集
  17. 2. sdiffstore destination key1 key2 ... --> 求多个keyvalue的差集并存放到destination中的value,注意前后顺序
  18. -- 8. 求两个set的并集
  19. 1. sunion key1 key2 --> 求两个keyvalue的交集
  20. 2. sunionstore destination key1 key2 ... --> 求多个keyvalue的交集并存放到destination中的value
  21. -- 9. 查看set中元素的个数
  22. 1. scard key

2.3.4 hash(哈希,类似java里的Map 绝对重点)

  1. -- 1. hash数据的结构为:map<string,string>
  2. key <key,value>,<key,value> --> key <field,value> , <field,value>....
  3. -- 2. 具体的操作:
  1. -- 1. 添加数据
  2. 1. hset key field value -->添加一个元素
  3. 2. hmset key field value [field value ...] -->添加多个元素
  4. 3. hsetnx key field value --> 如果field存在,则不添加
  5. -- 2. 获取元素
  6. 1. hget key field --> 获取key中的指定fieldvalue
  7. 2. hmget key field1 field2 ... --> 获取key中的多个fieldvalue
  8. 3. hgetall key --> 获取所有的hash
  9. 4. hkeys key --> 获取所有的field
  10. 5. hvals key --> 获取所有的value
  11. -- 3. 删除keyfield
  12. 1. hdel key field --> 删除key中的指定field
  13. -- 4. keyfieldvalue增加值
  14. 1. hincrby key field number --> key中的fieldvalue增加number
  15. -- 5. 获取hash键值对的数量
  16. 1. hlen key
  17. -- 6. 判定keyfield是否存在
  18. 1. hexists key field [field ...]

2.3.5 zset(有序的集合)

  1. -- 1. zset是什么?
  2. 1. 是一种特殊的setsorted set),在保存value的时候,为每个value多保存了一个score(分数)信息。根据score信息,可以进行排序。
  3. 2. 默认按照分数的从低到高进行排序。
  4. 3. 集合的成员是唯一的,但是评分可以重复
  5. -- 2. 结构
  6. key set<string,score>
  7. -- 3. 基本操作
  1. -- 1. 添加数据
  2. 1. ZADD key [score member ...]
  3. -- 2. 在分数的指定区间内返回数据,从小到大排列
  4. 1. ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
  5. -- 3. 在分数的指定区间内返回数据,从大到小排列
  6. 1. ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
  7. -- 4. 返回指定值的分数
  8. 1. ZSCORE key member
  9. -- 5. 统计分数区间内的元素个数
  10. 1. ZRANGE key start stop [WITHSCORES]
  11. -- 6. 返回集合中所有的元素的数量
  12. 1. ZCARD key
  13. -- 7. 统计分数区间内的元素个数
  14. 1. ZCOUNT key min max
  15. -- 8. 删除该集合下,指定值的元素
  16. 1. ZREM key member
  17. -- 9. 返回该值在集合中的排名,从0开始
  18. 1.ZRANK key member
  19. -- 10. 为元素的score加上增量
  20. 1. ZINCRBY key increment member

三 、 Redis的配置说明

3.1 单位说明

3.2 include

  1. -- 1. 说明:
  2. 可以将公共的配置放入到一个公共的配置文件中,然后通过子配置文件引入父配置文件中的内容!将配置按照模块分开!

3.3 network

  1. -- 1. 属性 bind
  2. '含义' :限定访问的主机地址
  3. '备注' :如果没有bind,就是任意ip地址都可以访问。生产环境下,需要写自己应用服务器的ip地址。
  4. -- 2. 属性 protected-mode
  5. '含义' :安全防护模式
  6. '备注' :如果没有指定bind指令,也没有配置密码,那么保护模式就开启,只允许本机访问。
  7. -- 3. 属性 port
  8. '含义' :端口号
  9. '备注' :默认是6379
  10. -- 4. 属性 tcp-backlog
  11. '含义' :网络连接过程中,某种状态的队列的长度
  12. '备注' redis是单线程的,指定高并发时访问时排队的长度。超过后,就呈现阻塞状态。
  13. 可以理解是一个请求到达后至到接受进程处理前的队列长度。(一般情况下是运维根据集群性能调控)高并发情况下,
  14. 此值可以适当调高。
  15. -- 5. 属性 timeout
  16. '含义' :客户端连接以后长时间没有操作,那么就关闭连接,这个超时时间就是指客户端多长时间没有操作
  17. '备注' :默认永不超时
  18. -- 6. 属性 tcp-keepalive
  19. '含义' :对客户端的心跳检测间隔时间

3.4 general

  1. -- 1. 属性 daemonize
  2. '含义' :是否为守护进程模式运行,也就是后台运行
  3. '备注' :守护进程模式可以在后台运行
  4. -- 2. 属性 pidfile
  5. '含义' :进程id文件保存的路径
  6. '备注' :配置PID文件路径,当redis作为守护进程运行的时候,它会把 pid 默认写到 /var/redis/run/redis_6379.pid 文件里面
  7. -- 3. 属性 loglevel
  8. '含义' :定义日志级别
  9. '备注' :一共有4种存储级别,根据用途不用选择不同的存储级别
  10. 级别1debug(记录大量日志信息,适用于开发、测试阶段)
  11. 级别2verbose(较多日志信息)
  12. 级别3notice(适量日志信息,使用于生产环境)
  13. 级别4warning(仅有部分重要、关键信息才会被记录)
  14. -- 4. 属性 syslog-enabled
  15. '含义' :是否记录到系统日志
  16. '备注' :要想把日志记录到系统日志服务中,就把它改成 yes
  17. -- 5. 属性 databases
  18. '含义' :设置数据库数量
  19. '备注' :默认16个数据库,数据库的dbid0-15
  20. -- 6. 属性:logfile
  21. '含义' :日志目录
  22. '备注' :前台运行时打印在控制台,后台运行时默认写到黑洞里面。所以我们一般会配置一个路径"/var/logs/redis.log"

3.5 其他

  1. -- 1. 属性 requirepass
  2. '含义' :设置密码
  3. -- 2. 属性 maxclients
  4. '含义' :最大连接数
  5. -- 3. 属性 maxmemory
  6. '含义' :最大占用多少内存
  7. '备注' :一旦占用内存超限,就开始根据缓存清理策略移除数据如果Redis无法根据移除规则来移除内存中的数据,
  8. 或者设置了“不允许移除”,那么Redis则会针对那些需要申请内存的指令返回错误信息,比如SETLPUSH等。
  9. -- 4. 属性 maxmemory-policy noeviction
  10. '含义' :缓存清理策略
  11. 根据使用redis的用途不同,选择不同的清除策略。
  12. 作为数据库时:noeviction,永远不要删除
  13. 作为缓存时:volatile-lru或者allkeys-lru或者volatile-ttl,最好是volatile-ttl
  14. 作为消息的中间件时:
  15. '备注' :一共有6种清除,清除方式如下:
  16. 'LRU算法:最近最少使用的策略'
  17. 1volatile-lru:使用LRU算法移除key,只对设置了过期时间的键
  18. 2allkeys-lru:使用LRU算法移除key
  19. 3volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
  20. 4allkeys-random:移除随机的key
  21. 5volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
  22. 6noeviction:不进行移除。针对写操作时会返回错误信息
  23. -- 5. 属性 maxmemory-samples
  24. '含义' :样本数,默认是5
  25. '备注' :样本数越小,准确率越低,但是性能越好。
  26. LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小。一般设置37的数字。

四、 持久化

  1. -- 1. 持久化介绍
  2. redis的数据是基于内存,一旦出现突然断电,那么数据就会从内存中丢失,所以redis提供了两种数据持久化的方式:rdbaof
  3. -- 2. 两种持久化方法的主要区别:
  4. 1. rdb:按照保存策略每间隔一段时间将redis内存中数据做一个快照,保存到磁盘中,但是前面写完快照以后就会把之前的快照删除,只保留最新的快照数据;
  5. 2. aof: 按照保存策略,将redis的对'数据的操作指令'保存到磁盘中,可以恢复已删除的数据。
  6. -- 3. 两种持久化方法的优劣势待详细分解后归纳总结。

4.1 RDB

4.1.1 RDB介绍

  1. -- 1. RDB是什么?
  2. '持久化方式':在指定的时间间隔内将redis内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,
  3. '恢复数据方式':将快照文件直接读到内存里
  4. -- 2. 工作机制:
  5. 每隔一段时间,就把内存中的数据保存到硬盘上的指定文件中
  6. -- 3. 默认是开启状态
  7. -- 4. 实现方式:
  8. 第一步:Redis会单独创建(fork)一个子进程来进行持久化,
  9. 第二步:先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
  10. '说明'
  11. 1. 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复
  12. 2. 对于数据恢复的完整性不是非常敏感
  13. -- 5. 缺点
  14. 最后一次持久化后的数据可能丢失

4.1.2 RDB的持久化触发条件

  1. -- 1. 触发条件1:自动保存策略,如下三种情况任何一种满足即进行持久化操作
  2. save <seconds> <changes> :在多少秒内数据发生改变以后就会自动保存
  3. '情况1'save 900 1 :900 秒内如果至少有 1 key 的值变化,则保存
  4. '情况2'save 300 10 :300 秒内如果至少有 10 key 的值变化,则保存
  5. '情况3'save 60 10000 :60 秒内如果至少有 10000 key 的值变化,则保存
  6. -- 2. 其他触发条件:
  7. 1. 执行save,或者bgsave命令!执行时,是阻塞状态。
  8. 2. 执行flushall命令,也会产生dump.rdb,只是将内存中的数据清空并进行持久化(空文件,意义不大)
  9. 执行flushdb,只会清空当前数据库的数据,不会进行持久化
  10. 3. 当执行shutdown命令时,也会主动地备份数据。
  11. -- 3. 持久化的文件也可以实现压缩。

4.1.3 参数配置

  1. -- 1. 属性 save
  2. '含义' :保存策略
  3. -- 2. 属性 dbfilename
  4. '含义' RDB快照文件名
  5. -- 3. 属性 dir
  6. '含义' RDB快照保存的目录
  7. '备注' :必须是一个目录,不能是文件名。最好改为固定目录。默认为./代表执行redis-server命令时的当前目录!
  8. -- 4. 属性 stop-writes-on-bgsave-error
  9. '含义' : 是否在备份出错时,继续接受写操作
  10. '备注' :如果用户开启了RDB快照功能,那么在redis持久化数据到磁盘时如果出现失败,默认情况下,redis会停止接受所有的写请求
  11. -- 5. 属性 rdbcompression
  12. '含义' :对于存储到磁盘中的快照,可以设置是否进行压缩存储。
  13. '备注' :如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,
  14. 但是存储在磁盘上的快照会比较大。
  15. 读取压缩文件,需要消耗内存
  16. -- 5. 属性 rdbchecksum
  17. '含义' :是否进行数据校验
  18. '备注' :在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,
  19. 如果希望获取到最大的性能提升,可以关闭此功能。

4.1.4 RDB的优缺点

  1. -- 1. 优点
  2. 1. 持久化的过程会单独创建一个子线程来完成,不影响主线程的io
  3. 2. RDB是一个非常紧凑的文件,很适合直接发送到其他的远端数据中心来进行备份
  4. 3. 对比aof持久化过程,数据恢复更快一些。
  5. -- 2. 缺点
  6. 1. 每生成一个新的rdb文件时,旧的rdb文件就会删除
  7. 2. 最后一次的持久化过程,可能会丢失数据
  8. 3. RDB每次持久化时,需要fork一个新的子线程来完成持久化的过程,消耗一定的性能

4.2 AOF

4.2.1 AOF简介

  1. -- 1. 持久化的方式:
  2. AOF是以日志的形式来记录每个写操作,将每一次对数据进行修改,都把新建、修改数据的命令保存到指定文件中。
  3. -- 2. 数据恢复的方式:
  4. Redis重新启动时读取这个文件,重新执行新建、修改数据的命令恢复数据。
  5. -- 3. 默认不开启,需要手动开启
  6. -- 4. AOF文件的保存路径,同RDB的路径一致。
  7. -- 5. AOF在保存命令的时候,只会保存对数据有修改的命令,也就是写操作!
  8. -- 6. RDBAOF存的不一致的情况下,按照AOF来恢复。因为AOF是对RDB的补充。备份周期更短,也就更可靠。

4.2.2 AOF保存数据的策略

  1. -- 1. AOF保存策略
  2. 1. appendfsync always:每次产生一条新的修改数据的命令都执行保存操作;效率低,但是安全!
  3. 2. appendfsync everysec:每秒执行一次保存操作。如果在未保存当前秒内操作时发生了断电,仍然会导致一部分数据丢失(即1秒钟的数据)。
  4. 3. appendfsync no:从不保存,将数据交给操作系统来处理。更快,也更不安全的选择。
  5. -- 2. 推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

4.2.3 配置参数

  1. -- 1. 属性 appendonly
  2. '含义' :是否开启AOF功能
  3. '备注' :默认是关闭的
  4. -- 2. 属性 appendfilename
  5. '含义' AOF文件名称
  6. -- 3. 属性 appendfsync
  7. '含义' AOF保存策略
  8. '备注' :官方建议everysec
  9. -- 4. 属性 no-appendfsync-on-rewrite
  10. '含义' 在重写时,是否执行保存策略
  11. '备注' aof重写功能如果开启,那么会将aof的数据加载到内存中,进行aof文件中的数据进行优化,可以节省aof文件的大小。
  12. 此参数为:执行重写,是否支持持久化
  13. -- 5. 属性 auto-aof-rewrite-percentage
  14. '含义' :重写的触发条件1
  15. '备注' :当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写
  16. -- 6. 属性 auto-aof-rewrite-min-size
  17. '含义' :设置允许重写的最小aof文件大小
  18. '备注' :避免了达到约定百分比但尺寸仍然很小的情况还要重写
  19. -- 7. 属性 aof-load-truncated
  20. '含义' :截断设置
  21. '备注' :如果AOF -load-truncated设置为yes,则加载一个截断的AOF文件,并且Redis服务器开始发送日志通知用户事件。
  22. 如果选项被设置为no,服务器将终止并出现错误拒绝开始。
  23. 当选项设置为no时,用户需要在重启之前使用"redis-check-aof"实用程序修复AOF文件

4.2.4 AOF文件的修复

  1. 如果AOF文件中出现了残余命令,会导致服务器无法重启。此时需要借助redis-check-aof工具来修复!
  2. 命令: redis-check-aof --fix 文件

4.2.5 AOF的优缺点

  1. -- 1. 优点
  2. 1. 备份机制更稳健,丢失数据概率更低
  3. 2. aof持久化文件是可读的日志文本,通过操作AOF稳健,可以处理误操作
  4. -- 2. 缺点
  5. 1. 比起RDB占用更多的磁盘空间
  6. 2. 恢复备份速度要慢
  7. 3. 每次读写都同步的话,有一定的性能压力

4.3 官方持久化建议

  1. -- 官方推荐两个都用;如果对数据不敏感,可以选单独用RDB;不建议单独用AOF,因为可能出现Bug;如果只是做纯内存缓存,可以都不用

五、事务

5.1 redis的事务介绍

  1. 1. Redis中事务,不同于传统的关系型数据库中的事务,acid一个都没有
  2. 2. Redis中的事务指的是一个单独的隔离操作。
  3. 3. Redis的事务中的所有命令都会序列化、按顺序地执行且不会被其他客户端发送来的命令请求所打断。
  4. 4. Redis事务的主要作用是串联多个命令防止别的命令插队

5.2 redis常用的命令

  1. -- 1. MULTI 标记一个事务块的开始
  2. -- 2. EXEC 执行事务中所有在排队等待的指令并将链接状态恢复到正常
  3. 当使用WATCH 时,只有当被监视的键没有被修改,且允许检查设定机制时,EXEC会被执行
  4. -- 3. DISCARD :刷新一个事务中所有在排队等待的指令,并且将连接状态恢复到正常。
  5. 如果已使用WATCHDISCARD将释放所有被WATCHkey
  6. -- 4. WATCH:标记所有指定的key 被监视起来,在事务中有条件的执行(乐观锁)
  7. -- 5. UNWATCH:放弃监控一个KEY

5.3 redis组队失败

  1. -- 1. 情况1:自作自受:类似java中的运行时错误,只有运行错误的操作指令不会执行,其他的指令会正常执行
  2. -- 2. 情况2:殃及池鱼:事务中语法出现错误,类似编译时就报错了,那么事务块中所有的指令都不会执行
  3. -- 3. 官方说明:为什么情况1不支持rockback,回滚呢?
  4. 因为在redis就是基于内存的操作,要求处理的数据快,所以redis内部可以保持简单且高速。

5.4 Redis中的锁

  1. -- Redis中的锁策略
  2. 1. Redis采用了乐观锁策略(通过watch操作)。乐观锁支持读操作,适用于多读少写的情况!
  3. 2. 在事务中,可以通过watch命令来加锁;使用 UNWATCH可以取消加锁;
  4. 3. 如果在事务之前,执行了WATCH(加锁),那么执行EXEC 命令或 DISCARD 命令后,锁对自动释放,即不需要再执行 UNWATCH

六、主从复制

6.1 主从简介

  1. -- 1. 什么是主从复制
  2. 配置多台Redis服务器,以主机和备机的身份分开。主机数据更新后,根据配置和策略,自动同步到备机的master/salver机制。
  3. -- 2. 主从用途
  4. Master以写为主,
  5. Slave以读为主,
  6. 二者之间自动同步数据。
  7. -- 3. 主从目的
  8. 1. 读写分离提高Redis性能;
  9. 2. 避免单点故障,容灾快速恢复
  10. -- 4. 实现原理
  11. 1. 当从机第一次上线时:从机给主机发送sync指令,主机立刻进行存盘操作,发送RDB文件给到从机,从机收到RDB文件以后,就会将数据
  12. 加载到内存汇总。
  13. 2. 后续:每次主机的写操作命令,都会立刻发送给从机,从机执行相同的命令来保持和主机的数据一致。
  14. -- 5. 注意
  15. 1. 主机收到从机的sync同步的指令时,即使在配置文件中禁止使用RDB持久化时,也会生产RDB文件
  16. 2. 但是如果主机所在的服务器磁盘的IO性能比较差时,那么这个复制过程就会出现瓶颈。
  17. 3. 第二点的问题,redis2.8.18版本开始实现了无磁盘复制功能。不过该功能还是处于试验阶段
  18. '实现方式':设置参数:repl-diskless-sync yes
  19. '实现过程'redis的主机进行复制初始化,不会将内存的数据进行持久化,而是直接通过网络的方式直接发送给从机,避免了io
  20. 能差的问题.

6.2 主从准备

  1. -- 1. 除非是不同的主机配置不同的Redis服务,否则在一台机器上面跑多个Redis服务,需要配置多个Redis配置文件
  2. -- 步骤1:准备多个Redis配置文件,每个配置文件
  3. 0. 在家目录在创建mkdir my_redis目录,在这个目录下创建如下4个配置文件
  4. 1. 准备一个base.conf文件
  5. 2. 另外准备3个配置文件:6379.conf/6380.conf/6381.conf
  6. 3. 如上4个配置文件的内容为:
  • 6379.conf
  1. include /home/atguigu/my_redis/base.conf
  2. dbfilename dump_6379.rdb
  3. pidfile /home/atguigu/my_redis/6379.pid
  4. logfile "/home/atguigu/my_redis/6379.log"
  5. port 6379
  • 6380.conf
  1. include /home/atguigu/my_redis/base.conf
  2. dbfilename dump_6380.rdb
  3. pidfile /home/atguigu/my_redis/6380.pid
  4. logfile "/home/atguigu/my_redis/6380.log"
  5. port 6380
  • 6381.conf
  1. include /home/atguigu/my_redis/base.conf
  2. dbfilename dump_6381.rdb
  3. pidfile /home/atguigu/my_redis/6381.pid
  4. logfile "/home/atguigu/my_redis/6381.log"
  5. port 6381
  1. -- 如上3个配置文件的说明:
  2. include -- 可以将公共的配置放入到一个公共的配置文件中,然后通过子配置文件引入父配置文件中的内容!将配置按照模块分开!
  3. dbfilename -- 持久化文件名字
  4. pidfile -- pid文件路径
  5. logfile -- log文件路径
  6. port 6381 -- redis端口
  • base.conf
  1. -- 是从redis-3.2.5目录中拷贝过来的,主要参数有:
  2. 1. bind 0.0.0.0
  3. 2. protected-mode no
  4. 3. port 6379
  5. 4. tcp-backlog 511
  6. 5. timeout 0
  7. 6. tcp-keepalive 300
  8. 7. daemonize yes
  9. 8. supervised no
  10. 9. pidfile /var/run/redis_6379.pid
  11. 10. loglevel notice
  12. 11. logfile "/opt/module/redis-3.2.5/redis.log"
  13. 12. databases 16
  14. 13. save 900 1
  15. save 300 10
  16. save 60 10000
  17. 14. stop-writes-on-bgsave-error no
  18. 15. rdbcompression yes
  19. 16. rdbchecksum yes
  20. 17. dbfilename dump_7379.rdb
  21. 18. dir /home/atguigu/my_redis --> rdb文件路径
  22. 19. slave-read-only yes
  23. 20. repl-diskless-sync no --> 同步时是否直接通过网络进行发送
  24. 21. appendonly no --> 不开启aof持久化
  25. 22. appendfsync everysec --> aof持久化策略
  26. 22. no-appendfsync-on-rewrite no --> 重写的过程依然执行持久化
  27. 23. auto-aof-rewrite-percentage 100 -->重写触发条件,重写文件是上一个重写文件的百分比
  28. 24. auto-aof-rewrite-min-size 64mb --> aof重写触发条件:重写文件的最小大小
  29. 25. aof-load-truncated yes --> 是否加载截断的文件
  1. -- 步骤2:分别启动不同配置文件的redis-server服务端
  1. -- 步骤3 分别进入不同redis-server的客户端并查看各自的信息。3个客户端的情况是一致的。
  2. 查看主从的副本关系:info replication

主从关系的配置:配从不配主。

6.3 主从建立

6.3.1 建立临时的主从关系

  1. -- 1. 临时建立
  2. '原则':配从不配主。
  3. '配置':在从服务器上执行'SLAVEOF ip:port'命令;
  4. '查看':执行'info replication'命令;
  5. -- 2. slave:只支持读的操作,不支持写的操作,同时主机的数据,在从机上能够直接获取
  6. hadoop105:6379> set k1 2
  7. (error) READONLY You can't write against a read only slave.

6.3.2 永久建立

  1. -- 1. 直接在配置文件指明当前的redis属于哪个的slave
  2. 在从机的配置文件中,编写slaveof属性配置!
  3. 如在6380.conf配置中写上: slaveof hadoop105 6379

6.3.3 恢复身份

  1. 执行命令slaveof no one恢复自由身!

6.4 常见问题

  1. -- 1. 从机是从头开始复制主机的信息,还是只复制切入以后的信息?
  2. 1. 从机第一次启动,从头开始复制主机信息
  3. 2. 后续,主机有一条数据发生修改,就发送给从机
  4. -- 2. 从机是否可以写?
  5. 1. 默认情况不能
  6. 2. 可以通过修改配置文件,设置slave-read-only no.但是从机写入的数据是不能同步到主机,因此没用设置的必要!
  7. -- 3. 主机shutdown后,从机是上位还是原地待命?
  8. 答: 原地待命
  9. -- 4. 主机又回来了后,主机新增记录,从机还能否顺利复制?
  10. 答:可以
  11. -- 5. 从机宕机后,重启,宕机期间主机的新增记录,从机是否会顺利复制?
  12. 答:可以
  13. -- 6. 其中一台从机down后重启,能否重认旧主?
  14. 答:不一定,如果是临时主从关系,不能重认旧主,如果是在配置文件中,指定了master,那么可以重认旧主
  15. -- 7. 如果两台从机都从主机同步数据,此时主机的IO压力会增大,如何解决?
  16. 答:按照主---从(主)---从模式配置!

6.5 哨兵模式

七、集群模式

八、Jedis

1.一个对比

2.Redis准备

①理解Redis配置文件中bind配置项含义
bind后面跟的ip地址是客户端访问Redis时使用的IP地址(需要再配置文件中体现)。看下面例子:

②查看Linux系统本机IP

远程客户端访问Linux服务器时不能使用127.0.0.1,要使用网络上的实际IP。可以用ifconfig命令查看。

③将Redis配置文件中的bind配置项设置为本机IP。

  1. bind [你的实际IP]
  2. bind 192.168.1.102

3.远处访问代码体现

  1. package com.atguigu.jedis;
  2. import org.junit.Test;
  3. import redis.clients.jedis.Jedis;
  4. import redis.clients.jedis.JedisPool;
  5. import redis.clients.jedis.Protocol;
  6. import java.util.List;
  7. public class JedisTest {
  8. // 连接Redis的主机地址
  9. private String host="192.168.1.102";
  10. //连接Redisde的端口号
  11. private int port= Protocol.DEFAULT_PORT;
  12. // 创建Jedis对象
  13. Jedis jedis = new Jedis(host, port);
  14. //读操作
  15. @Test
  16. public void testGetValue() {
  17. // 调用“和Redis命令同名的方法”操作Redis
  18. String ping = jedis.ping();
  19. System.out.println(ping); //PONG
  20. //获取数据库中number的值
  21. String number = jedis.get("number");
  22. System.out.println(number); //123321
  23. //关闭连接
  24. jedis.close();
  25. }
  26. //写操作
  27. @Test
  28. public void testLpush() {
  29. // 调用“和Redis命令同名的方法”操作Redis
  30. String ping = jedis.ping();
  31. System.out.println(ping); //PONG
  32. // 调用方法将数据存入Redis
  33. Long lpush = jedis.lpush("fruit", "apple", "banana", "orange");
  34. System.out.println("lpush result="+lpush); //lpush result=3
  35. // 查询刚才存入的数据
  36. List<String> fruitList = jedis.lrange("fruit", 0, -1);
  37. //数组需要遍历
  38. for (String fruit:fruitList) {
  39. System.out.println(fruit);
  40. }
  41. //关闭连接
  42. jedis.close();
  43. }
  44. //连接数据池
  45. @Test
  46. public void testJedisPool() {
  47. // 创建连接池对象
  48. JedisPool jedisPool = new JedisPool(host, port);
  49. // 从连接池中获取具体的一个连接对象
  50. Jedis jedis = jedisPool.getResource();
  51. // 调用具体方法
  52. String ping = jedis.ping();
  53. System.out.println(ping);
  54. // 关闭连接
  55. jedis.close(); //PONG
  56. }
  57. }

九、缓存穿透、缓存击穿、缓存雪崩区别和解决方案

缓存处理流程

前台请求,后台先缓存中取数据,取到直接返回结果。取不到时从数据库中取,数据库更新缓存,并返回结果,数据库也没取到,那直接返回空结果、

image.png

9.1、缓存穿透

  • 描述

    指缓存和数据库中没有数据,然后用户不断发起请求,这样会疯狂去查数据库,造成数据库压力。

  • 解决方案

    1、在接口层或者前面先对id进行过滤基础校验,例如过滤为null或为负数的数据。 2、当从缓存和数据库都取不到数据时,从数据库返回的null可以缓存到redis,防止同一id反复暴力去查数据库。

9.2、缓存击穿

  • 描述

    指缓存中无数据但是数据库中有数据(一般是缓存时间到期),这时由于并发用户特别多,同时读取缓存没有数据,疯狂去查数据库,数据库瞬间压力增大。

  • 解决方案

    1、设置热点数据永不过期(比如我们在查过一个缓存数据后,又给他设置一个一天的时间) 2、加互斥锁。

9.2、缓存崩塌

  • 描述

    指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机,区别于缓存击穿,缓存击穿指的是并发查询同一条数据,而缓存雪崩是不同数据都过期了,很多数据都是在缓存查不到从而去查数据库。

  • 解决方案

    1、缓存数据局的过期时间设置随机,防止同一时间大量数据过期现象发生。 2、如果缓存数据库是分布式部署的,将热点数据均匀分布在不同数据库中。 3、设置热点数据永不过期。

十、常用命令

1、查看占用内存

info/info memory

image.png

used_memory:13490096 //数据占用了多少内存(字节)

used_memory_human:12.87M //数据占用了多少内存(带单位的,可读性好)

used_memory_rss:13490096 //redis占用了多少内存

used_memory_peak:15301192 //占用内存的峰值(字节)

used_memory_peak_human:14.59M //占用内存的峰值(带单位的,可读性好)

used_memory_lua:31744 //lua引擎所占用的内存大小(字节)

mem_fragmentation_ratio:1.00 //内存碎片率

mem_allocator:libc //redis内存分配器版本,在编译时指定的。有libc、jemalloc、tcmalloc这3种。

详情连接