Redis笔记
发布日期:2022-09-29 16:53:46 浏览次数:2 分类:博客文章

本文共 6805 字,大约阅读时间需要 22 分钟。

redis key 命令

command use
keys * 查看当前库中key数
del key 立即删除key
unlink key 立即提示删除key,实际上是异步进行
set key value 设置键值对
type key 查看key类型
exists key key是否存在
expire key 10 设置key过期时间,单位为秒
ttl key 查看key是否过期,-1永不过期,-2已经过期

操作库命令

command use
select * *为[0~15],redis总共有16个库
dbsize 查看当前key数
flushdb 删除当前db
flushall 清除所有库

value 类型

字符串String

  • 最大512M,为2进制安全性,甚至可以保存图片或者序列化对象
  • 由于redis是单线程加上多路IO复用,所以在进行操作时是不会被打断的(不同于mameache是多线程加锁)
command use
get key 获取数据value
mget key1 key2... 获取多个数据
msetnx key1 value1 key2 value2... 插入多个键值对,有存在的就停止
mset key1 value1 key2 value2... 插入多个不存在的键值对
append value1 value+value1,返回总长
strlen key 返回长度
setnx key 只有当key不存在时可以存储,当key已经存在则返回0
incr key 给数字类型的值加一,返回加一后数据
decr key 同上,不过是减法
incrby key value 同上,不过是加上value
decrby key value 同上,不过是减法
get range key index1 index2 获取index1-index2的值
set range key index1 value 从index1开始覆盖值
setex key time value 设置值的时候同时设置过期时间
getset key valuenew 返回旧值同时更新新值

列表List

  • 单键多值,按照插入顺序排序可以添加元素到头尾,实际上是一个双向链表,头尾操作较快,通过下标操作中间性能会较差
  • 元素较少时使用ziplist,分配的是连续内存,元素较多时则使用quicklist,即多个ziplist使用双向指针链接
command use
lpush/rpush k1 v1 k2 v2 从左或右插入一个或者多个值
lpop/rpop k 从左或右吐出一个值,值在键在
rpoplpush k1 k2 从k1列表右边吐出值加到K2左边
lrange k start stop 从k1开始获取从start到stop下标的值
lindex key index 按照索引下标获取元素(从左到右)
llen key 获取长度
linsert key before/after value newvalue 在value后面插入新值
lrem key num value 删除num个value
lset key index value 替换index的值为value

集合set

  • 类似list,区别是可以自动查重

  • 实际是string类型的无序集合,底层为value为null的hash表,可以添加,删除,查找,复杂度都是O(1)

    command use
    sadd k1 v1 v2 v3 v1v2v3加入k1 ,重复value会被忽略
    smembers k1 取出所有值
    sismember k1 v1 判断v1是否为k1的值
    scard k1 返回个数
    srem k1 v1 v2... 删除元素
    spop k1 随机取一个元素
    srandmember k1 n 随机取n个值,但是不会从集合删除
    smove k1 k2 v1 k1的v1移到v2
    sinter k1 k2 返回交集
    sunion k1 k2 返回并集
    sdiff k1 k2 返回差集 k1中不在k2中的元素

哈希Hash

  • string类型的field 和value映射表,特别适合用于存储对象

    command use
    hset k1 f1 v1 设置k1中f1的值为v1
    hget k1 f1 获取f1值
    hmset k1 f1 v1 f2 v2 ... 批量设置v
    hexists k1 f1 看f1是否存在
    hkeys k1 看k1中的field
    hvals k1 看k1中的val
    hincrby k1 f1 incnum f1的值增加incnum
    hsetnx k1 f1 v1 当f1不存在时,增加f1和v1

有序列表Zset(sored set)

  • 类似于set,但是每个成员都关联了一个评分score ,用于从最低到最高评分排序,成员不可以重复,但是评分可以
  • 可以使用score或者position获取一个范围的元素
  • 可以用作一个没有重复成员的智能列表
command use
zadd k1 s1 v1 s2 v2 将一个或者多个member元素及其score加入到有序集key中
zrange k1 start stop [WITHSCORES] 返回有序集k1中下标在start stop之间的元素,加上[WITHSCORES]还可以返回分数
zrevrangebyscore k1 minmax 按分数从小到大排序.
zrevrangebyscore k2 maxmin 同上,按从大到小排序
zincrby k1 incnum v 为score加上增量
zrem k1 v 移除v
zcount k1 min max 统计k1中分数区间的数据
zrank k1 v 返回值在集合中的排名

实现一个文件访问量排序

zadd topR 1000 v1 2000 v2 3000 v3 4000 v4zincby topR 1234 v2

发布订阅

pub>>>channel>>>>sub

  • 只要订阅了频道就可以收到消息,一个客户端订阅的频道可以任意多
