Window下安装Redis
下载地址:https://github.com/tporadowski/redis/releases
redis-cli.exe 是redis客户端
redis-server.exe 是启动服务
Redis 官网:https://redis.io/
中文官网: http://www.redis.cn/
推荐视频链接: https://www.bilibili.com/video/BV1S54y1R7SB/?p=36
redis的基础知识:
redis是单线程,基于内存操作的,cpu不是redis性能瓶颈,cpu是多线程的性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽实现的。
redis默认有16个数据库,默认使用的是第0个。可以使用select进行切换数据库。
redis为什么单线程还这么快?
1.误区1:高性能的服务器一定是多线程的?。
2.误区2: 多线程(cpu上下文会切换)一定比单线程效率高
速度:cpu>内存>硬盘
核心:redis是将所有的数据全部放到内存中,所以说使用单线程去操作效率就是最高的,多线程(cpu上下文会切换:耗时的操作),,对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个cpu上的,在内存情况下,这个就是最佳的方案!
Redis五大基本数据类型
redis基本数据类型:String,list,set,zest,hash。
特殊数据类型:
HyperLogLog:用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
Geo:Redis 的 GEO 是 3.2 版本的新特性。这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作。
Pub/Sub: 发布订阅
常用key:Redis-Key
keys * # 查看所有的Key
set key value # set key
EXISTS name # 判断当前的key是否存在
move name 1 # 移除当前的key
EXPIRE name 10 # 设置key的过期时间 单位是秒 执行前要确认key存在不存在
ttl name # 查看当前key的剩余过期时间
type name # 查看当前key的类型
String
############################################
redis 127.0.0.1:6379> set name "zhangsan" #向redis写入一个键值对
OK
redis 127.0.0.1:6379> get name #通过键获取值
"zhangsan"
redis 127.0.0.1:6379> exists name #判断当前这个key存在不存在
(integer) 1
redis 127.0.0.1:6379> append name "hello" #向当前key追加字符串,如果当前key不存在就新建key
(integer) 13
redis 127.0.0.1:6379> get name
"zhangsanhello"
redis 127.0.0.1:6379> strlen name #获取key的长度
(integer) 13
redis 127.0.0.1:6379>
############################################
步长
redis 127.0.0.1:6379> incr count #自增1
(integer) 1
redis 127.0.0.1:6379> decr count #自减1
(integer) 0
redis 127.0.0.1:6379> incrby count 10 #指定增量
(integer) 10
redis 127.0.0.1:6379> decrby count 5 #指定减量
(integer) 5
############################################
字符串范围
redis 127.0.0.1:6379> set key1 "hello,nihao" #设备Key1的值
OK
redis 127.0.0.1:6379> getrange key1 0 3 #获取从开始到结束范围的字符串[0-3]
"hell"
redis 127.0.0.1:6379> getrange key1 0 -1 #结束值为-1,获取全部的字符串
"hello,nihao"
#替换
redis 127.0.0.1:6379> set key2 abcde
OK
redis 127.0.0.1:6379> setrange key2 0 xxa #替换指定位置开始的数据
(integer) 3
redis 127.0.0.1:6379> get key2
"xxade"
############################################
#setex 设置过期时间
#setnx 不存在key才会设置(分布锁会使用到)
redis 127.0.0.1:6379> setex key3 30 "hello" #设置key30秒过期
OK
redis 127.0.0.1:6379> ttl key3 #查看Key剩余过期时间
(integer) 24
redis 127.0.0.1:6379> setnx mykey "redis" #设置key
(integer) 1
redis 127.0.0.1:6379> ttl key3 #之前设置30秒的key已过期 -1 代表键没有设置过期时间,-2 代表键不存在。
(integer) -2
redis 127.0.0.1:6379> setnx mykey "mongodb" #因为key-mykey存在,所以设置不成功
(integer) 0
redis 127.0.0.1:6379> get mykey #get key校验
"redis"
redis 127.0.0.1:6379> mset k1 k2 v1 v2 x3 x3 #一次性设置多个Key,value
OK
redis 127.0.0.1:6379> mget ke v1 x3
1) (nil)
2) "v2"
3) "x3"
redis 127.0.0.1:6379> msetnx k1 v1 k4 x2 #msetnx 是一个原子性操作,要么一起成功,要么一起失败
(integer) 0
############################################
# 对象
redis 127.0.0.1:6379> mset user:1:name "zhangsan" user:1:age 2
OK
redis 127.0.0.1:6379> mget user:1:name user:1:2
1) "zhangsan"
2) (nil)
############################################
# getset #先get再set值
redis 127.0.0.1:6379> getset db redis #如果不存在值,返回nil,然后设置值
(nil)
redis 127.0.0.1:6379> get db
"redis"
redis 127.0.0.1:6379> getset db mongdb #如果存在值,获取原来的值,并设置新的值
"redis"
redis 127.0.0.1:6379> get db
"mongdb"
List
Set
Hash
Zset
Redis是怎么持久化的?服务主从数据怎么交互的?
原文链接:https://aobing.blog.csdn.net/article/details/102841400
RDB做镜像全量持久化,AOF是做增量持久化。因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在redis实列重启时,会使用RDB实施重启时,会使用RDB持久化文件重新构建内存,再使用AOF重新放近期的操作指令来实现完整回复重启之前的状态。
解释:把RDB理解为一整个表全量的数据,AOF理解为每次操作的日志就好了,服务器重启的时候先把表的数据全部搞进去,但是他可能不完整,你再回放一下日志,数据不就完整了,不过redis本身的机制是AOF持久化开启且存在AOF文件时,优先加载AOF文件;AOF关闭或者AOF文件不存在时,加载RDB时,加载RDB文件;加载AOF/RDB文件城后,redis启动成功;AOF/RDB文件存在错误时,redis启动失败并打印错误信息。
如果突然机器掉电会怎样?
取决于AOF日志sync属性的的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s一次,这个时候最多就丢失1s的数据。
RDB的原理
fork和cow。fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
Redis的同步机制
bgsave命令:redis进程执行fork(分叉)操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。
bgsave流程说明(bgsave是主流的触发RDB持久化操作.):
1) 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如只RDB/AOF子进程,如果存在bgsave命令直接返回。
2) 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork以操作的耗时,单位为微秒。
3) 父进程仍fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
4) 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成尺RDB的时间,对应info统计的rdb_last_save_time选项。
5) 进程发送信号给父进程衣示完成,父进程更新统计信息,具体见info Persistence下的rdb_*相关选项。
redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存缓冲,待完成将RDB文件全量同步到复制节点,复制节点接受完成后RDB镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
Redis集群,集群的高可用怎么保证,集群的原理是什么
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
缓存穿透、缓存击穿、缓存雪崩
参考链接:https://blog.csdn.net/kongtiao5/article/details/82771694
Redis的过期策略和内存淘汰机制
redis过期策略采用的是定期删除+惰性删除。过期策略= 定期删除+惰性删除。
定期删除:redis默认每隔100ms就随机抽取了一些设置了过期时间的key,检查其是否过期,如果有过期就删除。注意这里是随机抽取的,为什么哟啊随机呢,你想一想加入redis存了几十万个key,没隔100ms就遍历所有的设置过期时间的key的话,就会给cpu带来很大的负载。
惰性删除:定期删除可能导致很多过期的Key到了时间没有被删除掉。这时就要使用惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且过期了就删除。
定期删除+惰性删除存在的问题:
如果定期删除没删除key,然后你也没即时去请求key,也就是说惰性删除也没生效。这时,如果大量过期的key堆积在内存中,redis的内存会越来越高,导致redis的内存块耗尽。那么就应该采用内存淘汰机制。
内存淘汰机制
一、内存数据淘汰策略的配置:在redis.conf中有一行配置:
1 |
|
二、配置解释
1、noeviction:当内存不足以容纳新写入数据时,不进行移除,新写入操作会报错。应该没人用吧。
2、allkeys-lru:当内存不足以容纳新写入数据时,在所有的键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。
3、allkeys-random:当内存不足以容纳新写入数据时,在所有的键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。
4、volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐。
5、volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐。
6、volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除即将过期的key进行淘汰,即更早过期时间的key优先移除。不推荐。
ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
参考redis链接:https://blog.csdn.net/yuanlong122716/article/details/104420880