Redis 基础详解[非原创]

Redis

历史
  • 单机:单数据库
  • 多机:多数据库,数据库读写分离
  • 增加缓存区:优化读的效率
  • 设置多个集群(多个读写数据库作为一个集群),提高单点访问量
  • 分库分表,MySQL=>memcache
  • NoSQL(not only SQL,键值对存储,细粒度缓存,效率高,随取随用),存储高数据量,实时变化的数据。通过缓存存储数据,一定条件下再持久化。
    • 3V:海量、多样、实时
    • 3高:高并发、高可拓、高性能
Redis命令

一般返回值长度,boolean显示0-1。

string
  • select [] : 选择数据库,默认0-15
  • flushdb [] / flushall : 清除数据库
  • move [key] [db]:移除当前key
  • keys * : 查看数据库所有的key
  • set [key] [value]get [key] [value] : 使用:分隔符同样可以做到批量插入,set k1:v1 k2 v2.....
  • exists [key] : 是否存在key
  • expire [key] [time/s] : 设定自动过期
  • ttl[key] : 时间
  • type [key] : 返回键值类型
  • append [key] [string]: 追加字符串(若key不存在,自动生成key)
  • strlen [key] : 获取字符串长度
  • incr/decr [key]: 增1/减1(原子性操作)
  • incrby/decrby [key] [step]:
  • getrange [key] [start] [end]: string 读范围[start,end]
  • setrange [key] [offset] [value] : 替换指定位置开始字符串
  • setex [key] [time/s] [value] : 设置过期键值
  • setnx [key] [value] : 如果key不存在,设置键值(分布式锁)
  • mset [key] [value].... :批量添加键值
  • msetnx :批量添加键值,原子性操作(一起成功或一起失败)
  • getset [key] [value] : 先获取再设值

List:

双向链表结构。l开头表示往左插入,r开头表示往右插入.最后一个元素下标为-1,所有元素表示[0,-1]。

  • lpush/rpush [key] [value] : 加入队列
  • lpop/rpop [key] : 移除队头/队尾
  • lindex [key] [index] : 获取当前index下的值
  • llen [key] : 返回队列长度
  • lrem [key][count][value] :移除当前key下指定个数的值,精确匹配
  • ltrim [key][start][end] : 截取[start,end]的list
  • rpoplpush [source][destination] : 组合命令
  • lset [key][index][value] : 添加元素,前提是key存在
  • linsert [key][before/after][element][value] : 插入第一个遇到的元素的前面或后面,element为具体值。

set:

无序不重复,s开头

  • sadd [key][value]... : 加入集合
  • smembers [key] : 返回所有元素
  • sismember [key][value] :返回是否有该值
  • scard [key] : 返回元素个数
  • srem [key][value]... : 删除指定值
  • srandmember [key][count] : 随机选取count个元素
  • spop [key] : 随机移除元素
  • smove [source][destination][member] : 转移
  • sdiff/sunion/sinter [key] [key]... : 差集/交集/并集

Hash

map集合,更适合于对象的存储。h开头,key-value—>key-[key-value]

  • hset [key][field][value]...
  • hget [key][field]
  • hmset/hmget
  • hgetall [key] : 获得所有的key和value
  • hdel [key][field]
  • hlen [key]
  • hkeys/hvals [key]:只获取key/value
  • hincrby/hdecrby [key][field][increment]
  • …结合string都差不多。

Zset

有序集合,z开头,在set基础上加了个值用于排序。

  • zadd [key][score][value] : score提供排序优先级

  • zrangebyscore [key][min][max](withscores) : 从小到大排序

  • zrevrangebyscore [key][max][min](withscores) : 从大到小排序

  • zrevrange [key][start][stop] : 从大到小排(按元素下标)

  • zrem [key][value]

  • zcard [key] : 获取集合中元素个数

  • zcount [key][min][max] : score在[min,max]区间的元素个数

geospatial