subscribe chan1publish chan1 hello//可以看到订阅的客户端有接受消息

Redis新数据类型

Bitmaps

  • 可以想象成一个以位为单位的数组,每个单元都只能存放0和1,数组的下标在Bitmaps里叫偏移量
  • 活跃用户量很大,可以节约使用空间
command use
setbit k1 o1 v1 设置位图中某个偏移量的值为0或者1,offset 从0 开始
getbit k1 o1 同上,获取偏移值
bitcount k1 [start end] 统计置1数,如果设置了start和end ,则统计两者之间字节的位的置1数目
bitop and/or/nor/xor resultkey k1,k2,... 位操作,可以用来做多个位图的操作

Hyperloglog

  • 使用有限的空间做基数统计算法,优点是输入元素的数量或者体积很大时,使用的空间是一定的,很小的,缺点是会丢失一定精度
  • 一个hyperloglog一般只占用12KB,但是只能计算基数并不能存储
command use
pfadd k1 v1... 累计不重复数据,成功返回1,否则返回0
pfcount k1 统计返回基数近似值
pfmerge dest source1 source2... 将一个或者多个HLL合并的结果存到另一个HLL中

Geospatial

  • 用来表示坐标,元素的二维坐标,地图上是经纬度
  • 提供了经纬度查询,设置,范围查询,经纬度Hash等操作
command use
geoadd key longitude latitude member 添加经纬度
geopos key member 获取坐标
geodist key mem1 mem2 获取两个位置的直线距离
georadius key long1 lati1 meter 查询以(long1,lati1)为中心,meter为半径的事物
geoadd china:city 100.10 15.10 xxx 20.00 30.00 YYY

事务和锁机制

事物

是一个单独隔离的操作,事务中所有的操作都会序列化,按顺序进行,不会被打断 。

Multi,Exec,discard

  • Multi:使命令组队进入队列
  • Exec:顺序执行队列中的命令
  • discard:取消执行

错误处理

  • 命令组队时出错则队列取消,不可运行
  • 执行中出错则只有该命令不执行

事务冲突问题

悲观锁

操作之前先上锁,操作完解锁,传统数据库里有行锁,表锁,读锁,写锁等

乐观锁

操作前记录版本号,操作时更新版本号,保存时如果和当前版本号不同则不能保存操作,使用于多读的应用

watch key

执行multi之前先执行watch key,监视多个key是否被改动,如果被改动,则事务锁被打断

unwatch

取消监视key

Redis持久化

RDB(redis database)

原理

在指定时间间隔内将内存中的数据集快照写入磁盘中,恢复时就是将快照文件直接读到内存中。

会单独创建一个子进程用于备份数据到临时文件夹,直到持久化过程结束,用临时文件替换上一次持久化好的文件,主进程不进行IO操作,确保了极高的性能,适用于大规模数据且数据不敏感的恢复,缺点是可能丢失最后一次持久化后的数据。(每次保存一定量的数据,超出的部分则计入下一次持久化)

dump.rdb

在启动redis时会生成该文件

bgsave命令

可以实现自动异步保存

AOF(append of file)

原理

以日志的形式记录写操作(包括增量),将所有执行过的命令都记录下来,只能追加文件,不能改写文件,redis启动的时候会读取该文件重新构建数据,也就是重新执行一次命令。

流程

将客户端写操作存入aof缓存区,在appendfsnc的控制下进行写文件,当到达一定条件开始重写文件,即压缩命令,重启的时候会读取文件执行。

appendonly.aof

和RDB保存的路径一致

都开启时,首先使用aof

备份恢复和RDB一样

使用redis-check-aof --fix 修复aof文件

appendfsnc 同步频率设置

  • always:每次写操作都记录
  • everyesc: 每秒记录一次
  • no:由操作系统控制记录时间

rewrite

用于压缩命令,减小文件体积(一般是64M,且大于100%(即128M)才触发重写机制)

选择

官方推荐都使用

对数据敏感,使用RDB
不建议单独使用AOF,会有BUG
只是做内存缓存,则可以都不用

主从复制

原理

应用的写操作会在主服务器进行,主服务器进行完操作后会复制到从服务器上,应用的读操作因为不改变数据,所以可以从 从服务器中读取数据,这样可以实现读写分离,分担压力。

搭建一主多从

include /redis/redis.confpidfile /var/run/redis_6380.pidport 6380dbfilename dump6380.rdb

在从机上执行slaveof命令,设置host和port号,就可以实现了

复制原理和一主二仆

从服务器挂掉了,重启时会是主服务器,需要重新使用slaveof命令设置,重连上后会复制主服务器数据。

