侧边栏壁纸
博主头像
潘文波的小破站

行动起来,活在当下

  • 累计撰写 6 篇文章
  • 累计创建 8 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Redis简单入门

潘文波
2022-12-08 / 0 评论 / 2 点赞 / 530 阅读 / 0 字

Redis的几种使用场景

  1. 缓存系统
  2. 计数器
  3. 社交
  4. 消息队列
  5. 排行榜
  6. 实时系统

Redis的几种启动方式

  1. 简单启动:redis-server 使用redis默认配置启动
  2. 动态参数启动:redis-server options,使用动态参数,如:redis-server --port 6380
  3. 使用配置文件启动:redis-server <config path>,如:redis-server /var/configs/6381.conf

Redis的几种数据结构

  • 字符串 string
  • 哈希 hash
  • 列表 list
  • 集合 set
  • 有序集合 zset

常用的通用命令

  • keys 列出key,支持正则

生产环境中不宜滥用,该命令会执行全局扫描,因为redis是单线程的,容易造成阻塞影响性能。可以使用后面的 scan 命令来代替,如果生产环境是集群的话,可以在从节点上执行 keys 这类重量级命令。

  • dbsize 数据库中 key 的个数

这个命令不会执行全局扫描,使用的是Redis内置的全局计数器

  • exists 判断数据库中是否含有指定key
  • del 删除一个或多个key
  • expire key <seconds> 设置key的过期时间
  • ttl 查看key剩余的过期时间
  • persist 去掉key的过期时间
  • type key 查看key的数据类型

数据结构内部编码

image

因为Redis是单线程的,一次只能执行一个命令,如果指令执行时间过长,后续命令只能等待,所以线上生产环境要避免执行长命令,长命令有:
keys flushall flushdb slow lua script mutil/exec operate big value(collection)

数据详细结构

字符串 String

数据类型可以是字符串也可以是整形

场景

  • 缓存
  • 计数器
  • 分布式锁

常用命令

  • get key
  • set key value
  • setnx key valueset key value nx key不存在时设置值
  • set key value xx key存在时设置值
  • set key value ex seconds 设置key值并设置过期时间(有没有该key都可以)
  • del key 删除key

整形操作:

  • mget key1 key2... 批量获取一个或多个key的值
  • mset key1 value1 key2 value2... 批量设置一个或多个key-value对(原子操作)
  • getset key new-value 对key设置新值并返回旧值
  • append key value 将value追加到key值中
  • strlen key 获取字符串的字节长度(中文字符占两个字节)‘
  • incrby key k 自增k(整数),没有递减指令,但是可以通过传递负数实现递减
  • incrbyfloat key k 自增k(小数),没有递减指令,但是可以通过传递负数实现递减
  • getrange start end 获取字符串的范围,如果超出不会报错,返回空字符串
  • setrange key index value 从指定索引开始设置新值

哈希 Hash

存储方式为 key field value

常用命令

hash的命令都是以 h 开头的

  • hget key field
  • hgetall key
  • hset key field value 如:hset user:1:info name john
  • hdel key field 如:hdel user:1:info name
  • hexists key field 判断是否存在field
  • hlen key 获取字段个数
  • hmset key field1 value1 field2 value2... 批量设置多个属性(原子操作)
  • hmget key field1 field2... 批量获取key中的多个属性
  • hkeys key 获取key中的所有属性key
  • hvals key 获取key中所有属性的value
  • hsetnx key field value 当field不存在时,设置新值
  • hincrby key field k 字段值自增k
  • hincrbyfloat key field k 字段自增k(小数)

列表 List

数据结构:
image

列表是一个有序可重复集合

常用命令

list的命令都是以 l 开头的

  • lpush key value1 value2... 从左边一次插入多个值
  • rpush key value1 value2... 从右边一次插入多个值
  • linsert key before|after item value 在指定元素前|后插入value
  • lpop key 从左边移除一个元素
  • rpop key 从右边移除一个元素
  • lrem keys count item 移除和item相同的元素,当count大于0时,从左到右删除;当count等于0时,删除所有;当count小于0时,从右到左删除。
  • ltrim key start end 对列表进行裁剪,保留索引为start到end之间的元素
  • lrange key start end 查询索引为start和end之间的元素(包含start和end,索引大于等于0为从左到右,如果小于等于-1,则是从右到左。所以如果查询所有所有元素可以简写为 lrange key 0 -1)
  • lindex key index 获取索引为index的元素
  • llen key 获取列表长度
  • lset key index new-value 将指定索引位置的元素替换为新值
  • blpop key timeout 以阻塞的方式从左端弹出元素,如果列表中有元素的话,立刻弹出;如果没有元素则等待;超市时间如果为0则表示一直等待。
  • brpop key timeoutblpop,方向相反

