Redis总结

x33g5p2x  于2021-10-07 转载在 Redis  
字(10.0k)|赞(0)|评价(0)|浏览(290)

前言

Redis官方
Redis采用的是 单线程多路IO复用

提示:以下是本篇文章正文内容,下面案例可供参考

一、Redis常用数据类型

1. 在Linux系统中登录Redis,找到在redis的bin文件中执行下面目录
		启动服务器 ../redis-server redis.conf
		连接redis:../redis-cli -h 自己Linux的ip -p 自己设置的主从端口号 都可以登录

1.1 key 指令

1. keys *  #查看所有的key
2.set key value #设值
3.exists key #判断当前key是否存在  return 1 表存在
4.del  key   #从当前数据库 移除 key
5.move key 数据库(0-15) #表示将当前库的key移动到 指定的数据库
6.expire key 消失时间(秒)  #倒计时结束后key消失 单位是秒
	ttl key  #可以查看key的消失时间 ttl=time to lose
	           # -1表示永不过期  -2 表示已经过期	
	persist key #清除剩余的消失时间
7. type key  #查看key的类型
8.append key value  #往存在的key中追加 value  如果key不存在 相当于 set key value 新建键值对儿
9.strlen key  #查看key的长度
10.incr key #将key自增1
11.decr key #将key自减1
12.incrby key num #设置 key每次增加 num个数    浏览量+num
13.decrby key num #设置key每次减少 num个数    浏览量-num
14.getrange key start end #拿到key的指定范围  start从0开始   end=-1表示拿到全部的字符串
15.setrange key start value  #修改key 从start开始
	set test test666 
	替换value  setrange test 1 xx 
	get test : txxt666
16.setex key second value #设值过期时间    setex=set expire 设置失效时间
17.(分布式锁中常用)setnx key value  #不存在设置  如果key不存在设置成功返回1,如果key存在不设置 返回0   setnx=set if no exist
18.mset key value key value  #同时设置多个值
19.mget key key key  #同时读取多个值
20.msetnx key value key value #如果其中一个设置失败回滚所有数据都不存在 原子性操作:要么一起成功,要么一起失败

以json字符来保存对象
21.set user:id {name:value,age:value}
    get user:id 拿到该json

22.mset user:id:key value user:id value  #设置多组user对象
    mget user:id:key user:id:key获取多组对象

23.getset key value #先获取key 再将key的值设置成value  达到更新的效果
#若get拿到的key没有,set会创建key然后赋值value
#若get拿到的key存在,set会将key的值更新为value

24.info #获取服务器信息和统计
    flushdb #删除 当前 数据库中所有的key
    flushall #删除 所有 数据库中的key
25. select n  #切换数据库  n= 0-15

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1.2 list 指令

Redis list是 从左到右插入   左边是头  右边是尾
       Redis-list中的顺序 :先进后出
List: 单键多值
底层是 双向链表,对两端的操作性能很高,通过索引下标操作中间的节点性能较差
1.lpush key values # 把values插入 key这个list集合中

2.lrange key start end #查到当前key这个集合中的元素
	end= -1 代表所有元素

3.rpush key elements #从key这个集合中从右插入元素

4.lpop key  #把key这个集合中 左侧(头)移除
  rpop key  #把key这个集合中 右侧(尾)移除
  # 值在键在,值亡键亡	
5.lindex key num  #查找key这个list中索引为num的值
6.llen key  #查找key这个list的长度
7.lrem key num element  #从key这个list中移除 num个 element元素
	若当前key集合中的element的num数 <要移除的num 则只删除存在的个数
8.ltrim key start end  #截取(移除)key这个集合中的值

9.rpoplpush source destination(目的地)  #将 source这个集合中的尾(右侧)元素的最后一个 移除 然后 添加到 destination集合中
 #  rpoplpush= remove pop lpush

10.lset key index element  #将 key这个集合中第index个索引的value修改成element 如果没有index则会报错

11.linsert key before|after "pivot" "value"  #向key这个集合中的pivot值 向前或者向后 插入 value
	eg: linsert test before "world" "other"  将other插入到world之前

1.3 set 指令

