Redis_基本使用

1/18/2021 Redis

# Redis_基本使用

# 命令

# 使用要点

  • 命令中涉及到range操作的都支持正向索引(1,2,3)和负向索引(-1,-2,-3)
  • Redis虽然提供了很多的命令,但是需要评估每个命令的性能消耗(运行效率、网卡吞吐量)
    • smembers
    • keys

# Help命令

# @server

  • config

# @General

  • type
  • object
  • del
  • dump
  • exists
  • expire
  • expireat
  • persist
  • pexpire
  • pexpireat
  • pttl
  • keys
  • migrate
  • move
  • randomkey
  • rename
  • renamenx

# @string

  • set

  • setnx

  • setex

  • setrange

  • msetnx

    原子操作

  • msetex

  • get

  • getset

    设置新值,返回旧值

  • getrange

    getrange k1 0 -1
    
    1
  • append

  • strlen

  • incr

  • incrby

  • incrbyfloat

  • decr

  • decrby

  • setbit

    setbit k1 1 1
    setbit k1 7 1
    setbit k1 9 1
    // 字符集  ascii其他一般叫做扩展字符集扩展:  其他字符集不在对ascii重编码0xxxxxxx你自己写一个程序,字节流读取,每字节判断
    
    1
    2
    3
    4
  • bitpos

    start/end是指字节索引位置

  • bitcount

  • bitop

    setbit k1 1 1
    setbit k1 7 1
    setbit k2 1 1
    setbit k2 6 1
    bitop and andkey k1 k2
    bitop or orkey k1 k2
    
    1
    2
    3
    4
    5
    6

# @list

  • lpush

  • lpop

  • rpush

  • rpop

  • lrange

    lpush

  • lindex

  • lset

  • lrem

    lpush k1 a b c d a e f a g
    lrem k1 2 a  // 移除前两个a
    lrem k1 -2 a  // 移除后两个a
    
    1
    2
    3
  • linsert

    lpush k1 a b c d b e
    linsert k1 after b 6 // 如果有两个是在第一个符合条件的数据进行操作
    
    1
    2
  • llen

  • blpop

  • ltrim

    ltrim k4 0 -1

    删除范围外两端的数据

# @hash

  • hdel

  • hset

  • hmset

  • hget

  • hmget

  • hkeys

  • hvals

  • hgetall

  • hincrbyfloat

# @set

  • sadd

# @sorted set

# 管道Pipelining

一次发送多条操作指令,节省往返时间RTT(Round Trip Time)

echo -e "set k2 99\n incr k2\n get k2" | nc localhost 6379
1

使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理,例如10K的命令,读回复,然后再发送另一个10k的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容

# 大量插入数据

​ 使用正常模式的Redis 客户端执行大量数据插入不是一个好主意,因为一个个的插入会有大量的时间浪费在每一个命令往返时间上。使用管道(pipelining)是一种可行的办法,但是在大量插入数据的同时又需要执行其他新命令时,这时读取数据的同时需要确保尽可能快的写入数据。

只有一小部分的客户端支持非阻塞输入/输出(non-blocking I/O),并且并不是所有客户端能以最大限度的提高吞吐量的高效的方式来分析答复。

例如,如果我们需要生成一个10亿的keyN -> ValueN的大数据集,我们会创建一个如下的redis命令集的文件data.txt:

SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN
1
2
3
4

以前可以使用netcat的方式,使用方式如下:

(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null
1

然而这并不是一个非常可靠的方式,因为用netcat进行大规模插入时不能检查错误。

从Redis 2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数据插入工作。

使用pipe mode模式的执行命令如下:

cat data.txt | redis-cli --pipe
1

这将产生类似如下的输出:

All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000
1
2
3

使用redis-cli将有效的确保错误输出到Redis实例的标准输出里面。

# Pub/Sub

  • 只能收到订阅之后发布的消息

  • 使用案例

    • 聊天系统

image-20210713121936501

# transactions

  • 特点

    • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
    • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
  • 帮助

    help @transactions

  • 用法

    MULTIEXECDISCARDWATCH是Redis事务相关的命令。

    • MULTI开启事务

      • 开启事务之后发送的命令会被放到一个队列中
    • EXCEC负责触发并执行事务中所有的命令

      • 如果客户端在使用MULTI开启了一个事务之后,却因为断线而没有成功执行 EXEC,那么事务中的所有命令都不会被执行。
      • 另一方面,如果客户端成功在开启事务之后执行 EXEC,那么事务中的所有命令都会被执行。
    • DISCARD放弃执行事务

      • 清空事务队列,并且客户端会从事务状态中退出
    • WATCH

      • WATCH某个key,如果被其他事务修改会结束执行返回nil-reply

      • 使用check-and-set操作实现乐观锁

        WATCH mykey
        val = GET mykey
        val = val + 1
        MULTI
        SET mykey $val
        EXEC
        
        1
        2
        3
        4
        5
        6
  • 事务中的错误

    • 执行事务之前,入队可能因为语法错误(参数数量错误,参数名错误,等等)或其他更严重的错误(内存不足)出错

      判断返回值是否是QUEUED

    • 调用EXEC之后出错(类型操作错误等)

  • 多个事务执行逻辑

    开启事务之后对应的操作会被缓冲到队列中,哪个事务的EXCEC先到达就先执行哪个事务的任务

  • 为什么不支持回滚

    • Redis只会因为错误的语法失败(并且这些问题不能在入队时发现)或者命令用在错误的数据类型上。也就是说失败的命令是由错误编程造成的,这些问题应该在开发的过程中被发现,而不是生产环境
    • 因为不需要回滚,所以Redis内部可以保持简单快捷
  • check-and-set操作实现乐观锁

    WATCH mykey
    val = GET mykey
    val = val + 1
    MULTI
    SET mykey $val
    EXEC
    
    1
    2
    3
    4
    5
    6

    使用上面的代码, 如果在 WATCH 执行之后, EXEC 执行之前, 有其他客户端修改了 mykey 的值, 那么当前客户端的事务就会失败。 程序需要做的, 就是不断重试这个操作, 直到没有发生碰撞为止。

    这种形式的锁被称作乐观锁, 它是一种非常强大的锁机制。 并且因为大多数情况下, 不同的客户端会访问不同的键, 碰撞的情况一般都很少, 所以通常并不需要进行重试。

# modules

  • 如何加载模块

    • 启动的时候通过参数指定加载

      redis-server /etc/redis/6379.conf --loadmodule /path/xxx.so

    • 配置文件中配置

      loadmodule

# Redisbloom布隆过滤器

image-20210713144303490

  • 配置使用

    • 访问redis.io->modules查找RedisBloom的github地址 (opens new window)

    • 下载源码,解压安装

      • unzip *.zip

      • make

      • cp bloom.so /opt/mashibing/redis5/

    • 启动

      redis-server --loadmodule /opt/mashibing/redis5/redisbloom.so

    • 使用

      redis-cli

      bf.add ooxx abc

      bf.exits abc

      bf.exits sdfsdf

      cf.add

  • 架构

    • client实现bloom算法自己承载bitmap + Redis
    • client实现bloom算法 + Redis&bitmap
    • client + Redis&Bloom&bitmap

# cukcoo布谷鸟过滤器

# Lua脚本

# Lua脚本调试

# 内存优化

# 过期

  • 过期时间的变化

    • 过期时间不会随着访问而改变
    • 如果发生写会剔除过期时间,需要业务逻辑去补全
  • Redis如何淘汰过期的key

    • 过期两种方式

      • 被动访问时检测

        当客户端尝试访问它时,key会被发现并且主动的过期

      • 主动周期轮询判定

        定时随机测试设置keys的过期时间,所有的这些过期的key将会从秘钥空间删除

        1. 测试随机的20个keys进行相关过期监测
        2. 删除所有已经过期的keys
        3. 如果有多于25%的key过期,重复步骤1

        这样的话在任何给定的时刻,最多会清楚1/4的过期keys

      这样做的目的是稍微牺牲下内存,但是保住了Redis性能

  • 在复制AOF文件时如何处理过期

# LRUCache

# 从文件中批量导入数据

# 分区

# 分布式锁

# key事件通知

# 创建二级索引

# 客户端缓存