zoukankan      html  css  js  c++  java
  • 第二章 Redis数据类型

    一、redis搭建

    1.下载软件包

    下载Redis可以去Redis官网获取源码包,下载到服务器上编译。Redis官网(https://redis.io/)。进入下载页面(https://redis.io/download),从左到右分别是最新版、最新稳定版和容器版,我们可以下载最新稳定版的源码包(https://download.redis.io/releases/redis-6.0.9.tar.gz)。
    
    [root@db01 ~]# rz redis-6.0.9.tar.gz
    或者
    [root@redis01 ~]# wget https://download.redis.io/releases/redis-6.0.9.tar.gz
    

    2.安装依赖

    [root@redis01 ~]# yum install -y cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make tcl
    

    3 更新gcc版本

    centos7 默认的 gcc 版本小于 5.3 无法编译,需要先安装gcc新版才能编译
    [root@redis01 ~]# yum -y install centos-release-scl
    [root@redis01 ~]# yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
    
    #临时生效,退出 shell 或重启会恢复原 gcc 版本
    [root@redis01 ~]# scl enable devtoolset-9 bash
    
    #永久生效
    [root@redis01 ~]# echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
    

    4 .编译安装

    [root@redis01 ~]# tar -zxvf redis-6.0.9.tar.gz
    [root@redis01 ~]# mv redis-6.0.9 /usr/local/
    [root@redis01 ~]# cd /usr/local/redis-6.0.9
    [root@redis01 /usr/local/redis-6.0.9]# make &&make install  #默认安装
    或者
    [root@redis01 ~]# make PREFIX=/usr/local/redis-6.0.9 install #指定目录安装
    

    5.做软连接

    [root@redis01 /usr/local/redis-6.0.9]# cd ..
    [root@redis01 /usr/local]# ln -s /usr/local/redis-6.0.9 /usr/local/redis
    

    6.修改redis.conf

    [root@redis01 /usr/local]# cd redis
    [root@redis01 /usr/local/redis]# mkdir  /etc/redis/
    [root@redis01 /usr/local/redis]# cp redis.conf /etc/redis/
    [root@redis01 ~/redis-6.0.9]# vim /etc/redis/redis.conf
    bind 127.0.0.1 #根据情况是否需要远程访问去掉注释
    requirepass 123456 #修改密码
    protected-mode no # 关闭protected-mode模式,此时外部网络可以直接访问
    daemonize no      #以守护进程模式启动,指定目录安装时改为yes
    

    7. 配置system启动

    [root@redis01 /usr/local/redis]# vim /etc/systemd/system/redis.service
    [Unit]
    Description=Redis
    After=network.target
    
    [Service]
    #Type=forking
    ExecStart=/usr/local/redis-6.0.9/src/redis-server /etc/redis/redis.conf
    ExecReload=/usr/local/redis-6.0.9/src/redis-server -s reload
    ExecStop=/usr/local/redis-6.0.9/src/redis-server -s stop
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    
    注意Type=forking不注释掉 服务无法启动
    
    使服务自动运行
    [root@redis01 ~]# systemctl daemon-reload
    [root@redis01 ~]# systemctl enable redis
    
    启动服务
    [root@redis01 ~]# systemctl restart redis
    [root@redis01 ~]# systemctl status redis
    
    验证服务
    [root@redis01 /usr/local/redis]# netstat  -lntp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      12768/redis-server  
    

    8.连接redis

    #连接
    [root@redis01 /usr/local/redis]# redis-cli -p 6379
    127.0.0.1:6379> auth 123456			#验证密码
    127.0.0.1:6379>
    

    9.关闭redis

    [root@redis01 /usr/local/redis]# redis-cli shutdown
    或
    [root@db01 redis]# redis-cli 
    127.0.0.1:6379> shutdown
    

    二、redis配置文件

    1.配置

    #默认的配置文件
    [root@redis01 redis]# pwd
    /usr/local/redis
    [root@redis01 redis]# ll
    -rw-rw-r--  1 root root 46695 Jun 13  2018 redis.conf
    
    #创建reids配置文件目录
    [root@redis01 redis]# mkdir /service/redis/6379 -p
    
    #编写配置文件
    [root@redis01 redis]# vim /service/redis/6379/redis.conf
    bind 172.16.1.51 127.0.0.1							#监听地址
    port 6379										   #端口
    daemonize no									   #后台启动
    pidfile /service/redis/6379/redis_6379.pid		 	  #指定pid文件
    loglevel notice										#指定日志级别
    logfile /service/redis/6379/redis_6379.log			  #指定日志文件
    

    2.指定配置文件启动

    [root@redis01 redis]# redis-server /service/redis/6379/redis.conf
    

    三、redis操作

    1.基本操作

    1.连接redis
    	[root@db01 redis]# redis-cli 
        127.0.0.1:6379>
    2.查看所有数据
        127.0.0.1:6379> keys *
        (empty list or set)
    	#查看时注意不要轻易使用,如想查看数据,先查看数据量DBSIZE
    	127.0.0.1:6379> DBSIZE
    	(integer) 2018041
    3.添加数据
        127.0.0.1:6379> set k1 v1
        OK
    4.查看数据
        127.0.0.1:6379> keys *
        1) "k1"
        127.0.0.1:6379> get k1
        "v1"
    5.删除数据
        127.0.0.1:6379> keys *
        1) "k1"
        127.0.0.1:6379> DEL k1
        (integer) 1
        127.0.0.1:6379> keys *
        (empty list or set)
    6.修改数据
    	127.0.0.1:6379> set k1 v1
        OK
        127.0.0.1:6379> set k1 v11111
        OK
        127.0.0.1:6379> get k1
        "v11111"
    7.追加数据
    	127.0.0.1:6379> APPEND k1 000000
        (integer) 12
        127.0.0.1:6379> get k1
        "v11111000000"
    8.切换库
        127.0.0.1:6379> SELECT 1
        OK
        127.0.0.1:6379[1]> SELECT 2
        OK
        127.0.0.1:6379[2]> SELECT 3
        OK
        127.0.0.1:6379> SELECT 16
        (error) ERR invalid DB index
    

    2.密码的设置

    1.配置文件配置密码
        [root@db01 redis]# vim redis.conf 
        requirepass 123
    2.使用密码连接
    	[root@db01 redis]# redis-cli -a 123
    3.登陆后输入密码
    	[root@db01 redis]# redis-cli
        127.0.0.1:6379> AUTH 123
        OK
        127.0.0.1:6379> DBSIZE
        (integer) 2018041
    4.redis连接后获取密码
        127.0.0.1:6379> CONFIG GET requirepass
        1) "requirepass"
        2) "123"
    5.redis连接后修改密码
        127.0.0.1:6379> CONFIG set requirepass 234
        OK
        [root@db01 redis]# redis-cli
    	127.0.0.1:6379> DBSIZE
        (error) NOAUTH Authentication required.
        127.0.0.1:6379> auth 123
        (error) ERR invalid password
        127.0.0.1:6379> auth 234
        OK
    

    3.通用操纵

    1.判断key是否存在
        127.0.0.1:6379> EXISTS k1
        (integer) 1						#存在则返回1
        127.0.0.1:6379> EXISTS k2
        (integer) 0						#不存在则返回0
    2.修改key的名字
    	127.0.0.1:6379> KEYS *
        1) "k1"
        127.0.0.1:6379> RENAME k1 k100
        OK
        127.0.0.1:6379> KEYS *
        1) "k100"
    3.查看数据类型
    	127.0.0.1:6379> TYPE k100
        string
    4.设置生存时间
    	#以秒为单位
        127.0.0.1:6379> EXPIRE qiudao 10
        (integer) 1
        #以毫秒为单位
        127.0.0.1:6379> PEXPIRE k100 10000
    	(integer) 1
    5.查看生存时间
    	127.0.0.1:6379> TTL k100
        (integer) 1					#正整数生存时间倒计时
        127.0.0.1:6379> TTL k100
        (integer) -1				#-1代表没有设置生存时间
        127.0.0.1:6379> TTL k100
        (integer) -2				#代表设置过生存时间已删除,已过期
    6.取消生存时间
    	127.0.0.1:6379> TTL qiudao
        (integer) 93
        127.0.0.1:6379> PERSIST qiudao
        (integer) 1
        127.0.0.1:6379> TTL qiudao
        (integer) -1
    

    四、Redis数据持久化

    1.Redis数据安全问题

    	前面我们提到,Redis是一个缓存中间件,它的最大特点是使用内存从而使其性能强悍。但是使用内存的方式有一个致命的特点就是数据没办法持久化保存。然而Redis持久化存储有两种持久化方案,RDB(Redis DataBase)和 AOF(Append-Only File)。其中RDB是将内存中的数据进行快照存储到磁盘,AOF则为可回放的命令日志记录redis内的所有操作。它们各有特点也相互独立。Redis4之后支持RDB-AOF混合持久化的方式,结合了两者的优点,可以通过 aof-use-rdb-preamble 配置项可以打开混合开关。
    

    2.什么是持久化

    将内存中的数据写入到磁盘,永久保存
    

    3.持久化的模式

    1.RDB模式
    2.AOF模式
    

    4.快照持久化(RDB)

    1) RDB概述

    RDB(Redis DataBase)是将Redis内存中的数据进行Snaptshot快照存储在磁盘内,是Redis的默认持久化方案。使用RDB持久化默认有三种策略,该持久化策略在redis.conf中可配置,会以一段时间内有指定次数据修改的规则触发快照动作,快照文件名为dump.rdb,该文件默认使用LZF压缩算法 。每当Redis服务重启的时候会从该文件中加载数据进内存。
    
    RDB持久化除了可以根据配置中的策略触发,也可以手动触发,使用save和bgsave命令即可。这两个命令的区别的save会阻塞服务器进程,在进行save的过程中,服务器不能处理任何请求,而bgsave会通过一个子进程在后台处理rdb持久化。事实上save和bgsave调用的都是rdbSave函数,因此Redis不允许save和bgsave同时运行,这也是为了避免出现竞争导致rdb文件数据不准确。
    
    bgsave操作使用CopyOnWrite机制进行写时复制,是由一个子进程将内存中的最新数据遍历写入临时文件,此时父进程仍旧处理客户端的操作,当子进程操作完毕后再将该临时文件重命名为dump.rdb替换掉原来的dump.rdb文件,因此无论bgsave是否成功,dump.rdb都不会受到影响。
    
    另外在主从全量同步、debug reload以及shutdown的情况下也会触发RDB数据持久化。
    

    2)RDB模式

    可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)
    

    3)RDB工作模式

    1.默认情况下,Redis保存数据集快照到磁盘,名为dump.rdb的二进制文件。你可以设置让Redis在N秒内至少有M次数据集改动时保存数据集,或者你也可以手动调用SAVE或者BGSAVE命令。
    
    2.在上文中我们已经在配置文件中做过对应的配置:
    例如,这个配置会让Redis在每个60秒内至少有1000次键改动时自动转储数据集到磁盘:
    save 60 1000
    
    3.当 Redis 需要保存 dump.rdb 文件时,服务器执行以下操作:
    Redis 调用 fork() ,同时拥有父进程和子进程。
    子进程将数据集写入到一个临时的 RDB 文件中。当子进程完成对新 RDB 文件的写入时, Redis 用新RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
    
    4.这种方式使得 Redis 可以从写时复制机制中获益。
    

    4) 快照持久化快照相关配置

    #编辑配置文件
    [root@db01 ~]# vim /service/redis/6379/redis.conf 
    bind 172.16.1.51 127.0.0.1
    port 6379
    daemonize yes
    pidfile /service/redis/6379/redis_6379.pid
    loglevel notice
    logfile /service/redis/6379/redis_6379.log
    requirepass 123
    dir "/etc/redis"
    dbfilename dump.rdb
    stop-write-on-bgsave-error yes 
    rdbchecksum yes
    rdbcompression yes
    save 900 1
    save 300 10
    save 60 10000
    
    save m n
    #配置快照(rdb)促发规则,格式:save <seconds> <changes>
    
    #save 900 1 900秒内至少有1个key被改变则做一次快照
    #save 300 10 300秒内至少有300个key被改变则做一次快照
    #save 60 10000 60秒内至少有10000个key被改变则做一次快照
    
    #关闭该规则使用svae “” 
    
    dbfilename dump.rdb
    #rdb持久化存储数据库文件名,默认为dump.rdb
    
    stop-write-on-bgsave-error yes 
    #yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。
    
    rdbchecksum yes
    #在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
    
    dir "/etc/redis"
    #数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限
    
    rdbcompression yes
    #是否开启RDB文件压缩,该功能可以节约磁盘空间、
    

    5)使用RDB文件

    1.先停止redis
    2.将rdb文件放到指定目录下
    3.启动redis
    

    6) RDB优点

    1.RDB是一种表示某个即时点的Redis数据的紧凑文件。RDB文件适合用于备份。例如,你可能想要每小时归档最近24小时的RDB文件,每天保存近30天的RDB快照。这允许你很容易的恢复不同版本的数据集以容灾。
    2.RDB非常适合于灾难恢复,作为一个紧凑的单一文件,可以被传输到远程的数据中心。
    3.RDB最大化了Redis的性能,因为Redis父进程持久化时唯一需要做的是启动(fork)一个子进程,由子进程完成所有剩余工作。父进程实例不需要执行像磁盘IO这样的操作。
    4.RDB在重启保存了大数据集的实例时比AOF要快。
    

    7)RDB缺点

    1.当你需要在Redis停止工作(例如停电)时最小化数据丢失,RDB可能不太好。你可以配置不同的保存点(save point)来保存RDB文件(例如,至少5分钟和对数据集100次写之后,但是你可以有多个保存点)。然而,你通常每隔5分钟或更久创建一个RDB快照,所以一旦Redis因为任何原因没有正确关闭而停止工作,你就得做好最近几分钟数据丢失的准备了。
    2.RDB需要经常调用fork()子进程来持久化到磁盘。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且CPU性能不够强大的话,Redis会停止服务客户端几毫秒甚至一秒。AOF也需要fork(),但是你可以调整多久频率重写日志而不会有损(trade-off)持久性(durability)。
    

    8) RDB优缺点总结

    优点:速度快,适合于用作备份,主从复制也是基于RDB持久化功能实现的。
    
    缺点:会有数据丢失、导致服务停止几秒
    

    9)停止备份

    在配置文件中就设置save “”或在命令行中 config set save “”。
    

    10) 手动开始备份

    save:会立即生成dump.rdb,但是会阻塞往redis内存中写入数据。
    bgsave:后台异步备份。
    
    如果是使用flushdb命令,会把之前的快照更新成当前的空状态,所以执行了flushdb后更新的快照是没有数据的。
    

    11) save与bgsave对比

    命令 save bgsave
    IO类型 同步 异步
    是否阻塞 否(阻塞发生在fork)
    优点 不会消耗额外内存 不阻塞客户端命令
    缺点 阻塞客户端命令 创建fork,消耗内存

    5. AOF持久化

    	AOF(Append-Only File)记录Redis中每次的写命令,类似mysql中的binlog,服务重启时会重新执行AOF中的命令将数据恢复到内存中,RDB(按策略持久化)持久化方式记录的粒度不如AOF(记录每条写命令),因此很多生产环境都是开启AOF持久化。AOF中记录了操作和数据,在日志文件中追加完成后才会将内存中的数据进行变更。
    	AOF(append only file)只追加文件,记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
    

    1)AOF原理

    1.客户端的请求写命令会被append追加到AOF缓冲区内;
    
    2.AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;
    
    3.AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;
    
    4.Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;
    

    2) AOF配置

    开启了AOF之后,RDB就默认不使用了。使用下面的配置开启AOF以及策略。(如果使用AOF,推荐选择always方式持久化,否则在高并发场景下,每秒钟会有几万甚至百万条请求,如果使用everysec的方式的话,万一服务器挂了那几万条数据就丢失了)。
    
    #开启AOF持久化
    appendonly yes
    
    #AOF文件名
    appendfilename "appendonly.aof"
    
    #AOF文件存储路径 与RDB是同一个参数
    dir "/opt/app/redis6/data"
    
    #AOF策略,一般都是选择第一种[always:每个命令都记录],[everysec:每秒记录一次],[no:看机器的心情高兴了就记录]
    
    appendfsync always
    #appendfsync everysec
    # appendfsync no
    
    #aof文件大小比起上次重写时的大小,增长100%(配置可以大于100%)时,触发重写。[假如上次重写后大小为10MB,当AOF文件达到20MB时也会再次触发重写,以此类推]
    auto-aof-rewrite-percentage 100 
    
    #aof文件大小超过64MB时,触发重写
    auto-aof-rewrite-min-size 64mb 
    
    #是否在后台写时同步单写,默认值no(表示需要同步).这里的后台写,表示后台正在重写文件(包括bgsave和bgrewriteaof.bgrewriteaof网上很多资料都没有涉及到。其实关掉bgsave之后,主要的即是aof重写文件了).no表示新的主进程的set操作会被阻塞掉,而yes表示新的主进程的set不会被阻塞,待整个后台写完成之后再将这部分set操作同步到aof文件中。但这可能会存在数据丢失的风险(机率很小),如果对性能有要求,可以设置为yes,仅在后台写时会异步处理命令.
    no-appendfsync-on-rewrite no
    
    # 指redis在恢复时,会忽略最后一条可能存在问题的指令。默认值yes。即在aof写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败.
    aof-load-truncated
    

    3)AOF持久化策略

    AOF分别有三种备份策略,分别是[always:每个命令都记录],[everysec:每秒记录一次],[no:看机器的心情高兴了就记录],针对这三种策略给出如下说明。
    

    4)策略说明

    策略 说明 优点
    always 每次执行,都会持久化到AOF文件中 不丢失数据
    everysec 每秒持久化一次 减少IO
    no 根据服务器性能持久化 全自动

    5)策略抉择

    命令 Always Everysec no
    优点 不丢失数据 每秒一次fsync,减少IO 不用管,全自动
    缺点 IO开销大 丢1秒钟的数据 不可控

    6)AOF模式的优点

    1.使用AOF Redis会更具有可持久性(durable):你可以有很多不同的fsync策略:没有fsync,每秒fsync,每次请求时fsync。使用默认的每秒fsync策略,写性能也仍然很不错(fsync是由后台线程完成的,主线程继续努力地执行写请求),即便你也就仅仅只损失一秒钟的写数据。
    2.AOF日志是一个追加文件,所以不需要定位,在断电时也没有损坏问题。即使由于某种原因文件末尾是一个写到一半的命令(磁盘满或者其他原因),redis-check-aof工具也可以很轻易的修复。
    3.当AOF文件变得很大时,Redis会自动在后台进行重写。重写是绝对安全的,因为Redis继续往旧的文件中追加,使用创建当前数据集所需的最小操作集合来创建一个全新的文件,一旦第二个文件创建完毕,Redis就会切换这两个文件,并开始往新文件追加。
    4.AOF文件里面包含一个接一个的操作,以易于理解和解析的格式存储。你也可以轻易的导出一个AOF文件。例如,即使你不小心错误地使用FLUSHALL命令清空一切,如果此时并没有执行重写,你仍然可以保存你的数据集,你只要停止服务器,删除最后一条命令,然后重启Redis就可以。
    

    7)AOF重写

    1.因为 AOF 的运作方式是不断地将命令追加到文件的末尾,所以随着写入命令的不断增加, AOF 文件的体积也变得越来越大。举个例子,如果你对一个计数器调用了 100 次 INCR ,那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录。然而在实际上,只使用一条 SET 命令已经足以保存计数器的当前值了,其余 99 条记录实际上都是多余的。
    
    2.为了处理这种情况, Redis 支持一种有趣的特性:可以在不断服务客户端的情况下,对 AOF 文件进行重建。执行 BGREWRITEAOF 命令, Redis 将生产一个新的 AOF 文件,这个文件包含重建当前数据集所需的最少命令。
    

    8) AOF重写配置

    配置名 含义
    appendonly 开启AOF持久化功能
    auto-aof-rewrite-min-size 触发重写的最小尺寸
    auto-aof-rewrite-percentage AOF文件增长率
    aof_current_size AOF当前尺寸
    aof_base_size AOF上次启动和重写的尺寸(单位:字节)

    9) AOF重写触发机制

    根据配置,AOF持久化触发机制如下:
    
    1.aof_current_size > auto-aof-rewrite-min-size
    2.(aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage
    

    10) AOF重写流程

    12)AOF持久化缺点

    1.对同样的数据集,AOF文件通常要大于等价的RDB文件。
    2.AOF可能比RDB慢,这取决于准确的fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭fsync,即使在很高的负载下也和RDB一样的快。不过,即使在很大的写负载情况下,RDB还是能提供能好的最大延迟保证。
    3.在过去,我们经历了一些针对特殊命令(例如,像BRPOPLPUSH这样的阻塞命令)的罕见bug,导致在数据加载时无法恢复到保存时的样子。这些bug很罕见,我们也在测试套件中进行了测试,自动随机创造复杂的数据集,然后加载它们以检查一切是否正常,但是,这类bug几乎不可能出现在RDB持久化中。为了说得更清楚一点:Redis AOF是通过递增地更新一个已经存在的状态,像MySQL或者MongoDB一样,而RDB快照是一次又一次地从头开始创造一切,概念上更健壮。
    	但是,
    	1)要注意Redis每次重写AOF时都是以当前数据集中的真实数据从头开始,相对于一直追加的AOF文件(或者一次重写读取老的AOF文件而不是读内存中的数据)对bug的免疫力更强。
    	2)我们还没有收到一份用户在真实世界中检测到崩溃的报告。
    

    13)AOF持久化优缺点总结

    优点:可以最大程度保证数据不丢失
    缺点:日志记录量级比较大
    

    6.RDB与AOF抉择

    1) RDB与AOF比较

    命令 RDB AOF
    启动优先级
    体积
    恢复速度
    数据安全性 丢数据 根据策略的不同,丢数据的情况也不同
    轻重

    2) RDB与AOF之间的优劣势

    #1.RDB的优点
    1.压缩后的二进制文件,适用于备份、全量复制及灾难恢复。
    2.RDB恢复数据性能优于AOF方式。
    
    #2.RDB的缺点
    1.无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
    2.保存后的二进制文件,不同版本直接存在兼容性问题
    
    #3.AOF的优点
    1.以文本形式保存,易读
    2.记录写操作保证数据不丢失
    
    #4.AOF的缺点
    1.存储所有写操作命令,且文件为文本格式保存,未经压缩,文件体积高。
    2.恢复数据时重放AOF中所有代码,恢复性能弱于RDB方式。
    

    7. AOF与RDB混合

    	看了上面的RDB和AOF的介绍后,我们可以发现,使用RDB持久化会有数据丢失的风险,但是恢复速度快,而使用AOF持久化可以保证数据完整性,但恢复数据的时候会很慢。于是从Redis4之后新增了混合AOF和RDB的模式,先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB何AOF两部分恢复数据,即保证了数据完整性,又提高了恢复的性能。
    	
    	开启混合模式后,每当bgrewriteaof命令之后会在AOF文件中以RDB格式写入当前最新的数据,之后的新的写操作继续以AOF的追加形式追加写命令。当redis重启的时候,加载 aof 文件进行恢复数据:先加载 rdb 的部分再加载剩余的 aof部分。
    

    1)混合配置

    修改下面的参数即可开启AOF,RDB混合持久化
    aof-use-rdb-preamble yes
    

    2) 混合模式的使用

    开启混合持久化模式后,重写之后的aof文件里和rdb一样存储二进制的快照数据,继续往redis中进行写操作,后续操作在aof中仍然是以命令的方式追加。因此重写后aof文件由两部分组成,一部分是类似rdb的二进制快照,另一部分是追加的命令文本。
    
    # step: 进入Redis, 写入数据
    [root@alvin-test-os redis]# redis-cli --raw
    127.0.0.1:6379> set name alvin
    OK
    127.0.0.1:6379> set age 18
    OK
    127.0.0.1:6379> set add 上海
    OK
    127.0.0.1:6379> exit
    # Step 2: 查看备份文件
    
    [root@alvin-test-os redis]# ll data/
    总用量 8
    -rw-r--r--. 1 root root 121 11月 24 15:39 appendonly.aof
    -rw-r--r--. 1 root root 116 11月 24 15:39 dump.rdb
    
    [root@alvin-test-os redis]# cat data/appendonly.aof | grep add
    add
    [root@alvin-test-os redis]# cat data/appendonly.aof
    *2
    $6
    SELECT
    $1
    0
    *3
    $3
    set
    $4
    name
    $5
    alvin
    *3
    $3
    set
    $3
    age
    $2
    18
    *3
    $3
    set
    $3
    add
    $6
    上海
    
    # Step 3: 启动备份
    [root@alvin-test-os redis]# redis-cli --raw
    127.0.0.1:6379> BGREWRITEAOF
    Background append only file rewriting started
    127.0.0.1:6379> exit
    
    # Step 4: 查看配置文件发现AOF备份文件变成了二进制文件
    [root@alvin-test-os redis]# cat data/appendonly.aof
    REDIS0009�  redis-ver6.0.9�
    �edis-bits�@�ctime��_used-mem��4
     aof-preamble���namealvinadd上海age���6����&[root@alvin-test-os redis]#
    
    # Step 5: 再次写入文件
    [root@alvin-test-os redis]# redis-cli --raw
    127.0.0.1:6379> set company 上海
    OK
    127.0.0.1:6379> exit
    
    # Step 6:再次查看备份文件发现被分成了两份,一份二进制,一份AOF备份
    [root@alvin-test-os redis]# cat data/appendonly.aof
    REDIS0009�  redis-ver6.0.9�
    �edis-bits�@�ctime��_used-mem��4
     aof-preamble���namealvinadd上海age���6����&*2
    $6
    SELECT
    $1
    0
    *3
    $3
    set
    $7
    company
    $15
    上海
    [root@alvin-test-os redis]#
    

    3)备份Redis数据

    1.Redis 对于数据备份是非常友好的,因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建,就不会进行任何修改。
    2.当服务器要创建一个新的 RDB 文件时,它先将文件的内容保存在一个临时文件里面,当临时文件写入完毕时,程序才使用临时文件替换原来的 RDB 文件。
    3.这也就是说,无论何时, 复制 RDB 文件都是绝对安全的。
    
    #以下是我们的建议:
    1.创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
    2.确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
    3.至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。
    

    4)RDB持久化高级配置

    #编辑配置文件
    [root@db01 redis]# vim /etc/redis/6379/redis.conf
    #后台备份进程出错时,主进程停不停止写入? 主进程不停止容易造成数据不一致
    stop-writes-on-bgsave-error yes
    #导出的rdb文件是否压缩 如果rdb的大小很大的话建议这么做
    rdbcompression yes
    #导入rbd恢复时数据时,要不要检验rdb的完整性 验证版本是不是一致
    rdbchecksum yes
    

    5)AOF持久化高级配置

    #编辑配置文件
    [root@db01 redis]# vim /etc/redis/6379/redis.conf
    #正在导出rdb快照的过程中,要不要停止同步aof
    no-appendfsync-on-rewrite yes
    #aof文件大小比起上次重写时的大小,增长率100%时重写,缺点:业务开始的时候,会重复重写多次
    auto-aof-rewrite-percentage 100
    #aof文件,至少超过64M时,重写
    auto-aof-rewrite-min-size 64mb
    

    五、数据类型

    1.Redis数据结构之字符串

    Redis的String类型可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。
    

    1) 命令行模式

    进入命令行模式:
    #a 输入密码
    redis-cli -a password_value
     
    #raw 避免中文显示乱码
    redis-cli -a password_value --raw
    

    2) 查看命令帮助

    127.0.0.1:6379> help @string
    
      APPEND key value
      summary: Append a value to a key
      since: 2.0.0
    
      BITCOUNT key [start end]
      summary: Count set bits in a string
      since: 2.6.0
    
      BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
    
    

    3) Exists

    #查看key是否存在,返回true / false(0/1)
    
    127.0.0.1:6379> EXISTS a
    1
    127.0.0.1:6379> EXISTS b
    0
    

    4)TTL

    #查看数据过期时间
    
    127.0.0.1:6379> ttl a
    -1 		# 永不过期
    
    127.0.0.1:6379> ttl b
    (integer) 2 	# 过期时间还有2个单位
    

    5)增加数据

    增加数据的命令有以下几个:set,setex,psetex,setnx。
    
    #ex为多少秒过期 px为多少毫秒过期,nx为若不存在才创建,xx为若存在才覆盖创建
    set key value [ex seconds] [px milliseconds] [nx|xx]
    
    1.使用set命令新增一个键值对及其EX,PX用法
    # 设置
    127.0.0.1:6379> set name 金辉
    OK
    127.0.0.1:6379> get name
    金辉
    
    # 设置过期时间为秒
    127.0.0.1:6379> set name 金辉 ex 10
    OK
    127.0.0.1:6379> ttl name
    6
    127.0.0.1:6379> ttl name
    -2 
    
    # set 和 ex合并成setex
    127.0.0.1:6379> SETEX name 10 金辉
    OK
    127.0.0.1:6379> ttl name
    5
    127.0.0.1:6379> ttl name
    -2
    
    # 设置过期时间为毫秒
    127.0.0.1:6379> set name 金辉 px 10
    OK
    127.0.0.1:6379> TTL name
    -2
    
    # set 和 px 合并使用
    127.0.0.1:6379> PSETEX name 100 金辉
    OK
    127.0.0.1:6379> ttl name
    -2
    
    2.使用set命令新增一个键值对及其NX,XX用法
    Nx:当key不存在时创建,已存在则忽略。
    Xx:当key存在则更新,不存在则忽略。
    
    # nx
    127.0.0.1:6379> set name alvin nx
    OK
    127.0.0.1:6379> get name
    alvin
    127.0.0.1:6379> set name 金辉
    OK
    127.0.0.1:6379> get name
    金辉
    127.0.0.1:6379> set name alvin nx
    
    127.0.0.1:6379> get name
    金辉
    
    # set 与 nx 合并使用
    127.0.0.1:6379> setnx name alvin
    (integer) 0
    127.0.0.1:6379> get name
    金辉
    
    3.批量增加
    同时定义多个键值对,mset也可以和nx一起用。
    mset key1 value1 [key2 value2...] #批量创建kv,已存在的会被更新
    msetnx key1 value1 [key2 value2...] #批量创建kv,所有key不存在才会创建
    
    127.0.0.1:6379> mset k1 a k2 b k3 c
    OK
    127.0.0.1:6379> mget k1 k2 k3
    1) "a"
    2) "b"
    3) "c"
    

    6) 删除数据

    DDL			#删除数据
    
    使用del命令删除数据,可批量可单个删除。
    
    #格式
    del key1 [key2 key3...]
    
    #案例
    127.0.0.1:6379> del k1 k2 k3
    (integer) 3
    127.0.0.1:6379> del name_xx
    (integer) 1
    127.0.0.1:6379> mget k1 k2 k3 name_xx name_nx
    1) (nil)
    2) (nil)
    3) (nil)
    4) (nil)
    5) "wyk"
    

    7)更改数据

    #1.使用set命令修改数据
    127.0.0.1:6379> set name alvin
    OK
    127.0.0.1:6379> get name
    "alvin"
    127.0.0.1:6379> set name alvin
    OK
    127.0.0.1:6379> get name
    "alvin"
    
    #2.使用getset命令修改数据
    等同于get+set,执行此命令返回get的结果,然后将该key更新为新的value,下次再get的时候查到的就是新的value。
    127.0.0.1:6379> GETSET name alvin
    金辉
    127.0.0.1:6379>
    
    #3.使用setrange按下标更新数据
    对指定下标的字符串进行更新,下标从0开始算起。
    127.0.0.1:6379> SETRANGE name 5 alvin
    10
    127.0.0.1:6379> get name
    alvinalvin
    

    8)查找数据

    #1.查看所有的key
    查看所有的Key,在数据量大的Redis中慎用,容易卡死。
    127.0.0.1:6379> KEYS *
    1) "name"
    2) "a"
    
    #2.根据key获取数据
    使用get获得指定key的value。
    127.0.0.1:6379> get key
    
    #3.批量获得指定keys的values
    mget key1 [key2 key3...]
    127.0.0.1:6379> MGET a name
    b
    alvinalvin
    127.0.0.1:6379>
    
    #4.从字符串的指定开始结束下标截取字符串
    getrange key start end
    127.0.0.1:6379> GETRANGE name 1 4
    lvin
    127.0.0.1:6379>
    

    9)计数

    #1.指定key递增
    对指定的key的value加1,递增步长默认1,如果key不存在,其初始值为0,在incr之后其值为1,如果value的值不能转为整型,如hello,该操作将执行失败并返回相应的错误信息。
    
    127.0.0.1:6379> INCR num
    1
    127.0.0.1:6379> INCR num
    2
    
    #2.指定key递减
    对指定的key的value减1,递减步长默认1,如果key不存在,其初始值为0,在decr之后其值为-1,如果value的值不能转为整型,如hello,该操作将执行失败并返回相应的错误信息。
    
    127.0.0.1:6379> DECR num
    1
    127.0.0.1:6379> DECR num
    0
    
    #3.递增指定长度
    对指定的key的value加指定的步长,递增步长可指定,如果key不存在,其初始值为0,在incrby之后其值为步长,如果value的值不能转为整型,如hello,该操作将执行失败并返回相应的错误信息。
    
    $步长increment为整数,当为负数时效果等于递减
    incrby key increment
    
    #4.递减指定长度
    对指定的key的value减指定的步长,递减步长可指定,如果key不存在,其初始值为0,在decrby之后其值为步长的负数,如果value的值不能转为整型,如hello,该操作将执行失败并返回相应的错误信息。
    
    $步长increment为整数,当为负数时效果等于递増
    
    decrby key increment
    
    redis> SET count 100
    OK
    
    redis> DECRBY count 20
    (integer) 80
    

    10) 追加

    #在字符串最后面追加子串
    append key value
    
    # 对不存在的 key 执行 APPEND
    ## 确保 myphone 不存在
    redis> EXISTS myphone
    (integer) 0
    
    # 对不存在的 key 进行 APPEND ,等同于 SET myphone "nokia"
    ## 字符长度
    redis> APPEND myphone "nokia" 
    (integer) 5
    
    # 对已存在的字符串进行 APPEND
    ## 长度从 5 个字符增加到 12 个字符
    redis> APPEND myphone " - 1110" 
    (integer) 12
    
    redis> GET myphone
    "nokia - 1110"
    

    11) 长度

    #返回字符的长度
    
    strlen key
    

    2.Redis数据结构之哈希

    哈希类型是指键值对里的value本身存储的也是一个个的KV键值对,类似于python中的dict和java中的map集合。
    

    1)查看命令帮助

    not connected> help @hash
    
      HDEL key field [field ...]
      summary: Delete one or more hash fields
      since: 2.0.0
    
      HEXISTS key field
      summary: Determine if a hash field exists
      since: 2.0.0
    

    2) 查看hash类型的key中指定的field是否存在

    hexists key field
    127.0.0.1:6379> HEXISTS csdn name
    1
    
    127.0.0.1:6379> HEXISTS csdn company
    1
    

    3) 设置hash类型的单个field或一次性设置多个field

    HSET key field value [field value ...]
     
    hset csdn id 1 name Alvin company 上海
    

    4) 只有value中不存在的field才会被创建

    HSETNX key field value
    

    5) 删除数据

    #使用hdel命令删除hash类型的value中的fields,可批量可单个删除
    HDEL key field1 [field2 ...]
    
    127.0.0.1:6379> HDEL csdn name
    1
    127.0.0.1:6379> HEXISTS csdn name
    0
    

    6)更改数据

    #对hash类型中相同的field进行set操作会更新该field的值
    HSET key field value [field value ...]
    

    7) 查找数据

    #1.使用hget获取指定hash类型的field对应的值
    HGET key field
    
    127.0.0.1:6379> HGET csdn company
    上海
    
    #2.使用hmget获取指定hash类型的多个field对应的值
    HMGET key field [field ...]
    
    127.0.0.1:6379> HMGET csdn company id
    上海
    1
    
    #3.使用hgetall获得指定hash类型对象的全部field和对应的value值
    HGETALL key
    
    127.0.0.1:6379> HGETALL csdn
    id
    1
    company
    上海
    
    #4.使用hkeys获得指定hash类型对象的全部field
    HKEYS key
    
    127.0.0.1:6379> HKEYS csdn
    id
    company
    
    #5.使用hvals获得指定hash类型对象的全部field的values值
    HVALS key
    
    127.0.0.1:6379> HVALS csdn
    1
    上海
    

    8) 计数

    #1.hincrby可以对hash对象的指定的field的value做递增操作
    与string类型中的incrby类似,hincrby可以对hash对象的指定的field的value做递增操作,increment必须是整数(hash类型中没有hdecrby方法,当increment为负数时为递减操作),value必须是integer类型,否则会报对应的错误。
    HINCRBY key field increment
    
    ps:filed对应的value必须是integer类型,increment必须是整数,可以为负
    
    127.0.0.1:6379> HINCRBY csdn  id 10
    11
    
    #2.hincrbyfloat可以对hash对象的指定的field的value做递增操作
    与string类型中的incrbyfloat类似,hincrbyfloat可以对hash对象的指定的field的value做递增操作,increment可以是整数或浮点数(hash类型中没有hdecrbyfloat方法,当increment为负数时为递减操作),value必须是数字类型,否则会报对应的错误。
    HINCRBYFLOAT key field increment
    
    ps:filed对应的value必须是数字类型,increment可以是整数或浮点,可以为负
    
    127.0.0.1:6379> HINCRBYFLOAT csdn id 10.9
    21.9
    

    9) 长度

    #1.hlen返回hash类型中field的数量
    HLEN key
    
    127.0.0.1:6379> HLEN csdn
    2
    
    #2.hstrlen返回hash类型中指定filed对应的value的字符长度
    HSTRLEN key field
    
    127.0.0.1:6379> HSTRLEN csdn id
    4
    127.0.0.1:6379> HSTRLEN csdn company
    15
    

    10) 过期

    #我们可以看到hash类型没有hsetex hpsetex一类的方法,想对hash对象做过期策略可以使用全局函数expire。
    expire key seconds
    
    127.0.0.1:6379> EXPIRE csdn 1000
    1
    127.0.0.1:6379> ttl csdn
    987
    

    3.Redis数据结构之列表

    Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
    

    1)查看命令帮助

    help @list
    
      BLPOP key [key ...] timeout
      summary: Remove and get the first element in a list, or block until one is available
      since: 2.0.0
    
      BRPOP key [key ...] timeout
      summary: Remove and get the last element in a list, or block until one is available
      since: 2.0.0
    

    2)从左边插入元素

    从左边插入元素,从左边依次追加进栈,先进后出,后进先出
    LPUSH key element [element ...]
     
    127.0.0.1:6379> LPUSH mylist alvin 18
    3
    127.0.0.1:6379> LPUSH mylist 上海
    4
    127.0.0.1:6379> LRANGE mylist 0 -1
    上海
    18
    alvin
    127.0.0.1:6379>
    

    3)从左边插入元素

    从右边插入元素,从右边依次追加进队列,先进先出,后进后出。
    RPUSH key element [element ...]
     
    127.0.0.1:6379> RPUSH mylist linux
    5
    127.0.0.1:6379> RPUSH mylist python
    6
    127.0.0.1:6379> LRANGE mylist 0 -1
    上海
    18
    alvin
    上海市
    linux
    python
    

    4) list存在时才会从左边依次追加元素

    #与sting类型中的nx类似,只有当list存在时才会从左边依次追加元素。
    
    LPUSHX key element [element ...]
    
    127.0.0.1:6379> LPUSHX mylist Shanghai
    7
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    18
    alvin
    上海市
    linux
    python
    127.0.0.1:6379> LPUSHX testlist Shanghai
    0
    127.0.0.1:6379> LRANGE testlist 0 -1
    
    127.0.0.1:6379>
    

    5)当list存在时才会从右边依次追加元素

    #与lpushx类似,只有当list存在时才会从右边依次追加元素。
    RPUSHX key element [element ...]
    
    127.0.0.1:6379> RPUSHX mylist QingPu
    8
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    18
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379> RPUSHX testlist QingPu
    0
    127.0.0.1:6379> LRANGE testlist 0 -1
    
    127.0.0.1:6379>
    

    6) 从list中指定的元素的前/后 插入一个新元素

    LINSERT key BEFORE|AFTER pivot element
    
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    18
    alvin
    上海市
    linux
    python
    QingPu
    
    # 在某个KEY之前插入某个值
    127.0.0.1:6379> LINSERT mylist before 18 17
    9
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    17
    18
    alvin
    上海市
    linux
    python
    QingPu
    
    # 在某个值后面添加一个值
    127.0.0.1:6379> LINSERT mylist after 18 16
    10
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    17
    18
    16
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379>
    

    7) 删除数据

    #1.从列表左侧开始移除
    LREM key count element
    
    127.0.0.1:6379> LINSERT mylist after 18 16
    14
    127.0.0.1:6379> LINSERT mylist after 18 16
    15
    127.0.0.1:6379> LINSERT mylist after 18 16
    16
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    17
    17
    17
    17
    18
    16
    16
    16
    16
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379> LREM mylist 2 16
    2
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    17
    17
    17
    17
    18
    16
    16
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379>
    

    8) 修改数据

    #1.修改元素内容
    LSET key index element
    
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    17
    17
    17
    17
    18
    16
    16
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379> LSET mylist 2 19
    OK
    127.0.0.1:6379> LRANGE mylist 0 -1
    Shanghai
    上海
    19
    17
    17
    17
    18
    16
    16
    alvin
    上海市
    linux
    python
    QingPu
    127.0.0.1:6379>
    
    #2.截取为从下标start到下标stop闭区间的列表
    将原列表截取为从下标start到下标stop闭区间的列表,即原列表变为一个第start+1个到第stop+1个元素的列表。
    LTRIM key start stop
    
    127.0.0.1:6379> LTRIM mylist 2 8
    OK
    127.0.0.1:6379> LRANGE mylist 0 -1
    19
    17
    17
    17
    18
    16
    16
    127.0.0.1:6379>
    

    9) 查询数据

    #1.查看列表中元素的个数
    LLEN key
    
    127.0.0.1:6379> LLEN mylist
    7
    127.0.0.1:6379>
    
    #2.根据起止下标查询列表元素
    LRANGE key start stop
     
    lrange key 0 -1 #表示查看全部元素
    lrange key -1 -1 #表示查看最右边的元素
    
    #3.根据指定的index下标查看列表中的元素
    LINDEX key index
    
    127.0.0.1:6379> LINDEX mylist 3
    17
    127.0.0.1:6379>
    
    #4.从左边消费列表中的元素
    从左边消费列表中的元素,消费完之后从列表中删除。
    
    LPOP key
    
    127.0.0.1:6379> LRANGE mylist 0 -1
    17
    17
    17
    18
    16
    16
    127.0.0.1:6379> LPOP mylist
    17
    127.0.0.1:6379> LRANGE mylist 0 -1
    17
    17
    18
    16
    16
    127.0.0.1:6379>
    
    #5.从右边消费列表中的元素
    从右边消费列表中的元素,消费完之后从列表中删除。
    RPOP key
    
    127.0.0.1:6379> LRANGE mylist 0 -1
    17
    17
    18
    16
    16
    127.0.0.1:6379> RPOP mylist
    16
    127.0.0.1:6379> LRANGE mylist 0 -1
    17
    17
    18
    16
    127.0.0.1:6379>
    
    #6.消费列表最右边的元素并返回
    消费列表A的最右边的元素返回,然后追加到列表B的最左边。
    RPOPLPUSH source destination
     
    RPOPLPUSH List_A List_B
    
    127.0.0.1:6379> LRANGE mylist 0 -1
    17
    17
    18
    16
    127.0.0.1:6379> RPOPLPUSH mylist mylist
    16
    127.0.0.1:6379> LRANGE mylist 0 -1
    16
    17
    17
    18
    127.0.0.1:6379>
    
    #7.从列表中左侧查询元素
    从列表中左侧查询元素,返回列表的key和左侧第一个元素,若所有查询的列表中都没有元素,则会阻塞等待至设置的timeout秒之后返回空,若在这期间,这些列表新增了元素,则会立刻消费并返回该元素。
    BLPOP key [key ...] timeout
    
    127.0.0.1:6379> BLPOP mylist 10
    mylist
    16
    127.0.0.1:6379> BLPOP mylist 10
    mylist
    17
    127.0.0.1:6379> BLPOP mylist 10
    mylist
    17
    127.0.0.1:6379> BLPOP mylist 10
    mylist
    18
    127.0.0.1:6379> BLPOP mylist 10
    
    # 从列表右侧开始消费
    

    4.Redis数据结构之无序集合

    Redis 的 Set 是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
    

    1) 查看帮助命令

    #使用Redis命令手册查看
    127.0.0.1:6379> help @set
    

    2) 增加数据

    7.2.1、	给集合内新增成员
    给集合内新增成员,若集合不存在则创建集合并新增成员。
    
    SADD key member [member ...]
    
    127.0.0.1:6379> sadd myset 1
    1
    127.0.0.1:6379> sadd myset 2
    1
    127.0.0.1:6379> sadd myset 3
    1
    127.0.0.1:6379> sadd myset 4
    1
    127.0.0.1:6379> sadd myset 5
    1
    127.0.0.1:6379> SMEMBERS myset
    1
    2
    3
    4
    5
    127.0.0.1:6379>
    

    3) 删除数据

    #1.从集合中删除指定的成员
    从集合中删除指定的成员,返回删除的个数。
    SREM key member [member ...]
    
    127.0.0.1:6379> SREM myset 3 4
    2
    127.0.0.1:6379> SMEMBERS myset
    1
    2
    5
    127.0.0.1:6379>
    

    4) 修改数据

    #1.移动数据
    127.0.0.1:6379> SADD myset1 1 2 3 4 5
    5
    127.0.0.1:6379> sadd myset2 one two three
    3
    127.0.0.1:6379> SMOVE myset1 myset2 4
    1
    127.0.0.1:6379> SMEMBERS myset1
    1
    2
    3
    5
    127.0.0.1:6379> SMEMBERS myset2
    4
    three
    two
    one
    127.0.0.1:6379>
    

    5) 查看数据

    #1.查看集合中所有的成员
    SMEMBERS key
    
    127.0.0.1:6379> SMEMBERS myset2
    4
    three
    two
    one
    
    #2.返回集合中成员的个数
    SCARD key
    
    127.0.0.1:6379> SMEMBERS myset2
    4
    three
    two
    one
    127.0.0.1:6379> SCARD myset2
    4
    
    #3.从集合中随机返回指定个数的成员
    
    SRANDMEMBER key [count]
    
    127.0.0.1:6379> SRANDMEMBER myset1 2
    3
    2
    127.0.0.1:6379> SRANDMEMBER myset1 2
    1
    5
    
    #4.判断对象是否是集合中的成员
    SISMEMBER key member
    
    127.0.0.1:6379> SISMEMBER myset1 6
    0
    127.0.0.1:6379> SISMEMBER myset1 3
    1
    
    #5.随机返回一个成员
    从集合中随机弹出一个成员,返回该成员并从集合中删除该成员。
    
    SPOP key
    
    127.0.0.1:6379> SPOP myset1
    2
    127.0.0.1:6379> SPOP myset2
    4
    127.0.0.1:6379> SPOP myset2
    one
    127.0.0.1:6379> SPOP myset2
    two
    127.0.0.1:6379> SPOP myset2 2
    three
    

    6) 交集

    #1.取多个集合的交集
    取多个集合的交集,返回这些集合中共同拥有的成员。
    
    SINTER key [key ...]
    
    127.0.0.1:6379> sadd myseta 1 2 3 4 5
    5
    127.0.0.1:6379> sadd mysetb 4 5 6 7 8
    5
    127.0.0.1:6379> sadd mysetc 5 6 7 8 9
    5
    127.0.0.1:6379> SINTER myseta mysetb mysetc
    5
    
    #2.将多个集合的交集的结果保存为一个新的集合
    将多个集合的交集的结果保存为一个新的集合destination  ,返回新集合的成员个数。
    SINTERSTORE destination key [key ...]
    
    127.0.0.1:6379> SINTERSTORE mysetc mysetb myseta
    4
    127.0.0.1:6379> SMEMBERS mysetc
    5
    6
    7
    8
    127.0.0.1:6379> SMEMBERS mysetb
    4
    5
    6
    7
    8
    127.0.0.1:6379> SMEMBERS myseta
    5
    6
    7
    8
    127.0.0.1:6379>
    

    7) 并集

    #1.取多个集合的并集
    取多个集合的并集,相同的成员会被去重。
    SUNION key [key ...]
    
    127.0.0.1:6379> SADD myset_a 1 2 3 4 5
    5
    127.0.0.1:6379> sadd myset_b 3 4 5 6 7
    5
    127.0.0.1:6379> SUNION myset_a myset_b
    1
    2
    3
    4
    5
    6
    7
    127.0.0.1:6379>
    
    #2.将多个集合的并集的结果保存为一个新的集合
    SUNIONSTORE destination key [key ...]
    
    127.0.0.1:6379> SUNIONSTORE new_myset myset_a myset_b
    7
    127.0.0.1:6379> SMEMBERS new_myset
    1
    2
    3
    4
    5
    6
    7
    127.0.0.1:6379>
    

    8) 差集

    #1.取多个集合的差集
    取多个集合的差集,以最左边的为主集合,返回左集合中有而其他集合没有的成员。
    127.0.0.1:6379> SDIFF myset_a myset_b
    1
    2
    127.0.0.1:6379> SMEMBERS myset_a
    1
    2
    3
    4
    5
    127.0.0.1:6379> SMEMBERS myset_b
    3
    4
    5
    6
    7
    

    9) 将多个集合的差集的结果保存为一个新的集合

    #将多个集合的差集的结果保存为一个新的集合 ,返回新集合的成员个数 。
    SDIFFSTORE destination key [key ...]
    
    127.0.0.1:6379> SDIFFSTORE myset_sdiff myset_a myset_b
    2
    127.0.0.1:6379> SMEMBERS myset_sdiff
    1
    2
    127.0.0.1:6379>
    
    

    5.Redis数据结构之有序集合

    	Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
    

    1) 查看命令帮助

    127.0.0.1:6379> help @sorted_set
    

    2) 增加数据

    往有序集合中新增成员,需要指定该成员的分数,分数可以是整形或浮点型,当分数相同时候,索引下标按照字典排序。
    
    127.0.0.1:6379> ZADD myzset 1 alvin
    1
    127.0.0.1:6379> ZADD myzset 2 shanghai 3 beijing
    2
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    shanghai
    beijing
    

    3)查询数据

    #1.获取有序集合的成员数
    ZCARD key
    
    127.0.0.1:6379> ZCARD myzset
    3
    127.0.0.1:6379>
    
    #2.获取指定分数区间内的成员数
    从有序集合内获取指定分数区间内的成员数。
    ZCOUNT key min max
    
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    shanghai
    beijing
    127.0.0.1:6379> ZCOUNT myzset 1 2
    2
    127.0.0.1:6379>
    
    #3.字典排序
    根据字典排序返回min ,max之间的数据量.
    ZLEXCOUNT key min max
    
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    shanghai
    beijing
    127.0.0.1:6379> ZLEXCOUNT myzset [al [zzz
    3
    127.0.0.1:6379>
    
    #4.获取成员的分数值
    返回有序集中,成员的分数值,不存在的成员返回空。
    
    ZSCORE key member
    
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    shanghai
    beijing
    127.0.0.1:6379> ZSCORE myzset shanghai
    2
    
    #5.	127.0.0.1:6379> ZSCAN myzset 0 match "sh*"
    0
    shanghai
    2
    127.0.0.1:6379> ZSCAN myzset 0 match "al*"
    0
    alvin
    1
    

    5)删除数据

    #1.移除指定的成员
    ZREM key member [member ...]
    
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    shanghai
    beijing
    127.0.0.1:6379> ZREM myzset shanghai
    1
    127.0.0.1:6379> ZRANGE myzset 0 -1
    alvin
    beijing
    127.0.0.1:6379>
    

    6.Redis基础命令之常用命令

    1) 查看所有key

    127.0.0.1:6379> KEYS *
    

    2) 查看key的类型

    127.0.0.1:6379> TYPE myset1
    set
    127.0.0.1:6379> TYPE a
    string
    

    3) 随机返回一个key

    127.0.0.1:6379> RANDOMKEY
    myset_sdiff
    127.0.0.1:6379> RANDOMKEY
    new_myset
    127.0.0.1:6379> RANDOMKEY
    myset
    

    4) 删除key

    返回删除状态1/0,True/False。
    del key [key2 key3 key4...]
    

    5) 判断一个key是否存在

    返回状态1/0,True/False,当传入多个key时返回or的结果,即只要有一个存在就返回True。
    exists key [key ...]
    

    6) 重命名一个key

    127.0.0.1:6379> RENAME myset mysets
    OK
    127.0.0.1:6379>
    

    7) 查看key的剩余生存时间

    #1.以秒为单位
    ttl key
    127.0.0.1:6379> ttl mysets
    -1	# -1代表永不过期
    
    #2.以毫秒为单位
    Pttl key
    127.0.0.1:6379> PTTL a
    -1	# -1代表永不过期
    
  • 相关阅读:
    iOS多线程开发小demo5 线程间的通信
    iOS多线程开发小demo4,线程的同步问题
    iOS多线程开发小demo3,线程的状态
    iOS多线程开发小demo2,NSThread篇
    iOS多线程开发小demo
    iOS开发多线程基础知识
    sublime text 3 3083 注册码
    Canvas现实画板功能
    CSS3动画进度条
    移动端使用HTML5表单增强体验
  • 原文地址:https://www.cnblogs.com/jhno1/p/14999338.html
Copyright © 2011-2022 走看看