redis笔记(一)

206 阅读13分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 8 天,点击查看活动详情

一、基础知识

1,redis支持的数据类型:

  • string字符串、hash哈希、list列表、set集合、zset有序集合、Bitmaps位图、HyperLogLog、Geo;

2,redis特性:

  • 速度快:
    • 读10w/s,写8.1w/s;
    • 原因:内存存放、C语言实现、单线程无多线程竞争问题;
  • 基于键值对构建;
  • 功能丰富:
    • 键过期功能,实现缓存;
    • 发布订阅,实现消息系统;
    • Lua脚本,构建新命令;
    • 事务,保证事务特性;
    • pipeline,减少网络开销;
  • 简单稳定:
    • 原因:源码少,单线程模型,不需要依赖操作系统类库;
  • 客户端语言多:
    • 基于tcp协议编程;
    • Java、Python、C++……;
  • 可持久化:
    • RDB和AOF两种方式将数据持久化到硬盘,重启能恢复;
  • 主从复制:
    • 读写分离;
    • 多个数据副本;
  • 高可用和分布式:
    • 故障发现和自动转移;
    • 可扩展;

3,使用场景

  • 缓存、排行榜系统、计数器应用、社交网络……
  • 中小规模的热数据,不适合大规模的冷数据;

4,启动与关闭相关

  • redis 可执行文件说明

    可执行文件说明
    redis-server启动redis服务
    redis-cli启动redis客户端
    redis-benchmarkredis基准测试工具
    redis-check-aofredis aof 持久化文件检测和修复工具
    redis-check-dumpredis rdb 持久化文件检测和修复工具
    redis-sentinel启动redis哨兵模式
  • redis 启动

    • 默认配置:
      • 命令:redis-server;
      • 使用默认配置文件:/usr/local/redis-6.2.4/redis.conf;
    • 参数启动:
      • 命令:redis-server --configKey1 configValue1 --configKey2 configValue2;
      • eg:redis-server --port 8888;
      • 其他未修改的参数依然使用默认配置文件中的默认参数,且自定义参数不会保存到配置文件中;
    • 配置文件启动:
      • 命令:redis-server /opt/redis/redis.conf;
  • redis 客户端命令

    • 交互式:
      • 命令:redis-cli -h host -p port;
      • 再执行 redis 命令;
    • 命令行式:
      • 命令:redis-cli -h host -p port commend;
      • eg:redis-cli -h 127.0.0.0 -p 6379 get key1;
  • redis 服务关闭

    • redis-cli shutdown nosave|save
    • 可以选择是否生成持久化文件;
    • 过程:断开与客户端的连接、持久化文件生成、服务关闭;
    • kill -9 可能会导致缓冲区资源丢失以及无法生成持久化文件;

二、基本命令

  • Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库服务;
  • 命令到服务端后都会进入一个队列,然后被逐一执行;
  • 单线程快速原因:
    • 纯内存访问;
    • 非阻塞io,epoll实现io多路复用;
    • 单线程避免了线程切换和竞态产生的消耗;

1,全局命令

