1、数据类型
- string
增删改查
- set key value
- get key
- del k
- strlen k
加减
- incr article
- incrby article 3
- decr article
- decyby article
取v中特定位置数据
- getrange name 0 -1
- getrange name 0 1
- setrange name 0 x
设置过期时间
- setex pro 10 华为
等价于
- set pro 华为
- expire pro 10
在分布式系统里面可以使用如下命令实现分布式锁
- setnx(set if not exist)
- 如果返回1:设置成功
- 如果返回0:设置失败
- List 有序、可重复
存
- lpush num 1 2 3 4 5
- rpush num2 1 2 3 4 5
弹出(获取数据的同时将数据从list中删除)
- lpop
- rpop
查
- lrange num 0 -1
- lrange num2 0 -1
根据下标获取元素
- LINDEX key index
大小
- LLEN key
队列:先进先出
- lpush num3 1 2 3 #左边推进去
- rpop num3 1 #右边取出来
- 或者
- rpush num4 1 2 3
- lpop num4
栈:先进后出
- lpush num5 1 2 3
- lpop num5
- 或者
- rpush num6 1 2 3
- rpop num6
- #list的长度
- llen num5
- set无序,不可重复
存
- sadd ips '192.168.22.1' '192.168.22.2' '192.168.22.2'
查
- smembers ips
查看某个元素在集合中是否存在
- SISMEMBER key member
删
- srem ips '192.168.22.1'
大小
- scard ips #获取set的长度
随机
- sadd nums 3 4 5 0 9 8 9 0 8 6
- srandmember nums 3
随机并移除
- spop rands 3
交集
- redis 127.0.0.1:6379> SADD myset "hello"
- (integer) 1
- redis 127.0.0.1:6379> SADD myset "foo"
- (integer) 1
- redis 127.0.0.1:6379> SADD myset "bar"
- (integer)
- redis 127.0.0.1:6379> SADD myset2 "hello"
- (integer) 1
- redis 127.0.0.1:6379> SADD myset2 "world"
- (integer) 1
- redis 127.0.0.1:6379> SINTER myset myset2
- 1) "hello"
并集
- redis> SADD key1 "a"
- (integer) 1
- redis> SADD key1 "b"
- (integer) 1
- redis> SADD key1 "c"
- (integer) 1
- redis> SADD key2 "c"
- (integer) 1
- redis> SADD key2 "d"
- (integer) 1
- redis> SADD key2 "e"
- (integer) 1
- redis> SUNION key1 key2
- 1) "a"
- 2) "c"
- 3) "b"
- 4) "e"
- 5) "d"
- Hash:hash的key不能重复,如果重复就覆盖
存
- hset person name 'jack'
- hset person age 40
取
- hget person name
- hget person age
存多个
- hmset person name 'rose' age 12
大小
- hlen person
判断k是否存在
- hexists person age
hkeys person
hvals personperson "{'name':'zhangsan'}" string
name jack
age 12person:hash()
#hash可以大大减少redis中的K 同时hash结构特别适合存放对象
person :
name 'jack'
age '18'
hget person age
- Zset:有序,不可重复,通过score来进行排序,score必须是数字
通过score进行排序
zadd hot 300 '华为met10' 10 '苹果10' 19 '小米'
zrange hot 0 -1
zrevrange hot 0 -1#分数范围过滤
zrangebyscore hot 11 100
zrangebyscore hot 10 100 limit 0 1
#删除
zrem hot '小米'
zcard hot #查看集合的元素个数
.3、redis事务
- mutli #开启事务
- exec #提交事务
- discard #回滚事务
3.1、redis事物不是原子性
因为,有一条命令执行失败,之前的命令不会回滚,其他命令仍然继续执行。
redis所有命令都会顺序执行,事物执行过程中不会被其他客户端的命令打断
3.2、redis为什么不支持事物回滚
redis 只会因为语法错误而失败,如果这些错误不会在入队的时候发现,说明时程序错误造成的
不需要对回滚进行支持,所以redis才非常的快
1.4、持久化
RDB
Redis会单独fork一个子进程进行持久化工作,该子进程先将数据写入一个临时文件,等待持久化完毕,再将临时文件覆盖替换上此持久化好的文件,整个过程主进程是不会进行任何的IO操作,确保了极高的性能,而且当进行大规模数据恢复的时候RDB性能也非常高. 但是RDB有缺点,没法保证数据不丢失
触发方式:
自动触发
- 如900秒有1个被改变
- save 900 1
- save 300 10
- save 60 10000
手动触发
1.正常关闭redis-server(shutdown,flushdb手动)
2.save该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。 显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷。
3.bgsave 执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
AOF:
- 以日志的形式记录每个写操作(命令),当redis重启时,加载aof文件,将修改命令执行一遍。
AOF重写
将命令压缩由于AOF持久化是Redis不断将写命令记录到 AOF 文件中,随着Redis不断的进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命令 bgrewriteaof 来重新。
1.5、redis内存满了怎么解决
加服务器。
通过配置文件修改配置
1.6、内存淘汰
实际上Redis定义了几种策略用来处理这种情况:
-
noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)
-
allkeys-lru:从所有key中使用LRU算法进行淘汰,LRU(Least Recently Used)
-
volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰,LRU(Least Recently Used)
-
allkeys-random:从所有key中随机淘汰数据
-
volatile-random:从设置了过期时间的key中随机淘汰
-
volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰
1.7、为什么删除数据后,Redis内存占用依然很高?
- 内存碎片
1.8、为什么会出现内存碎片
Redis
提供了多种的内存分配策略,比如libc
、jemalloc
、tcmalloc
,默认使用jemalloc
。
jemalloc
这种分配策略并不是按需分配,而是固定大小分配,比如8字节、32字节....2KB、4KB等
1.9、如何判断存在内存碎片?
INFO memory
1.10、如何清理内存碎片?
Redis提供了参数配置,可以控制清除内存碎片的时机,命令
1.11、缓存击穿
某一个
热点key,在失效的一瞬间
,持续的高并发访问击破缓存
直接访问数据库,导致数据库造的周期性压力(极端情况下导致数据库宕机)
解决:
- 布隆过滤器的基本原理是利用多个哈希函数和一个位数组来表示一个集合。当元素被加入到集合中时,通过多个哈希函数将其映射到位数组中的多个位置,并将这些位置的位设置为1。当查询一个元素是否存在于集合中时,同样使用多个哈希函数计算其哈希值,并检查对应的位数组位置是否都为1,如果有任何一个位置为0,则可以确定该元素一定不在集合中;如果所有位置都为1,则该元素可能存在于集合中。
- 加锁:确保只有一个请求能够访问数据库加载数据,其他请求等待加载完成后直接从缓存获取数据。
- 热点数据永不过期
- 热点数据预热
1.12、缓存穿透
- 非法访问、数据库并不存在需要查找的数据,缓存也无法命中,请求都会到数据库,从而可能压垮数据源
解决:布隆
1.13、缓存雪崩
- Redis中大量的key几乎同时过期,然后大量并发查询穿过redis击打到底层数据库上,此时数据库层的负载压力会骤增,我们称这种现象为"缓存雪崩"
解决方案
-
在可接受的时间范围内随机设置key的过期时间,分散key的过期时间,以防止大量的key在同一时刻过期;
-
延长热点key的过期时间或者设置永不过期,这一点和缓存击穿中的方案一样
1.14、缓存预热
- 当系统上线时,缓存内还没有数据,直接提供给用户使用,每个请求都会穿过缓存去访问底层数据库,如果并发大的话,很有可能在上线当天就会宕机,因此我们需要在上线前先将数据库内的热点数据缓存至Redis内再提供出去使用,这种操作就成为"缓存预热"。
解决:
- 缓存预热的实现方式有很多,比较通用的方式是写个批任务,在启动项目时或定时去触发将底层数据库内的热点数据加载到缓存内。
1.15、缓存更新/缓存同步
- 缓存同步是指确保多个缓存副本之间的数据保持一致的过程。在分布式系统中,通常会部署多个缓存副本以提高系统的性能和可用性,但是这样就会引入缓存之间的数据一致性问题。缓存同步的目的是确保不同缓存副本中的数据保持同步,
解决:
- 数据双写一致性:当写入数据时,同时更新数据库和缓存,保持数据的一致性。这种方式可以确保缓存数据与数据库数据同步,但会增加写入操作的耗时和复杂度。
1.16、缓存降级
- Redis服务不可用,或者网络抖动,导致服务不稳定
解决
- 使用熔断降级策略进行服务熔断降级
1.17、Redis6的新特性
- 多线程
- 访问控制权限功能
1.18、布隆过滤器
查:通过hash计算得到对应位置,如果当前位置由数据则代表数据存在
插入:通过hash计算得到对应位置,将当前位置改为1.布隆过滤器直有0和1
优点,由二进制组成占用空间非常小查询非常快,保密性好只有0和1
1.19、集群
单节点访问压力大,单节点故障导致程序不可用
一主两从
采用一组2从,主节点负责写,从节点负责读,且要实现主从同步,主节点写后从节点也有相同数据
哨兵:
- 监控:Sentinel 会不断地定期检查你的主服务器和从服务器是否运作正常。
- 提醒: 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移: 当主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作,选举新主
- 哨兵:是整个集群的入口
- (通过哨兵投票选出主节点,哨兵一定十奇数,2n+1)
分布式集群
会有16384个hash,根据分布式的集群个数分配如下图,将set进来的数进行hash算出对应的区间进行存储,get一样算处对应区间获取相应值