使用 geohash 保存地理位置的坐标,使用有序集合(zset)保存地理位置的集合,适用于zset命令

  • 1、GEOADD:增加某个地理位置的坐标
  • 2、GEOPOS:获取某个地理位置的坐标
  • 3、GEODIST:获取两个地理位置的距离
  • 4、GEORADIUS:根据给定地理位置坐标获取指定范围内的地理位置集合
  • 5、GEORADIUSBYMEMBER:根据给定地理位置获取指定范围内的地理位置集合
  • 6、GEOHASH:获取某个地理位置的 geohash 值,二维的经纬度转化为一维的字符串,字符串越接近表示距离越近。
Hyperloglog

基数统计,占用内存固定,只需12KB。

  • pfadd
  • pfcount : 计数(去重)
  • pfmerge [destkey][sourcekey]... : 所有source合并为destkey
Bitmaps

位存储,位图,操作二进制位进行记录,0:1。优化了空间存储,提高效率。

  • setbit [key][offset][value]
  • bitcount [count]
介绍

Redis 是单线程的,多线程是为处理IO请求

Redis 基于内存操作,无CPU瓶颈。Redis也有事务,本质是一组命令的集合。具有一次性、顺序性、排他性。没有隔离级别的概念。

单条命令保证原子性但事务不保证原子性。

multi : 开启事务

exec : 执行事务(根据命令顺序执行)

  • 编译型异常:指令有误,所有指令都不执行。
  • 运行时异常:运行时出错,其他指令依然可正常执行。(不符合原子性)

discard : 取消事务

悲观锁

无论什么情况都会加锁

乐观锁

监视数据

watch [key]... : 充当乐观锁操作

unwatch : 解锁

误区
  1. 高性能服务器一定是多线程
  2. 多线程一定比单线程效率高
原理

Redis将所有数据全部存于内存中且无上下文切换,所有使用单线程时效率很高。

Redis配置文件
Redis持久化
RDB机制

Redis DateBase,Redis默认模式

Redis单独创建一个fork进程,负责将当前时刻的数据以快照(Snapshot)的形式持久化到磁盘中(覆盖原来的rdb文件),持久化过程中主进程不能进行任何IO操作。当要恢复时将快照文件直接读到内存即可。

保存的文件默认名称:dump.rdb

config文件:

save [interval][times] : 每隔interval时间的数据修改超过times次,就触发rdb操作,及生成dump.rdp文件

触发机制:

  • save : 自动触发rdb
  • flushall
  • shutdown :退出后自动生成rdb文件

恢复:

  • dump文件在默认目录下即可,redis启动时会自动恢复其中的数据。

优点:

  • 适合大规模数据恢复
  • 对数据完整性要求不高

缺点:

  • 它以时间间隔定期保存,一部分数据可能丢失。
  • fork进程,会占用一定内存空间
AOF机制

Append Only File

redis会将每一个收到的命令都通过write函数追加到文件中。通俗的理解就是日志记录。

config配置:

appendonly no—>appendonly yes : 开启aof,与adb同时开启时,优先启用aof(安全性更高)

appendfsync always : 每次修改都会同步,效率低

appendfsync everysec : 默认开启。每秒执行一次同步,可能丢失数据

appendfsync no :不执行同步,有操作系统执行数据同步,速度快

修复aof文件:

aof文件损坏时,redis服务将无法开启。可以使用redis-check-aof --fix appendonly.aof命令修复aof文件(删除了错误数据,只保留正确数据)。

重写:

在当前的快照保存工作结束后,开启一个子进程,将AOF文件进行重写,合并set命令等操作到一个临时文件,达到缩小文件大小的目的。重写结束后后将临时文件替换为新的AOF文件(重写过程中如果有新的redis操作命令,会提交到缓存中,重写结束后追加到AOF文件内)

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64m  #aof文件大于64mb时,fork一个新的进程将aof文件进行重写。

优点:

  • 每一次修改都同步,文件完整性、一致性好。

缺点:

  • 相对于数据文件来说,aof远大于rdb,修复速度也较慢。
  • aof 是一种 IO操作,效率要比rdb慢,
Security

requirepass 123456 : 设置密码


config set requirepass [password] : 设置密码[临时性的]

config get requirepass

auth [password] : 登录操作