命令说明
config get name查看某个配置信息
config set name value在命令行动态设置某个配置信息
config rewrite将配置持久化到本地配置文件
info [section]查看redis基本情况,或某个section情况
dbsize输出key的总数
randomkey随机输出一个key
keys pattern全量遍历键;
·* 代表匹配任意字符;
·?代表匹配一个字符;
·[] 代表匹配部分字符;
·\x 用来做转义;
expire key seconds设置key过期时间;
expire设置毫秒;
expireat key timestamp键在秒级时间戳timestamp后过期
expireat设置毫秒
object encoding key查看key内部结构的编码方式
exists key检查key是否存在
del key [key ...]删除key
ttl/pttl key查看key剩余过期时间;
pttl表示毫秒级过期时间;
-1 表示未设置过期时间;
-2 表示key不存在;
type key查看key的数据结构类型
persist key将键的过期时间清除
rename key newkey键重命名
重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性
renamenx key newkey只有newKey不存在时候才被覆盖
select dbIndex切换数据库
flushdb清除当前数据库
flushall清除所有数据库

  • key迁移:
    • a)move:
      • move key dbIndex:用于redis内部迁移,把指定的键从源数据库移动到目标数据库中;
    • b)dump+restore
      • dump key: 在源Redis上,dump命令会将键值序列化,格式采用的是RDB格式;
      • restore key ttl value
    • c)migrate
      • migrate host port key|"" destination-db timeout [copy] [replace] [keys key [key...]
        • ·host:目标Redis的IP地址;
        • ·port:目标Redis的端口;
        • ·key|""":要迁移的单个键,多个键时为空;
        • ·destination-db:目标Redis的数据库索引;
        • ·timeout:迁移的超时时间(单位为毫秒);
        • ·[copy]:如果添加此选项,迁移后并不删除源键;
        • ·[replace]:如果添加此选项,migrate不管目标Redis是否存在该键都会正常迁移进行数据覆盖;
        • ·[keys key[key...]]:迁移多个键,eg:“keys key1 key2 key3”;
      • migrate命令将dump、restore、del三个命令进行组合,并且具有原子性;
  • key遍历:
    • scan cursor [match pattern] [count number]
      • ·cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值,直到游标值为0,表示遍历结束;
      • ·match pattern是做模式的匹配;
      • ·count number表明每次要遍历的键个数,默认值是10;
      • 另外还有hscan、sscan、zscan
    • 可能有并发问题;

2,字符串命令

命令说明
setnxkey不存在才设置,可以用于分布式锁
setxxkey存在才设置
append key value字符串末尾追加值
strlen key返回字符串长度
getset key value设置并返回原值
setrange key offeset value设置指定位置的字符
getrange key start end获取部分字符串,闭区间
  • 值可以是字符串、数值、二进制,最大不能超过512MB;
  • set key value [ex seconds] [px milliseconds] [nx|xx];
    • ex seconds:为键设置秒级过期时间;
    • px milliseconds:为键设置毫秒级过期时间;
    • nx:键必须不存在,才可以设置成功,用于添加;
    • xx:键必须存在,才可以设置成功,用于更新;
  • 对于字符串类型键,执行set命令会去掉过期时间,这个问题很容易在开发中被忽视
  • setex命令作为set+expire的组合,不但是原子执行,同时减少了一次网络通讯的时间。
  • mget 相比于多次 get 可以节省网络开销;
  • 自增减:incr、incrby、incrbyfloat、decr、decrby;
  • 内部编码:
    • int:8个字节的长整型;
    • embstr:小于等于39个字节的字符串;
    • raw:大于39个字节的字符串;

3,哈希命令

命令说明
hset key field value设置指定字段的值
hget key field获取指定字段的值
hmset key field1 value1 [field2 value2 ...]同时将多个字段的值
hmget key field1 [field2 ...]获取所有给定字段的值
hgetall key获取所有字段的值
hkeys key获取所有字段
hvals key获取所有值
hlen key获取字段的数量
hstrlen key field获取指定字段的字符串值长度
hdel key field2 [field2 ...]删除所有给定的字段
hexists key field查看指定字段是否存在
hincrby key field increment为指定字段的整数值加上增量 increment
hincrbyfloat key field increment为指定字段的浮点数值加上增量 increment
hsetnx key field value只有在字段 field 不存在时,设置哈希表字段的值
hscan key cursor [MATCH pattern] [COUNT count]从key的cursor游标开始查询键符合pattern的字段和值,每次查询的数量是count
  • 哈希类型的内部编码:
    • ziplist(压缩列表):当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面比hashtable更加优秀;
    • hashtable(哈希表):当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1);

4,列表命令

命令说明
lpush key value [value ...]从左边插入元素
rpush key value [value ...]从右边插入元素
linsert key before/after pivot value在pivot前或后插入元素
lrange key start end获取指定范围内的元素列表,闭区间,左往右0N-1,右往左-1N
lindex key index获取列表指定索引下标的元素
llen key获取列表长度
lpop key从列表左侧弹出元素
rpop key从列表右侧弹出
lrem key count value删除count数量的指定元素,count>0从左往右,count<0从右往左,count=0全部删除
ltrim key start end按照索引范围修剪列表,闭区间
lset key index newValue修改指定索引下标的元素
blpop/brpop key [key ...] timeout阻塞式弹出
  • 一个列表最多存储2^32-1个元素;
  • 列表类型的内部编码:
    • ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用;
    • linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现;
    • quicklist(快速列表):以一个ziplist为节点的linkedlist,结合了两者的优势,为列表类型提供了一种更为优秀的内部编码实现;

5,集合命令

命令说明
sadd key element [element ...]添加元素,返回结果为添加成功个数
srem key element [element ...]删除元素,返回结果为删除成功个数
scard key计算元素个数
sismember key element判断元素是否在集合中
smember key获取所有元素
srandmember key [count]随机从集合返回指定个数元素,不删除元素
spop key从集合随机弹出元素,并删除
sinter/suinon/sdiff key [key ...]求多个集合的交集、并集、差集
sinterstore/suionstore/sdiffstore destination key [key ...]将交集、并集、差集的结果保存
  • 集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素;
  • 一个集合最多存储2^32-1个元素;
  • 集合类型的内部编码:
    • intset(整数集合):当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用;
    • hashtable(哈希表):当集合类型无法满足intset的条件时,Redis会使 用hashtable作为集合的内部实现;

6,有序集合命令

命令说明
zadd key score member [score member ...]添加成员
·nx:member必须不存在,才可以设置成功,用于添加;
·xx:member必须存在,才可以设置成功,用于更新;
·ch:返回此次操作后,有序集合元素和分数发生变化的个数;
·incr:对score做增加,相当于zincrby
zcard key计算成员个数
zscore key member计算某个成员的分数
zrank/zrevrank key member计算成员的排名,分别是分数从低到高和从高到低
zrem key member [member ...]删除成员
zincrby key increment member增加成员的分数
zrange/zrevrange key start end [withscores]返回指定排名范围的成员,闭区间;
withscores选项,同时会返 回成员的分数
zrangebyscore/zrevrangebyscore key max min [withscores] [limit offset count]返回指定分数范围的成员;
[limit offset count]选项可以限制输出的起始位置和个数;
min和max还支持开区间和闭区间,-inf和+inf分别代表无限小和无限大;
zcount key min max返回指定分数范围成员个数
zremrangebyrank key start end删除指定排名内的升序元素
zremrangebyscore key min max删除指定分数范围的成员
zinterstore/zunionstore destination numkeys key [key ...] [weights weight [weight ...]] [aggregate sum/min/max]交/并集
·destination:交集计算结果保存到这个键;
·numkeys:需要做交集计算键的个数;
·key[key...]:需要做交集计算的键;
·weights weight[weight...]:每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,权重默认是1;
·aggregate sum/min/max:计算成员交集后,member的分值可以按照sum(和)、 min(最小值)、max(最大值)做汇总,默认值是sum;
  • 有序集合中的元素可以排序,它给每个元素设置一个分数(score)作为排序的依据;
  • 有序集合中的元素不能重复,但是score可以重复;
  • 有序集合类型的内部编码:
    • ·ziplist(压缩列表):当有序集合的元素个数小于zset-max-ziplist- entries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用;
      • ·skiplist(跳跃表):当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,此时ziplist的读写效率会下降。

三、基本功能

1,慢查询

  • 慢查询:
    • 就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息记录下来;
    • 日志内容:日志id、发生时间戳、命令耗时、执行命令和参数;
    • 日志存放在指定长度的先进先出的队列中;
    • 慢查询只记录命令执行时间,并不包括命令排队和网络传输时间。
  • 配置参数:
    • slowlog-log-slower-than:预设阈值;
    • slowlog-max-len:日志存储数量;
  • 相关命令:
    • slowlog get [n]:获取慢查询日志;
    • slowlog len:获取慢查询日志列表当前的长度;
    • slowlog reset:慢查询日志重置;

2,redis-cli命令

参数说明示例
-r(repeat)将命令执行多次redis-cli -r 3 ping
-i(interval)每隔几秒执行一次命令,但是必须和-r一起使用redis-cli -r 5 -i 1 ping
-x从标准输入(stdin)读取数据作为redis-cli的最后一个参数echo "world" | redis-cli -x set hello
-c(cluster)连接Redis Cluster节点时需要使用的-
-a(auth)对于配置密码的redis,无需手动输入auth命令
--slave把当前客户端模拟成当前Redis节点的从节点,可以用来 获取当前Redis节点的更新操作-
--rdb请求Redis实例生成并发送RDB持久化文件,保存在本地-
--pipe将命令封装成Redis通信协议定义的数据格式,批量发送 给Redis执行-
--bigkeys使用scan命令对Redis的键进行采样,从中找到内存占用比 较大的键值,这些键可能是系统的瓶颈-
--eval指定lua脚本-
--latency测试客户端到目标Redis的网络延迟,执行结果只有一条redis-cli -h host -p port --latency
--latency-history分时段了解延迟信息,通过 -i 控制间隔时间redis-cli -h host -p port -i 5 --latency-history
--latency-dist使用统计图表的形式从控制台输出延迟统计信息-
--stat可以实时获取Redis的重要统计信息,包括增量数据-
--raw和--no-raw返回结果是原始格式或格式化后的-

3, redis-server命令

参数说明示例
--test-memory用来检测当前操作系统能否稳定地分配指定容量的内存给 Redis,可以有效避免因为内存问题造成Redis崩溃,单位MBredis-server --test-memory 1024

4,redis-benchmark命令

参数说明示例
-c(clients)选项代表客户端的并发数量(默认是50)-
-n(num)选项代表客户端请求总量(默认是100000)redis-benchmark -c 100 -n 20000
-q显示redis-benchmark的requests per second信息-
-r(random)向redis中插入更多随机的键-r 1000(表示对后三位随机处理)
-P每个请求pipeline的数据量(默认为1)-
-k选项代表客户端是否使用keepalive,1为使用,0为不使用,默认值为 1-
-t对指定命令进行基准测试-t get,set
--csv将结果按照csv格式输出-

5,原生批命令与pipeline区别

  • Redis客户端执行一条命令分的四个过程:发送命令、命令排队、命令执行、返回结果;
  • 其中发送和返回,称为Round Trip Time(RTT,往返时间),批命令和pipeline都能节省这部分时间;
  • 原生批命令包括:hset、hget、mset、mget……
批命令pipeline
原子的非原子的
一个命令对应多个key支持多个命令
服务端支持实现客户端和服务端都共同支持实现

6,发布订阅

  • 消息发布 者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息;
  • 客户端在执行订阅命令之后进入了订阅状态,只能接收subscribe、 psubscribe、unsubscribe、punsubscribe的四个命令;
功能命令
发布消息publish channel message
订阅频道subscribe channel [channel ...]
取消订阅unsubscribe [channel [channel ...]]
按照模式订阅频道psubscribe pattern [pattern...]
按照模式取消订阅punsubscribe [pattern [pattern ...]]
查看活跃的频道pubsub channels [pattern]
查看频道订阅数pubsub numsub [channel ...]
pubsub numpat