set集合中 value不可以重复 无序

1.sadd key values #向key集合中添加多个value

2.smembers key  #查看key集合的所有元素

3.sismember key value #查看当前key集合中是否存在指定的value

4.scard key  #获取key集合中元素的个数

5.srem key value  #移除key中指定的value值

6.srandmember key (num) #从key集合中随机拿出(n)个值 不加num 默认拿出1个

7.spop key  #随机从key集合中删除一个value

8.smove key newKey member  #将key中的member元素移动到newKey的集合中,key中移动的value会失去

9.sdiff key1 key2  #查看key1集合与key2集合中 有哪些差集(key1中出现但是后面的集合没有出现)

10.sinter key1 key2 #查看key1集合与key2集合中的交集(共有的value)

11.sunion key1 key2 #查看key1集合与key2集合中所有的value

1.4 hash 指令

简单来说 key-Hash(哈希)<key-value>  我存我自己
	eg: hset myHash

1.hset key field value  #把value存入key这个哈希的field字段中
	如果 key中这个field存在 那么value的值会被重新覆盖
2.hget key field  #获取key这个哈希的field字段

3.hmset key filed1 value field2 value2 #在key中设置多个字段值

4.hmget key filed1 field2 #同时获取多个字段值

5.hgetall key  #获取所有哈希字段

6.hdel key field #删除key中指定的field 对应的value也就删除了

7.hlen key  #获取key哈希表的字段数量

8.hkeys key  #只获取所有的field     

9.hvals key  #只获取所有的value

10.hincrby key field num  #给key哈希表中的字段 加减 num

11.hsetnx key filed value  #如果不存在 给key哈希表中的filed增加value   存在失败

1.5 zset 指令

Zset(有序集合,从小到大排序)
索引从0开始
在set基础上,增加了一个值 set k1 v1  zset k1 score1 v1

1.zadd key score value #添加一个值

2.zadd key score value score value2  #添加多个值、

3.zrange key start end #查看key的元素
   zrange key start end withsores #显示key的所有元素并且显示score 

4.zrangebyscore key -inf +inf #通过score对 key进行排序 -inf表示负无穷 +inf表示正无穷  从小到大

5.zrevrange key start end  #从高到低降序 start 0 end -1

6.zrangebyscore key -inf +inf withscores #并且把score显示出来

7.zrem key member #从key中移除member成员 

8.zcard key  #获取有序集合的个数

9.zcount key min max  #获取key中指定区间的值

10.zincrby key number member #给key中的member的score值增加number

11.zrank key mumber #查看key中munber成员的排名 排名从0开始

1.6 HyperLogLog 指令

#在一组集合中只统计key中不重复的数为n,n叫做基数
1. pfadd key element #向key中添加element数据,重复的加不进去
2. pfcount key #查询key中的基数(不重复的数据个数)
3. pfmerge newKey oKey1 oKey2 #将oKey1和oKey2中的数据合并到newKey中 返回合并后的基数

1.7 geospatial 指令

地理位置

1.geoadd key longitude(精度) latitude(纬度) member #给key中添加 member这个城市的经度纬度

2.geopos key member  #获取key中 member城市的 精度和纬度

3.geodist key member1 member2 m|km|ft|mi| #查询key中 member1和member2两个城市的距离

4.georadius key 精度 纬度 方圆多少公里以内 #查询key中精度纬度并且在方圆多少公里以内的城市

二、事务的使用

2.1 事务

Redis事务使用的是乐观锁:
#悲观锁:
	当有人使用时其他线程只能排队
#乐观锁:
	所有人都可以进行操作数据,当进行操作时会先判断数据的版本号,如果版本号不一致,则更新数据失败
1.  multi #开启事务

2.  set key value #将多个命令入队到事务中,返回 queued队列 

3.  exec #最后由exec命令触发事务,一并执行事务中的所有命令

4.  discard #放弃当前事务

5. watch  key1 key2(可以监视多个key)   #如果在执行multi之前,先执行 watch key,可以进行监视一个或多个key,如果在 事务执行之前这个/这些key被其他命令所改动,那么事务将会打断。

6. unwatch key  #取消对key的监视