订阅和发布
Redis命令
  • subscribe [channel] : 创建频道(订阅端)
  • publish [channel][massage] : 发布信息(发布端)
  • pubsub channels [pattern] : 返回当前的活跃频道
  • pubsub numsub [channel].. : 返回频道订阅数量
原理

服务器中维护着一个pubsub_channels字典,所有的频道和订阅关系都存储在这里。字典的键为频道的名称,而值为订阅频道的客户端链表。

发布端发布信息时,服务器会遍历pubsub_channels中对应键的链表,向每一个客户端发送信息。

主从复制

从机负责读,主机负责写。配置文件默认为主机

配置文件:
  • 设置从机

image-20201128160627477

  • 命令行配置:

    slaveof [host][port] : 临时性配置主从关系

    slaveof no one : 重新成为master

复制原理

Slave启动成功连接到master后,发送sync命令。Master接到命令后启动后台存盘进程,同时收集所接受到用于修改的数据集命令,在后台进程执行完毕后,master传送整个数据文件到slave,完成一次完全同步

  • 全量复制

    slave服务在接受到数据库文件数据后,将其存盘并加载到内存中。

  • 增量复制

    master继续将新的所收集到的修改命令依次传给slave,完成同步。

    只要是重新连接master,一次完全同步(全量复制)将被自动执行。

哨兵模式(sentinel)

主从切换技术,即当master宕机后,自动配置新的master ,免去了手动配置,提高高可用性。

原理:

后台监控主机是否发生故障,若发生故障则根据投票数自动将从库转化为主库。

哨兵模式作为一种特殊的模式。哨兵作为一个独立的进程,独立运行。哨兵通过发送命令,等待Redis服务器响应,从而监控多个Redis实例。

具体作用:
  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅的模式通知其他的从服务器,修改配置文件,让他们切换主机。
哨兵:

sentinel.conf

sentinel monitor [name] [host][port] 1 : 1表示设置投票机制。

通过 redis-sentinel [config] 启动哨兵(master转移需要一定时间–心跳包)

单个哨兵进程对Redis服务器监控可能会发生一些问题,这时可以设置多个哨兵进行监控,各个哨兵之间同样会进行监控,形成多哨兵模式。(简单说就是怕哨兵坏了)

具体流程

多个哨兵监视各个主机、从机。当某个哨兵认为该主服务器发生宕机时,即主观下线时,并不会马上进行failover过程,而是需要其他哨兵对该主服务器进行判断,当认定它宕机的数量达到一定值时,才认定它已宕机。此时各个哨兵将进行一次投票,投票最终结果决定新的主服务器,由一个哨兵发起该结果并进行failover故障转移操作(从机–>主机),成功后,通过发布订阅模式,让各个哨兵将各自监控的从服务器实现切换主机,即客观下线

优点
  • 基于主从配置,有它所有的优点
  • 主从可切换,故障可转移,高可用
  • 手动到自动,更加健壮
缺点
  • Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦

  • 实现哨兵模式(哨兵集群)的配置十分麻烦。

    port 26379
    daemonize yes
    logfile "26379.log"
    dir "./"
    sentinel monitor mymaster 192.168.250.132 7000 2 #必要
    sentinel down-after-milliseconds mymaster 30000
    sentinel parallel-syncs mymaster 1
    #默认转移时间
    sentinel failover-timeout mymaster 15000
    sentinel auth-pass mymaster 123
    bind 192.168.250.132 127.0.0.1
    
Redis 缓存穿透、击穿和缓存雪崩
缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。

假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。即便是采用UUID,也是很容易找到一个不存在的KEY,进行攻击。

  • 采用缓存空值。如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。
缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

  • 互斥锁
  • 设置热点key永不过期
缓存雪崩

缓存雪崩,是指在某一个时间段,缓存集中过期失效。

产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

Redis应用场景
  • 计数器

  • 统计多单位数量:关注数、浏览量等

  • 对象缓存存储

  • 消息队列,消息排队 :list

  • 共同爱好、共同好友 :set sdiff/sunion/sinter

  • 排行榜 :zset

  • 附近的人:geo

  • 计算在线用户量:hyperloglog

  • 记录打卡信息。。:bitmaps

  • 实时聊天,聊天室、订阅、关注:订阅、发布

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值