Redis

简介

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

相关网站

常用命令

  • redis-cli连接 redis

    redis-cli -h 127.0.0.1 -p 6379
    # -c 连接集群结点时使用,此选项可防止moved和ask异常
    # -a 密码
  • 切换数据库

    # 默认有16个数据库(0-15)
    select 1
    
    select 16
    # (error) ERR DB index is out of range
  • 查看数据库数据量

    dbsize
  • 查看数据库所有的key

    keys *
  • 存值、取值

    set key1 v1
    # OK
    get key1
    # "v1"
  • 清空数据操作

    # 清除当前数据库
    flushdb
    # 清除所有数据库(慎用)
    flushall
  • 判定键是否存在

    exists key1
  • 移动某个键到某个数据库

    move key1 1
  • 设置键的过期时间,查看键的剩余过期时间

    expire key1 10
    # 10秒后过期
    ttl key1
  • 查看数据类型

    type key1
    # string

数据类型

string

  • 末尾追加字符串

    append key1 xxx
    # 键不存在时,等于set操作
  • 自增、自减操作

    set view_num 0
    # 自增
    incr view_num
    # 自减
    decr view_num
    # 以步长为10,自增
    incrby view_num 10
  • 截取、替换字符串

    set key1 abcdefg
    # 截取下标为1-3位的字符 [1,3]
    getrange key1 1 3
    # bcd
    
    # 截取全部(等于查看全部)
    getrange key1 0 -1
    
    # 从下标第2个字符开始替换后面的字符为xx
    setrange key1 2 xx
    # "abxxefg"
  • setex、setnx(分布式锁、乐观锁常用)

    # 设置过期时间并赋予新值
    setex set_with_expire 30 'newData'
    # 不存在键的时候赋值,存在无法赋值
    setnx set_if_not_exist 'data'
    setnx set_if_not_exist 'newData'
    get set_if_not_exist
    # "data"
  • 存取多值

    mset k1 v1 k2 v2 k3 v3
    mget k1 k2 k3
    # msetnx 原子性操作,失败一个都失败
    msetnx k1 v1 k4 v4
  • getset

    # 先获取在设置值
    getset k6 v6
    # (nil)
    getset k6 v6_new
    # "v6"
    get k6
    # "v6_new"

list

  • lpush

    lpush list_key firstValue
    lpush list_key secondValue thirdValue
    
    lrange list_key 0 -1
    # 1) "thirdValue"
    # 2) "secondValue"
    # 3) "firstValue"
  • rpush

    rpush list_key right_side
    
    lrange list_key 0 -1
    # 1) "thirdValue"
    # 2) "secondValue"
    # 3) "firstValue"
    # 4) "right_side"
  • lpop、rpop

    lpop list_key
    rpop list_key
    
    lrange list_key 0 -1
    # 1) "secondValue"
    # 2) "firstValue"
  • lindex

    lindex list_key 1
    # "firstValue"
  • llen

    llen list_key
    # (integer) 2
  • lrem

    lrem list_key 1 secondValue
  • ltrim

    lpush list_key2 a b c d e f g
    # 通过下标截取list
    ltrim list_key2 3 5
    lrange list_key2 0 -1
    # 1) "d"
    # 2) "c"
    # 3) "b"
  • rpoplpush

    lpush list_key3 1 2 3 4 5
    # 移动一个list最右边的,加在另一个list的最左边
    rpoplpush list_key3 list_key4
    
    lrange list_key3 0 -1
    # 1) "5"
    # 2) "4"
    # 3) "3"
    # 4) "2"
    lrange list_key4 0 -1
    # 1) "1"
  • exists

    exists list_key3 list_key4
  • lset

    lset list_key4 0 one
    
    lrange list_key4 0 0
    # 1) "one"
  • linsert

    linsert list_key4 before "one" "before"
    linsert list_key4 after "one" "after"
    
    lrange list_key4 0 -1
    # 1) "before"
    # 2) "one"
    # 3) "after"