#Redis发布订阅模式

1.subscribe channel(可以换自定义名)  #订阅频道

2.publish channel(可以换自定义名) message(要发布的信息) #发布频道

三、RDB与AOF

3.1 RDB(Redis Database)

1. 在redis.conf配置文件中 有 dump.rdb文件是RDB默认生成的文件,你在哪个目录下启动Redis服务,dump.rdb就会在哪个目录下生成

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

3.2 文件存放目录

3.3 RDB备份是如何执行的

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,等持久化的过程结束了,再用这个临时文件替换上次持久化的文件,RDB的缺点:最后一次持久化操作后数据可能丢失

3.2 AOF(Append Only File)

以日志的方式来记录每个写操作(增量保存),将Redis执行过程的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取文件重新构建数据,

3.2.1 AOF开启

AOF默认不开启
在redis.conf配置文件中查找appendonly

修改完毕后,重启redis 用 kill杀死端口号或者shutdown退出redis

3.2.2 RDB与AOF同时存在Redis读取谁的文件

当我们开启RDB与AOF后,Redis开启服务后会读取appendonly.aof文件 也就是读取AOF文件,但是RDB的数据不会丢失

3.2.3 AOF文件恢复

当appendonly.aof文件受损后,redis不能正常启动读取AOF文件
,我们可以在redis的bin目录下使用命令对appendonly.cof文件进行修复:
./redis-check-aof --fix appendonly.aof

3.2.4 AOF同步频率设置

#在redis.conf配置文件中修改,默认 是  appendfsync everysec(every second)每秒记录一次
	appendfsync always #始终同步,每次Redis的写入都会立刻写入日志,性能较差但数据完整性比较好
	appendfsync everysec #每秒同步,每秒记入日志一次,如果宕机(Redis挂掉),本秒的数据可能丢失
	appendfsync no #redis不主动进行同步,把同步时机交给操作系统

3.3 总结RDB与AOF

RDB:
	优点:
		1.适合大规模的数据恢复
		2.对数据完整性和一致性要求不高更适合使用RDB
		3.节省磁盘空间
		4.恢复速度快
	缺点:
		1.进行fork时,内存中的数据内copy了一份,大概两倍的膨胀性需要考虑
AOF:
	优点:
		1.备份机制更强,丢失数据概率更低
		2.刻度的日志文本,可以处理误操作
	缺点:
		1.占用磁盘空间更多
		2.恢复备份速度要慢
		3.每次读写都同步,有一定的性能压力
用哪个好:
	如果对数据不敏感,可以单用RDB
	不建议单独使用AOF,可能会出现bug
	如果只是纯内存缓存,可以都不用。

四、主从复制

4.1 什么叫做主从复制?

主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master 以 写 为主,Slave以读为主
	如果只有一台Redis服务器,我们的读写操作都在这一台Redis服务器中进行,当数据过多时,压力较大
	主从复制:
		1.我们的主服务器只负责写入操作
		2.将主服务器的数据复制到从服务器,从服务器负责读取数据,从而大大减小服务器的压力
		优点:
			1.读写分离:减少服务器压力
			2.容灾快速恢复:当其中一台从服务器挂掉,那么我们就会读不到数据,根据策略,进行切换到另一台从服务器进行读取数据

4.2 实现一主两从

创建两个额外的redis.conf命名为 redis6380.conf和redis.6381.conf的空文件
	在这两个文件中写入以下命令:
		include /mySoft/redis-5.0.5/bin/myRedis/redis.conf #地址换成自己创建的主服务器配置文件
		pidfile /var/run/redis_6380.pid 或 /var/run/redis_6381.pid
		port 6380/6381
		dbfilename dump6380.rdb 或  dump6381.rdb
	启动服务器 ../redis-server redis.conf
	连接redis:../redis-cli -h 自己Linux的ip -p 自己设置的主从端口号 都可以登录
	查看当前redis服务器的运行状态(需要进入redis):info replication  # role master 表示当前是主服务器
	将端口号为6380/6381的服务器设置成 从服务器   配从(服务器)不配主(服务器): slaveof <Linux主机ip> <主Redis主机端口号>
	完成搭建!
	当我们在Redis主服务器上进行写入数据时,数据会复制给 redis从服务器,我们可以在 从服务器拿到主服务器写入的数据
	
	方法二:
		1.我们复制redis.conf配置文件
		2.查找 replicaof ,后面改成 replicaof <主机ip> <主服务器端口号>
		3.查找 port 端口号 修改为 6380/6381
		4.若复制整个redis文件夹里面包含有appendonly.aof 和 dump.rdb 文件夹 需要删除这两个持久化文件 rm -rf appendonly.aof dump.rdb
		5.启动从机即可