主服务器挂掉后,从服务器不会篡位,会一直等主服务器重启为止。

  • 连接上主服务器后会发送消息,同步数据
  • 主服务器收到消息后,会持久化生成RDB文件并把RDB发送到从服务器,从接收到后从RDB文件读取数据

薪火相传和反客为主

薪火相传:从服务器下可以挂载从服务器

反客为主:主挂了,从可以执行slaveof no one命令变成主机

哨兵模式

反客为主的自动版,从库派出一个哨兵监视主机,主机挂掉后,立刻反客为主

  • 在配置文件夹里设置一个sentinel.conf文件,填写命令sentinel monitor mymaster 127.0.0.1 6379 1 其中1是指多少个哨兵愿意迁移的数量
  • redis-sentinel sentinel.conf启动哨兵

配置文件中有priority项,该项值默认100,越小当选主机优先级就越高,如果相同则比较数据,谁最新选谁,如果还是相同则比较runid,越小则优先级越高(每个redis实力都会生成一个40位的runid)

集群

原理

无中心化集群,任何一台主服务器都可以作为入口,并且都可以转发请求,他们是互相联通的。

搭建

一个集群至少有3个节点,尽量保证每个主库运行在不同IP,每个从库和主库不在同一个IP

配置文件

include /redis/redis.confpidfile /var/run/redis_6379.pidport 6379dbfilename dump6379.rdbcluster-enabled yescluster-node-timeout 15000cluster-config-file nodes-6379.conf

设置集群命令

redis-cli --cluster create --cluster-replicas 1 ip1:port ip2:port ip3:port ip4:port ip5:port ip6:port...

其中 1 代表最简单的集群模式

链接到集群

redis-cli -c -p port

操作和故障恢复

cluster nodes //查看节点

每个集群有16384个插槽slots,主机平分插槽,集群使用CRC16(key)平均分到对应的插槽

如果是插入多个值需要使用{}

mset k1{u1} v1 k2{u1} v2 k3{u1} v3
cluster keyslot k1 //查询key的插槽cluster countkeysinslot slot //计算这个插槽里有几个键(但是只能获取自己被分配的插槽的值,其他主机被分配的插槽不可以被获取)cluster getkeysinslot  slotnum count//返回插槽slotnum里的count个key

挂掉的主机再恢复会成为从机

根据配置中的cluster-require-full-coverage来判断主从都宕机情况,为yes则整个集群都挂掉,为no则分配的插槽的数据不可使用和存储。

应用问题

缓存穿透

应用服务器压力增大,在redis中查不到数据,只能不停查找数据库,数据库最终崩溃了。

原因:redis查询不到数据库,出现了很多非正常url访问

解决方案:

  • 对空值缓存:就算查不到也存到redis,但是要设置过期时间。
  • 设置可访问的白名单:使用bitmaps定义一个白名单
  • 采用布隆过滤器:
  • 实时监控:当redis命中率极速下降时,设置黑名单

缓存击穿

数据库访问压力瞬时增加,redis中的没有出现key大量过期,但是还是正常访问

原因:某个key过期了,大量访问中用到这个key,没法命中,只能把压力给数据库

解决方案:

  • 预先设置热门数据:提前设置热门数据,并延长过期时间
  • 现场监控:查看key的热值并随时延长时间
  • 使用锁:

缓存雪崩

数据库压力变大,导致服务器崩溃

原因:极少时间内,查询大量key的集中过期

解决方案:

  • 多级缓存架构:nginx缓存+redis缓存+其他缓存等
  • 使锁或者队列:不能大量访问同时查询一个key
  • 设置过期标志更新缓存:设置提前量记录缓存数据是否过期,如果过期会触发通知另外的线程去后台更新缓存。
  • 将缓存时间分开:设置一个随机值增加到失效时间上,这样重复率就会下降,很难引起集体失效。

分布式锁:设置锁和过期时间

设置分布式锁的三种方案:

  • 基于数据库
  • 基于缓存redis:性能最高
  • 基于zookeeper:可靠性最高

redis分布式锁:

使用setnx设置锁,del释放锁

要设置过期时间,最好同时设置

set key value nx ex 10 //nx 上锁 ex 过期时间,单位为S

分布式锁:UUID防止误删

set lock uuid nx ex 10//释放锁之前判断锁的uuid是谁,如果不是自己的,就不操作释放

分布式锁:LUA保证删除原子性

删除锁前,锁过期了,自动释放,很可能误删锁。

分布式锁的实现要求

  • 互斥:同一时间只有一个客户端可以持有锁。
  • 不会死锁:即使有个客户端崩溃了,没有主动释放锁, 也能保障后续加锁。
  • 设置和开锁必须是同一个。
  • 加锁和解锁必须有原子性。

转载地址:https://www.cnblogs.com/eddiez/p/15335285.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Redis笔记
下一篇:Redis笔记

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年03月25日 23时11分58秒