集合 Set

无序不重复的元素集合,而且支持集合间操作

常用命令

命令都是以 s 开头

集合内操作
  • sadd key value1 value2... 向集合中添加一个或多个元素,如果集合中已存在要添加的元素,则添加不成功
  • srem key item 删除集合中的item
  • scard key 获取集合中元素数量
  • sismember key item 判断元素是否存在于集合中
  • srandmember key [count] 随机获取集合中count个元素,默认为1
  • spop key 从集合中随机弹出一个元素(该元素将从集合中删除)
  • smembers key 获取集合中所有元素(无序的)
集合间操作
  • sinter key1 key2... 计算集合间的交集
  • sdiff key1 key2... 计算集合间的差集
  • sunion key1 key2... 计算集合间的并集

集合间的操作命令加上 store 就是将操作结果存储到指定key中:

  • sinterstore dest-key key1 key2... 计算集合间的交集并将结果存储到 dest-key 中
  • sdiffstore dest-key key1 key2... 同上
  • sunion dest-key key1 key2... 同上

有序集合 ZSet

有序集合相对于无序集合的差异:
image

常用命令

ZSet的命令都是以 z 开头

  • zadd key score1 item1 score2 item2... 添加元素
  • zrem key item1 item2... 删除元素
  • zscore key item 获取元素的分数
  • zincrby key k item 元素的分数加k,如果元素不存在,则是0+k
  • zcard key 获取集合中的元素个数
  • zrank key item 获取item的排名(从小到大)
  • zrange key start end [withscores] 获取指定范围的元素
  • zrevrange key start end [withscores] 反向排序获取指定范围的元素
  • zrangebyscore key min max [withscores] 获取指定分数范围内的元素
  • zrevrangebyscore key max min [withscores] 反向获取指定分数范围内的元素
  • zcount key min max 获取指定分数范围内的元素个数
  • zremrangebyscore key min max 按照分值范围删除元素
  • zremrangebyrank key start end 按照排名范围删除元素

集合间的操作同样适用于zset,但是需要指定key的个数:

  • zinter num-key key1 key2... num-key 是指后面集合的个数
  • zdiff num-key key1 key2... 同上
  • zunion num-key key1 key2... 同上

zset的集合间操作同样也支持添加 store 修饰符用于持久化,zset 的集合间操作 不会比较分数,得到的结果的分值会被相加。

慢查询

生命周期

一个指令执行可分为4个阶段:发送指令 -> 排队 -> 执行命令 -> 返回结果
image
其中慢查询发生在 执行命令 阶段

客户端超时不一定是慢查询引起的,但是慢查询是客户端超时的一个kennel因素

pipeline

如果分批次执行n个命令,就会消耗n次网络时间;可以使用 pipeline 来通过一次网络请求,执行多个命令,进而减少网络时间的消耗。
pipeline 和带有 m 的批量操作命令是有本质区别的:
pipeline 是将多个命令打包一次发送到服务器,在服务端重新拆包等待执行,执行之后再打包返回客户端,所以 pipeline 不是原子操作。带有 m 端批量操作指令是原子性的

注意事项:

  1. 注意每次 pipeline 携带的数据量
  2. pipeline 每次只能作用在一个redis节点上
  3. m 操作与 pipeline的区别

发布订阅

redis只实现了简单的发布订阅功能,无法实现消息堆积,不能追溯以前的消息。

常用命令

  • publish channel message 向对应频道发送消息,返回订阅者数
  • subscribe channel1 channel2... 订阅频道
  • unsubscribe channel 取消订阅频道
  • psubscribe pattern 按照匹配规则订阅频道,如果:psubscribe openbook:*
  • pubsubscribe pattern 按照匹配规则取消订阅频道
  • pubsub channels <pattern> 找出订阅者至少为1的频道
  • pubsub numsub channel 获取channel的订阅数量(不包含按照规则订阅的订阅者)
  • pubsub numpat 获取被订阅的规则总数 如:openbook:* channel:*