4.3 常用三招

4.3.1 一主二仆

主服务器:a  从服务器:b 从服务器:c
	当 从服务器c 挂掉后,我们从新启动从服务器c后,从服务器c的状态是master独立的主机
	,并不能直接加入我们的主服务器a,需要用命令 slaveof <ip> <port> 来加入主服务器a
	,让我们这个重启的主服务器c变成 主服务器a 的从服务器,服务器c变成从服务器后
	,会将 主服务器a 中的 所有数据 从头到尾 复制一遍

	
	主服务器:a  从服务器:b 从服务器:c
	若 主服务器a  挂掉后,从服务器b 从服务器c 不会做任何事情,还认 主服务器a  为 master
	,当 主服务器a 重新启动后,服务器a 还是 b 和 c 的主服务器a

4.3.2 薪火相传

单我们有一个主服务器,n个从服务器,如果n个服务器都从主服务器获取数据,那么 主服务器 压力会比较大
	,我们可以把 n个从服务器 分成个n个组,每组有一个队长来管理下面的从服务器(类似于传销),当我们 主服务器a 写入数据时,主服务器a 就需要给 从服务器b 发送数据即可,从服务器b 再给下面管理的 n个从服务器 发送数据。
	将 n个从服务器 连接 管理的 从服务器b 即可 : slaveof <从服务器b ip> <从服务器b 端口号>
	缺点:
		当我们管理n个从服务器的 从服务器b 挂掉后,我们的主服务器 无法主动 向下面的n个从服务器 发送数据,会导致读取不到数据

4.3.3 反客为主

当主服务器挂掉后,从服务器可以上升为大哥(上位)
	从服务器 变成 主服务器 : slaveof no one
	缺点:需要我们手动给从服务器 输入命令 来变成 主服务器

4.4 哨兵模式(sentinel)

反客为主的自动版:后台监控主服务器是否故障,如果故障了 根据投票数自动将从服务器转为主服务器,一旦有 主服务器  宕机(挂掉)后,自动将某个 从服务器  变成 主服务器
	操作:
		1.在redis启动目录下创建一个 sentinel.conf 文件夹,名字不能错
		2.在sentinel.conf文件中输入  sentinel monitor mymaster(这个自定义名称可以换) redis主服务器ip redis主服务器端口号 1(从服务器中的哨兵有几个同意就可以切换)   保存
		3.启动服务  ./redis-sentinel sentinel.conf
		4.测试让主机挂掉,看第三步的窗口会选举出来从服务器中的一个当做主服务器,主机再次连接后就变成了从服务器
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

五、Redis集群

5.1 无中心化集群

通俗来说就是:每一台服务器都可以当做集群的入口,服务器之间可以互相连通

5.2 集群搭建

