redis-cli redis命令行工具
shutdown exit 退出命令行并关闭redis服务
redis-serverctrl+C 仅退出命令行
1.Redis应用场景
1、热点数据的缓存 ---- 由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据,另外结合expire,我们可以设置过期时间然后再进行缓存更新操作,这个功能最为常见。 2、限时业务的运用 redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。 3、计数器相关问题 什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景 。 4、排行榜相关问题 关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。 在奶茶活动中,我们需要展示各个部门的点赞排行榜, 所以我针对每个部门做了一个SortedSet,然后以用户的openid作为上面的username,以用户的点赞数作为上面的score, 然后针对每个用户做一个hash, 通过zrangebyscore就可以按照点赞数获取排行榜,然后再根据username获取用户的hash信息,这个当时在实际运用中性能体验也蛮不错的。 5、分布式锁 --Sys---本地锁 在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。这个主要利用redis的setnx命令进行,setnx:"set if notexists"就是如果不存在则成功设置缓存同时返回1,否则返回0 ,这个特性在俞你奔远方的后台中有所运用,因为我们服务器是集群的,定时任务可能在两台机器上都会运行,所以在定时任务中首先通过setnx设置一个lock,如果成功设置则执行,如果没有成功设置,则表明该定时任务已执行。 当然结合具体业务,我们可以给这个lock加一个过期时间,比如说30分钟执行一次的定时任务,那么这个过期时间设置为小于30分钟的一个时间 就可以,这个与定时任务的周期以及定时任务执行消耗时间相关。 当然我们可以将这个特性运用于其他需要分布式锁的场景中,结合过期时间主要是防止死锁的出现。 6、延时操作---延迟队列 比如在订单生产后我们占用了库存,10分钟后去检验用户是够真正购买,如果没有购买将该单据设置无效,同时还原库存。 由于redis自2.8.0之后版本提供Keyspace Notififications功能,允许客户订阅Pub/Sub频道,以便以某种方式接收影响Redis数据集的事件。 所以我们对于上面的需求就可以用以下解决方案,我们在订单生产时,设置一个key,同时设置10分钟后过期, 我们在后台实现一个监听器,监听key的实效,监听到key失效时将后续逻辑加上。 当然我们也可以利用rabbitmq、activemq等消息中间件的延迟队列服务实现该需求。 7、分页、模糊搜索 redis的set集合中提供了一个zrangebylex方法,语法如下:ZRANGEBYLEX key min max [LIMIT offffset count]通过ZRANGEBYLEX zset - + LIMIT 0 10 可以进行分页数据查询,其中- +表示获取全部数据zrangebylex key min max 这个就可以返回字典区间的数据,利用这个特性可以进行模糊查询功能,这个也是目前我在redis中发现的唯一一个支持对存储内容进行模糊查询的特性。前几天我通过这个特性,对学校数据进行了模拟测试,学校数据60万左右,响应时间在700ms左右,比mysql的like查询稍微快一点,但是由于它可以避免大量的数据库io操作,所以总体还是比直接mysql查询更利于系统的性能保障。 8、点赞、好友等相互关系的存储 点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。这个在奶茶活动中有运用,就是利用set存储用户之间的点赞关联的,另外在点赞前判断是否点赞过就利用了sismember方法,当时这个接口的响应时间控制在10毫秒内,十分高效。 9、队列 由于redis有list push和list pop这样的命令,所以能够很方便的执行队列操作。 Redis列表结构,LPUSH可以在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接根据ID去到对应的内容页即可。
总结:
1.热点数据得缓存
2.限时任务
3.计算器--incr decr
4.分布式锁。==setnx
5.排行榜---sort set
2.Redis的持久化方式
持久化:把内存中的数据,保存到磁盘的过程
为什么要持久化?
Redis对数据的操作都是基于内存的,当遇到了进程退出、服务器宕机等意外情况,如果没有持久化机制,那么Redis中的数据将会丢失无法恢复。有了持久化机制,Redis在下次重启时可以利用之前持久化的文件进行数据恢复。
持久化方式:第一种:RDB 第二种:AOF
2.1RDB持久化方式
RDB持久化以指定的时间间隔执行数据集的时间点快照。 RDB是Redis默认的持久化方式。
在指定的时间间隔内,把内存中的数据复制到磁盘。
RDB持久化存储在磁盘上的名称默认为 dump.rdb
2.1.1Redis触发RDB持久化方式
(1) 手动触发--save命令触发
save
命令会阻塞Redis服务,执行save命令期间,Redis不能处理其他命令, 直到RDB持久化完成。当Redis服务储存大量数据时,会造成较长时间的阻塞,不建议使用。
(2)手动触发--bgsave命令
Redis服务一般不会阻塞。Redis进程会执行fork操作创建子进程,RDB持久化由子进程负责,不会阻塞Redis服务进程。Redis服务的阻塞只发生在fork阶段,一般情况时间很短。基本上Redis中所有的RDB操作都是采bgsave命令。
bgsave
命令的具体流程如下图:1.执行bgsave命令,Redis进程先判断当前是否存在正在执行的RDB或AOF子线程,如果存在就是直接结束。 2.Redis进程执行fork操作创建子线程,在fork操作的过程中Redis进程会被阻塞。 3.Redis进程fork完成后,bgsave命令就结束了,自此Redis进程不会被阻塞,可以响应其他命令。 4.子进程根据Redis进程的内存生成快照文件,并替换原有的RDB文件。 5.子进程通过信号量通知Redis进程已完成。
2.1.2自动触发--满足某种条件触发持久化
Redis内部自动触发RDB持久化,也是采用bgsave的方式,减少Redis进程的阻塞。
配置文件 redis.conf
save seconds changes 表示在s秒内数据被修改过c次时,自动触发bgsave操作 # save <seconds> <changes> [<seconds> <changes> ...]
主从模式
当从节点做全量复制时,主节点会自动执行
bgsave
操作,并且把生成的RDB文件发送给从节点
执行
debug reload
命令时,也会自动触发bgsave
操作
执行
shutdown
命令时,如果没有开启AOF持久化也会自动触发bgsave
操作
2.1.3RDB优缺点
优点:(1)数据恢复速度快 (2)备份速度快 (二进制文件)
缺点:指定时间间隔保存,无法做到实时持久化或秒级持久化,即数据完整性差
2.2AOF持久化方式
AOF(Append Only File)持久化是把每次写命令(增删改操作)追加写入日志中,当需要恢复数据时重新执行AOF文件中的命令就可以了。AOF解决了数据持久化的实时性,也是目前主流的Redis持久化方式。
AOF持久化流程
命令追加(append):所有写命令都会被追加到AOF缓存区(aof_buf)中。 文件同步(sync):根据不同策略将AOF缓存区同步到AOF文件中。 文件重写(rewrite):定期对AOF文件进行重写,以达到压缩的目的。 数据加载(load):当需要恢复数据时,重新执行AOF文件中的命令。
2.2.1AOF持久化配置
AOF持久化默认是不开启的,需要手动配置(redis.conf)
# appendonly改为yes,开启AOF appendonly yes # AOF文件的名字 appendfilename "appendonly.aof" # AOF文件所在目录 appenddirname "appendonlydir" # AOF文件的写入方式 # everysec 每个一秒将缓存区内容写入文件 默认开启的写入方式 appendfsync everysec # 运行AOF重写时AOF文件大小的增长率的最小值 auto-aof-rewrite-percentage 100 # 运行AOF重写时文件大小的最小值 auto-aof-rewrite-min-size 64mb
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage配置确定自动触发的时机。auto-aof-rewrite-min-size表示运行AOF重写时文件大小的最小值,默认为64MB;auto-aof-rewrite-percentage表示当前AOF文件大小和上一次重写后AOF文件大小的比值的最小值,默认为100。只用前两者同时超过时才会自动触发文件重写。
文件同步策略:
appendfsync always----总是触发,每执行一个写操作,就会触发AOF
appendfsync everysec----每隔1秒触发一次AOF--会丢失一秒内的数据
appendfsync no----不触发AOF
2.2.2AOF优缺点
优点:数据完整性高,(最多丢失最后1秒的数据 everyesc|丢失最后一个写命令 )
缺点:数据恢复慢,而且日志文件非常大
RDB和AOF两者不能兼容
Redis启动时(恢复数据时)默认先加载AOF文件,一般在企业中使用RDB
3.集群模式
作用:解决单点故障问题
集群模式:(1)主从模式 (2)哨兵模式 (3)集群化模式(去中心化模式)
3.1主从模式
特点:1个主节点,多个从节点;主节点负责读写操作,从节点只负责读操作;当主节点执行写操作时,数据会同时同步到其他从节点上,要保证数据统一
配置主从模式,配从不配主
1.安装正常情况,3台机器(1主2从)
为了节省资源:一台虚拟机开启三个Redis服务(端口号不同)
设置允许所有ip连接
bind 0.0.0.0 -::1
关闭保护模式
protected-mode no
修改端口号port:
port 6380:master节点
port 6381.6382:slave节点
修改RDB储存文件dump.rdb名称:
dbfilename dump6380.rdb
dbfilename dump6381.rdb
dbfilename dump6382.rdb
关闭AOF持久化:
appendonly no
开启三个Redis服务:
验证:
启动客户端: redis-cli -p port
查看主从关系: info replication
配置主从关系:slaveof 主节点ip 主节点端口号(例:slaveof 127.0.0.1 6380)
测试主从模式
1.主节点负责读写操作,从节点只负责读操作,主节点写的数据同时同步到从节点
2.如果主节点宕机,从节点如何?从节点还是从节点,等待主节点重启。
3.如果增加一个新的从节点,会不会同步之前的数据?会。
3.2哨兵模式
主从模式的缺点:当主节点挂掉(老大),从节点无法承担主节点的责任(小弟无法自动上位),使用哨兵模式,小弟自动上位
原理:哨兵时时刻刻检查主节点
修改配置文件sentinel.conf
从节点当选为主节点的条件:1.哨兵投票数 2.从节点出故障的次数
启动哨兵服务
redis-sentinel sentinel.conf测试:关闭主节点(shutdown exit)
当主节点关闭后,6381和6382竞争上岗。(随机)
当原来的主节点重新启动,则会挂载到现在的主节点下成为从节点。
3.3集群化模式(去中心化模式,内置哨兵模式)
主从模式和哨兵模式,他们只有一个master主节点,如果这是写操作比较大,上面两种模式就会堵塞。这时就可以使用集群化模式。
多master和多slave
cluster模式,
实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容
。Redis-Cluster采用无中心结构,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
3.3.1集群化原理:
Redis Cluster中有一个16384长度的槽的概念,他们的编号为0、1、2、3……16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。正常工作的时候,Redis Cluster中的每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。这里值得一提的是,在Redis Cluster中,只有Master才拥有槽的所有权,如果是某个Master的slave,这个slave只负责槽的使用,但是没有所有权。
如下所示:
那么Redis集群是怎么存储的呢? 首先,在redis的每一个节点上,都有这么两个东西,一个是插槽(slot)可以理解为是一个可以存储两个数值的一个变量这个变量的取值范围是:0-16383。还有一个就是cluster我个人把这个cluster理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。 还有就是因为如果集群的话,是有好多个redis一起工作的,那么,就需要这个集群不是那么容易挂掉,所以,理论上就应该给集群中的每个节点至少一个备用的redis服务,这个备用的redis称为从节点(slave)。然后,每一个节点都存有这个集群所有主节点以及从节点的信息,它们之间通过互相的ping-pong判断是否节点可以连接上。 如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。如果某个节点和所有从节点全部挂掉,我们集群就进入faill状态。还有就是如果有一半以上的主节点宕机,那么我们集群同样进入发力了状态。这就是我们的redis的投票机制。 具体的原理图如下:
(1)、投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout)认为当前master节点挂掉. (2)、什么时候整个集群不可用(cluster_state:fail) a、如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败。 b、如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。
3.3.2配置集群化
资源不足,在一台虚拟机上开启六个redis服务充当六台虚拟机(redis服务中不能有数据)
port 7000 7001 7002--主节点
7003 7004 7005--从节点
在/usr/local/redis-7.0.2目录下创建redis-cluster,复制六个redis.conf
修改redis.conf(以7000为例)
#设置所有ipv4地址都可以访问Redis服务 bind 0.0.0.0 -::1 #关闭保护模式 允许其他服务器访问 protected-mode no #设置端口号 port 7000 #守护线程 是否开启Redis后台启动 daemonize yes #修改dump.rdb dbfilename dump7000.rdb #修改appendonly.aof || appendonly appendfilename appendonly7000.aof || appendonly no #开启集群配置 cluster-enabled yes #修改cluster-config-file cluster-config-file nodes-7000.conf #修改集群超时时间(ms) cluster-node-timeout 5000
3.3.3启动集群化模式
启动Redis服务
redis-server redis7000.conf
为6台redis配置槽以及主从关系
redis-cli --cluster create --cluster-replicas ip:port...
redis-cli --cluster create --cluster-replicas 1 192.168.223.166:7001 192.168.223.166:7002 192.168.223.166:7003 192.168.223.166:7004 192.168.223.166:7005 192.168.223.166:7006
--cluster-replicas 1 主节点最少拥有的从节点个数验证:
redis-cli -c -h 192.168.1.35 -p 7000