消息队列

借助 list 对阻塞,实现消息的抢购消费

位图 Bitmap

Bitmap在redis中不是一个新的数据类型,其借助的是字符串,如果使用type命令来查看其数据类型的话,发现是字符串类型。

使用场景

  1. 用户签到
    很多网站都提供了签到功能,并且需要展示最近一个月的签到情况,这种场景可以使用bitmap来实现。根据日期 offset = 一年中的第几日 key = 年份:用户id

  2. 统计活跃用户(用户登录情况)
    使用日期作为key,然后用户id为offset,如果当日活跃过就设置为1
    假如20221218的活跃情况是:[1,0,1,1,0,1],20221219的活跃用户情况是:[1,1,1,1,0,1],统计连续两天活跃的用户总数:

bitop and res 20221218 20221219
bitcount res

统计20221218~20221219活跃过的用户:

bitop or res 20221218 20221219
bitcount res
  1. 统计用户是否在线
    如果需要提供一个查询当前用户是否在线的接口,也可以考虑使用bitmap。既节约空间又高效。只需要一个key,然后用户id为offset,如果在线就设置为1,不在线就设置为0.

常用命令

  • setbit key offset value value值只能是0或者1
  • getbit key offset 获取偏移offset的值
  • bitcount key [start end] 获取指定范围内1多个数,如果不指定start和end,则计算全部
  • bitop options destKey key1 key2... 对多个key进行操作

and 与运算符 &
or 或运算符 |
xor 异或 ^
not 取反 ~
这些操作都是对每个bit位上的值进行操作

  • bitop key value 返回key中第一个位value的索引

经纬坐标Geo

使用type命令发现,geo的类型是zset,基于zset实现,所以成员操作可以使用zset的相关命令

常用命令

  • geoadd key longitude latitude member 添加经纬度
  • geopos key member 获取成员经纬度坐标
  • geodist key member1 member2 [unit] 计算两个成员之间的距离(unit:m、km、mi英里、ft英尺)
  • georadius key longitude radius [unit] [partoptions] 获取指定经纬度距离范围内的成员
partoptions 可以是以下情况:
withcoord:返回结果包含经纬度
withdist:返回结果包含距离中心点的距离
withhash:返回结果包含geohash
COUNT count:指定返回结果的数量
asc | desc:返回结果按照距离中心点的距离进行升序 | 降序排列
store key:将返回结果的地理位置信息保存到指定键,存储到了一个zset中,score是在geo中的hash值。
storedist key:将返回结果距离中心点的距离保存到指定键中,存储到一个zset中,score是到中心点的距离。

持久化

持久化的方式有 快照日志
image

快照模式 RDB

触发RDB持久化的方式有三种:save(同步命令)bgsave(异步命令)自动(根据一定阈值条件自动触发)生成rdb文件,redis可以根据rdb文件恢复磁盘上持久化的数据。
save 命令会阻塞其他命令,bgsave 使用的是子线程执行快找操作,不会阻塞其他命令的执行,但是生成子线程的操作是会阻塞其他命令的执行的
redis配置文件中默认的rdb生成策略:
image

RDB 方式存在的问题 :

  • 耗时、耗性能
  • 不可控、容易丢失数据

日志模式 AOF

原理:写命令刷新到缓存区,然后根据一定策略将缓冲区中的命令写入磁盘持久化,AOF模式的三种策略:alwayseverysecno

  • alwasy:每条命令都会写入磁盘
  • eveysec:每秒将缓冲区中的命令写入磁盘中
  • no:系统将自动决定什么时候将缓冲区中的命令写入磁盘中

三种策略对比

image

随着命令的增多,AOF日志文件会逐渐增大,redis为了解决这一点,会将AOF中的命令进行重写:将重复的、过期的、多次操作进行简化:
image

这样可以减小磁盘占用、增加恢复速度
AOF重写配置:
image

RDB和AOF对比取舍
image

主从复制

  • 从节点为主节点提供了数据备份
  • 对读写进行分流,减轻主节点压力

主从复制存在的问题

当主节点挂掉之后,只能手动转移

2

评论区