1.复制一份redis.conf配置文件在你自定义文件夹中
	2.创建一个redis6379.conf配置文件在你自定义的文件夹中
	3.redis6379.conf配置文件中写入以下命令:
		include /mySoft/redis-5.0.5/bin/myRedis/redis.conf #地址换成自己创建的主服务器配置文件
		pidfile /var/run/redis_6380.pid 或 /var/run/redis_6381.pid
		port 6380/6381
		dbfilename dump6380.rdb 或  dump6381.rdb
		cluster-enabled yes #打开集群模式
		cluster-config-file nodes-6379.conf #设置节点配置文件名
		cluster-node-timeout 15000 #设定节点失联时间,超过该毫秒,集群自动进行主从切换
	4.cp redis6379.conf 并改名为其余的5个文件,并且把里面所有的6379改成相对应的其他服务器的端口号
	5.把6个Redis服务器启动起来  redis-server redisxxxx.conf
	6.启动完毕后, ll 可以看见 启动的node节点文件 即可
	7.进入redis安装目录中的scr目录下,本身需要一个ruby环境,高版本的redis自带,若没有需先安装ruby环境
	8.若scr下 有 redis-cli 和 redis-trib.rb  表示 有ruby环境
	9../redis-cli --cluster create --cluster-replicas 1(1表示用最简单的方式进行分配) <ip:端口号1 ip:端口号2 ip:端口号3 ip:端口号4 ip:端口号5 ip:端口号6> #此处的ip 必须是Linux  IP地址,不能是 localhost 或 127.0.0.1
	10. 输入第9步命令则会 提示 分配的主从集群   后 输入  <yes> 同意分配
	测试:
	11. ./redis-cli -c(采用集群策略连接) -h ip地址 -p xxxx(集群中的随便一个端口号都可以)
	12.  cluster nodes  #查看集群节点的信息

5.3 slot插槽

当集群创建完毕后,会提示:
		[OK] All 16384 slots covered.
		16384代表的是Redis中的插槽,一个Redis集群中包含16384个插槽(hash  slot),数据库中的每个键都属于16384插槽中的某一个
		当我们向集群中 插入数据时,Redis会通过计算 key 来算出 插入数据所在的插槽,然后把数据放入插槽中,
		以我创建的集群为例,有6个插槽,那么 我有三个master 主机,
		主机a插槽范围:0~5460 主机b插槽范围:5461~10922  主机c插槽范围:10923~16383
		当我们的key属于 三个主机插槽中的某一个范围时,就交给对应的主机进行存储数据
		查看key所在的插槽: cluster keyslot key
		查找自己主机所包含范围内插槽内是否有值: cluster countkeysinslot 插槽值

5.4 故障恢复

当我们的某台主机宕机后,我们的从服务器会变成主机,而我们挂掉的主机再重新启动后,会变成从机

六、缓存问题

6.1 缓存穿透

总结:
		1.应用服务器压力变大
		2.redis命中低低(找不到数据),从而去数据库查找
		3.一直查询数据库,导致数据库崩
	导致原因: 一般都是有黑客进行攻击导致
		1.redis查询不到数据
		2.大量非正常访问的url 修改url请求不存在的参数
	解决方案:
		1.对空值缓存:如果一个查询返回的数据为空,我们仍然把这个空结果(null)进行Redis缓存,设置空结果的过期时间很短,最长不超过五分钟
		2.布隆过滤器
		3.设置白名单
		4.进行实时监控:当发现Redis中的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单。
		5.报警(网警):有问题找警察叔叔

6.2 缓存击穿

总结:
			1.数据库访问压力瞬时增加
			2.redis里没有出现大量的key过期
			3.redis正常运行
		导致原因:
			1.redis中的某个key过期,并且这个时间有大量访问这个key
			2.redis查询不到,会有大量访问数据库,导致数据库压力瞬时增大
		解决方案:
			1.预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长
			2.实时调整:现场监控这些热门数据,实时调整key的过期时长
			3.使用锁

6.3 缓存雪崩

总结:
		1.数据库压力变大服务器崩溃
	导致原因:
		1.在极少时间段,查询大量key集中过期情况
	解决方案:
		1.构建多级缓存架构:NGINX缓存+Redis缓存+其他缓存
		2.使用锁或队列:不适合高并发情况
		3.设置过期标志更新缓存
		4.让缓存失效时间分散开

七、分布式锁

7.1 依据 Redis实现分布式锁

Redis共享锁: 性能最高
	setnx age 22 :当我们第一次设置了key value时,redis会进行上锁操作,如果这个key不释放,则其他setnx age 无法设置新值,只能等锁释放后才可以设置
	1.通过 setnx key value 上锁
	2.del释放锁
	3.若锁一直不释放,我们可以手动设置失效时间 expire key second
	4.上锁之后出现异常,无法进行失效时间设置
	,我们可以在上锁时直接加上失效时间  set key value nx ex second

相关文章