set

  • sadd

    sadd set_key firstValue secondValue thirdValue
    sadd set_key secondValue
    
    smembers set_key
    # 1) "secondValue"
    # 2) "thirdValue"
    # 3) "firstValue"
  • sismember、scard

    # 是否存在某个元素
    sismember set_key thirdValue
    # (integer) 1
    
    # set集合中的元素个数(set cardinality)
    scard set_key
    # (integer) 3
  • srem

    # 移除某个元素
    srem set_key secondValue
  • srandmember

    sadd set_key2 a b c d e f g h i j k l m n o p q r s t u v w x y z
    # 随机取5个元素
    srandmember set_key2 5
  • smove

    # 移动一个元素到另外一个set中
    smove set_key2 set_key3 a
  • sdiff、sinter、sunion

    sadd set_key4 1 2 3 4
    sadd set_key5 3 4 5 6
    
    # 第一个set的差集
    sdiff set_key4 set_key5
    # 1) "1"
    # 2) "2"
    
    # 交集
    sinter set_key4 set_key5
    # 1) "3"
    # 2) "4"
    
    # 并集
    sunion set_key4 set_key5

hash

  • hset

    hset hash_key field1 v1 field2 v2
    
    hget hash_key field1 field2
    # "v1"
    hmget hash_key field1 field2
    # 1) "v1"
    # 2) "v2"
    hgetall hash_key
    # 1) "field1"
    # 2) "v1"
    # 3) "field2"
    # 4) "v2"
  • hdel

    # 删除某个字段
    hdel hash_key field1
  • hlen、hkeys、hvals

    hset hash_key field1 v1 field2 v2 field3 v3 field4 v4 field5 v5
    
    # 获取map长度
    hlen hash_key
    # (integer) 5
    
    # 获取所有字段
    hkeys hash_key
    # 1) "field2"
    # 2) "field1"
    # 3) "field3"
    # 4) "field4"
    # 5) "field5"
    
    # 获取所有的值
    hvals hash_key
    # 1) "v2"
    # 2) "v1"
    # 3) "v3"
    # 4) "v4"
    # 5) "v5"
  • hexists

    # 是否存在某个字段
    hexists hash_key field3
  • hincrby、hdecrby

    hset hash_key num 0
    
    # 自增、自减
    hincrby hash_key num 5
    hincrby hash_key num -3
    
    hget hash_key num
    # "2"

zset

  • zadd

    # 有序set
    zadd zset_key 2 secondValue 3 thirdValue
    zadd zset_key 1 firstValue
    
    zrange zset_key 0 -1 withscores
  • zcard

    # 统计个数
    zcard zset_key
  • zrevrange

    # 倒序
    zrevrange zset_key 0 -1
    
    zrevrange zset_key 2 3
    # 1) "firstValue"
    
    zrevrange zset_key -2 -1 withscores
    # 1) "secondValue"
    # 2) "2"
    # 3) "firstValue"
    # 4) "1"
  • zrem

    # 删除指定元素
    zrem zset_key secondValue
  • zcount

    # 指定区间计数
    zcount zset_key -inf +inf
    # (integer) 2
    
    zcount zset_key 0 2
    # (integer) 1

事务

MULTIEXECDISCARDWATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

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

EXEC 命令负责触发并执行事务中的所有命令:

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

当使用 AOF 方式做持久化的时候, Redis 会使用单个 write(2) 命令将事务写入到磁盘中。

# 开启事务
127.0.0.1:6379[1]> multi
OK
# 开始输入命令
127.0.0.1:6379[1]> set k1 v1
QUEUED
127.0.0.1:6379[1]> get k1
QUEUED
127.0.0.1:6379[1]> set k2 v2
QUEUED
127.0.0.1:6379[1]> set k3 v3
QUEUED
127.0.0.1:6379[1]> keys *
QUEUED
127.0.0.1:6379[1]> setex k2 5 xxx
QUEUED
127.0.0.1:6379[1]> keys *
QUEUED
# 输入命令结束
# 触发并执行事务中的所有命令
127.0.0.1:6379[1]> exec
# 1) OK
# 2) "v1"
# 3) OK
# 4) OK
# 5) 1) "k2"
#    2) "k1"
#    3) "k3"
# 6) OK
# 7) 1) "k2"
#    2) "k1"
#    3) "k3"

# 再次验证k2是否过期
127.0.0.1:6379[1]> keys *
# 1) "k1"
# 2) "k3"
  • discard 放弃事务

  • Redis 不支持回滚(roll back),回滚并不能解决编程错误带来的问题

    以下是这种做法的优点:

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

    • WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为

管理客户端

  1. 自带的 redis-cli

  2. RedisDesktopManager (高版本收费,0.9.3 免费)

    下载地址 https://github.com/uglide/RedisDesktopManager/releases/tag/0.9.3

  3. RedisInsight

    下载地址 https://docs.redis.com/latest/ri/installing/install-redis-desktop/

单机启动

# windows下 配置好 redis.windows.conf cmd中运行 redis-server redis.windows.conf

# Docker
docker run -itd --name redis-test-pw -p 6379:6379 redis --requirepass "password"

集群启动(三台机器,三主三从,Docker版)

  1. 虚拟机3台Liunx设备

    # 这里用 Ubuntu 22.04 系统
    # 3台设备的ip为 192.168.1.95 、 192.168.1.96 、 192.168.1.97
  2. 3台机器分别创建容器

    # 192.168.1.95
    docker create --name redis-node1 --net host -v /data/redis-data/node1:/data redis --cluster-enabled yes --cluster-config-file nodes-node-1.conf --port 6379 --requirepass "password" --masterauth "password"
    
    docker create --name redis-node2 --net host -v /data/redis-data/node2:/data redis --cluster-enabled yes --cluster-config-file nodes-node-2.conf --port 6380 --requirepass "password" --masterauth "password"
    
    # 192.168.1.96
    docker create --name redis-node3 --net host -v /data/redis-data/node3:/data redis --cluster-enabled yes --cluster-config-file nodes-node-3.conf --port 6379 --requirepass "password" --masterauth "password"
    
    docker create --name redis-node4 --net host -v /data/redis-data/node4:/data redis --cluster-enabled yes --cluster-config-file nodes-node-4.conf --port 6380 --requirepass "password" --masterauth "password"
    
    # 192.168.1.97
    docker create --name redis-node5 --net host -v /data/redis-data/node5:/data redis --cluster-enabled yes --cluster-config-file nodes-node-5.conf --port 6379 --requirepass "password" --masterauth "password"
    
    docker create --name redis-node6 --net host -v /data/redis-data/node6:/data redis --cluster-enabled yes --cluster-config-file nodes-node-6.conf --port 6380 --requirepass "password" --masterauth "password"
  3. 启动容器,并设置docker重启始终启动策略

    # 192.168.1.95
    docker start redis-node1 redis-node2
    docker update --restart=always redis-node1 redis-node2
    
    # 192.168.1.96
    docker start redis-node3 redis-node4
    docker update --restart=always redis-node3 redis-node4
    
    # 192.168.1.97
    docker start redis-node5 redis-node6
    docker update --restart=always redis-node5 redis-node6
  4. 随意进入一个容器

    docker exec -it redis-node6 bash
  5. 设置集群关系

    redis-cli --cluster create 192.168.1.95:6379 192.168.1.95:6380 192.168.1.96:6379 192.168.1.96:6380 192.168.1.97:6379 192.168.1.97:6380  --cluster-replicas 1
    
    # 中途输入 yes
  6. 测试集群

    # 进入集群节点
    redis-cli -c -h 192.168.1.95 -p 6379 -a password
    
    # 查看集群节点信息
    cluster info
    # 查看配置信息
    CONFIG GET *

Redis
https://元气码农少女酱.我爱你/e9a6abc21627/
作者
元气码农少女酱
发布于
2023年5月2日
许可协议