音乐播放器
琢钰
 
文章 标签
12

Powered by X2 | Theme: Fog
载入天数...
载入时分秒...
总访问量:  |   访问人数:
御风飞行中...

Redis

  热度: loading...

一、NoSql入门和概述

  • NoSQL(Not Only SQL),不仅仅是SQL,泛指非关系型数据库。
  • NoSQL不依赖业务逻辑方式存储,而以简单地key-value模式存储,大大增加了数据库的扩展能力。
  • NOSQL不遵循SQL标准。
  • 不支持ACID。
  • 远超于SQL的性能。

适用场景

  • 对数据高并发的读写
  • 海量数据的读写
  • 对数据有高可扩展性要求

不适用于需要事务支持和即席查询(条件查询)的场景。

缓存数据库

主要的缓存数据库有:

  • Memcached
  • Redis
  • MangoDB
  • HBase (Hadoop)
  • Cassandra (Apache)
  • Neo4J

只有ManggoDB可替代关系型数据库。

Memcached与Redis的区别:

  • Redis是可持久化的,Memcached一般不持久化。
  • Memcached只支持简单的key-value模式,Redis还支持多种数据结构的存储。
  • Memcached使用的是多线程+锁,Redis使用的是单线程+多路IO复用。

二、Redis安装

2.1 步骤

  1. 下载Redis安装包

  2. 解压

    tar -zxvf redis-3.2.5.tar.gz
    
  3. 进入目录

    cd redis-6.0.5/
    
  4. 进行编译

    make
    

    如果报错,需要安装gcc和gcc-c++

    yum install gcc
    yum install gcc-c++
    make distclean
    
  5. 安装

    make install
    

2.2 目录介绍

image-20200703213526049
  • redis-benchmark:性能测试工具
  • redis-check-aof:修复有问题的AOF文件
  • redis-check-rdb:修复有问题的dump.rdb文件
  • redis-cli:客户端操作入口
  • redis-sentinel:Redis集群使用
  • redis-server:Redis服务器启动命令
image-20200703214210259

2.3 启动Redis

  1. 备份配置文件

    cp redis.conf /opt/myRedis/redis.conf
    
  2. 修改配置文件

    daemonize yes
    
  3. 启动

    redis-server /opt/myRedis/redis.conf
    
  4. 检查是否启动

    [root@xmy329 myRedis]# ps -ef | grep redis
    root      2940     1  0 21:50 ?        00:00:00 redis-server 127.0.0.1:6379
    root      2951  2570  0 21:50 pts/0    00:00:00 grep --color=auto redis
    
  5. 用客户端访问

    [root@xmy329 myRedis]# redis-cli
    127.0.0.1:6379> exit
    [root@xmy329 myRedis]# redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> 
    
  6. 测试验证

    [root@xmy329 myRedis]# redis-cli
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> 
    

为什么Redis的端口号是6379?

6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被antirez及其朋友当作愚蠢的代名词。Redis作者antirez同学在twitter上说将在下一篇博文中向大家解释为什么他选择6379作为默认端口号。

GHS

2.4 相关知识

  • 默认16个数据库,类似数组下标从0开始,初始默认使用0号库,使用select index 切换数据库
  • 同一密码管理,所有库都是同一个密码,要么都OK要么一个都连不上
  • Redis是单线程+多路IO复用技术

作者:levonfly
链接:https://www.zhihu.com/question/32163005/answer/300165049
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

IO模式一般分为同步IO和异步IO. 同步IO会阻塞进程, 异步IO不会阻塞进程. 目前linux上大部分用的是同步IO, 异步IO在linux上目前还不成熟, 不过windows的iocp算是真正的异步IO。

同步IO又分为阻塞IO, 非阻塞IO, IO多路复用. What? 同步IO明明会阻塞进程,为什么也包括非阻塞IO? 因为非阻塞IO虽然在请求数据时不阻塞, 但真正数据来临时,也就是内核数据拷贝到用户数据时, 此时进程是阻塞的.

那么这些IO模式的区别分别是什么? 接下来举个小例子来说明. 假设你现在去女生宿舍楼找自己的女神, 但是你只知道女神的手机号,并不知道女神的具体房间

先说同步IO的情况,

  1. 阻塞IO, 给女神发一条短信, 说我来找你了, 然后就默默的一直等着女神下楼, 这个期间除了等待你不会做其他事情, 属于备胎做法.

  2. 非阻塞IO, 给女神发短信, 如果不回, 接着再发, 一直发到女神下楼, 这个期间你可以在两次发短信间隙喝口水,属于专一做法.

  3. IO多路复用, 是找一个宿管大妈来帮你监视下楼的女生, 这个期间你可以些其他的事情. 例如可以顺便看看其他妹子,玩玩王者荣耀, 上个厕所等等. IO复用又包括 select, poll, epoll 模式. 那么它们的区别是什么?

    3.1 select大妈 每一个女生下楼, select大妈都不知道这个是不是你的女神, 她需要一个一个询问, 并且select大妈能力还有限, 最多一次帮你监视1024个妹子

    3.2 poll大妈不限制盯着女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神

    3.3 epoll大妈不限制盯着女生的数量, 并且也不需要一个一个去问. 那么如何做呢? epoll大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字, 只要女生下楼了, epoll大妈就知道这个是不是你女神了, 然后大妈再通知你.

上面这些同步IO有一个共同点就是, 当女神走出宿舍门口的时候, 你已经站在宿舍门口等着女神的, 此时你属于阻塞状态

接下来是异步IO的情况

你告诉女神我来了, 然后你就去王者荣耀了, 一直到女神下楼了, 发现找不见你了, 女神再给你打电话通知你, 说我下楼了, 你在哪呢? 这时候你才来到宿舍门口. 此时属于逆袭做法

三、Redis基本指令

3.1 Redis五大数据类型

  • string
  • set
  • list
  • hash
  • zset

指的是键对应的值的类型。

3.2 key

  • keys *:查询当前所有的键
  • exists <key>:判断某个键是否存在
  • type <key>:查看键的类型
  • del <key>:删除键
  • expire <key> <seconds>:为键值设置过期时间,单位为秒
  • ttl <key>:查看还有多少秒过期,-1为永不过期,-2为已过期。
  • dbsize:查看当前数据库key的数量
  • Flushdb:清空当前数据库
  • Flushall:通杀全部库

3.3 String

String类型是二进制安全的,意味着Redis的String可以包含任何数据,比如jpg图片或者序列化的对象。最多可以是512M。

  • get <key>:查询对应键值
  • set <key> <value>:添加键值对
  • append <key> <value>:将给定的键值后面追加
  • strlen <key>:获取值的长度
  • setnx <key> <value>:只有在键不存在的时候才会赋值。
  • incr <key>:将key中存储的数字值增1,只能对数字值操作
  • decr <key> :将key中存储的数字值减1,只能对数字值操作
  • incrby/decrby <key> <步长>:将key中存储的数字值增/减步长,只能对数字值操作
  • mset <key1> <value1> <key2> <value2> <key3> <value3>:同时设置多个键值对
  • mget <key1> <key2> :同时获取多个value
  • msetnx <key1> <value1> <key2> <value2> <key3> <value3>:当且仅当所有key都不存在时,同时设置多个键值对
  • getrange <key> <起始位置> <结束位置>:获得值的范围,闭区间,类似于substring(包前不包后,左闭右开)
  • setrange <key> <起始位置> <value>:从起始位置开始用value覆写key所存储的字段。
  • setex <key> <过期时间> <value>:在设置键值的同时设置过期时间。
  • getset <key> <value>:设置新值的同时获得旧值。

3.4 List

单键多值。也只能存储string。底层是个双向链表,对两端操作性能很高,通过索引下标的操作中间的节点性能会较差。

  • lpush/rpush <key> <value1> <value2> <value3>:从左边/右边插入一个或多个值。

  • lpop/rpop <key>:从左边/右边吐出一个数据,值在键在,值亡键亡。

  • rpoplpush <key1> <key2> :从<key1>的列表右边吐出一个值插到<key2>列表左边。

  • lrange <key> <start> <stop>:按照索引下标获得元素,从左到右。-1代表最后一个元素。

    lrange testList 0 -1 # 从表头查到表尾
    
  • lindex <key> <index>:按照索引下标获得元素,从左到右。

  • llen <key>:获得列表长度。

  • linsert <key> before/after <value> <newvalue>:在某个值之前/后面插入新的值。

  • irem <key> <n> <value>:从左边删除n个value,0代表删除所有,负整数代表从右往左删,正整数代表从左往右删。

3.5 Set

string类型的无序不可重复集合。底层是一个value为null的hash表。

  • sadd <key> <value1> <value2> <value3>:将一个或多个元素加入到集合key中,已经存在的将被忽略。
  • smembers <key>:取出该集合的所有值
  • sismember <key> <value>:判断key中是否含有该value值。有1无0.
  • scard <key>:返回元素个数。
  • srem <key> <value1> <value2> <value3>:删除集合中的一个或多个元素。
  • spop <key> :随机从该集合中吐出一个值。
  • srandmember <key> <n>:随机从集合中取出n个值,不会从集合中删除。
  • sinter <key1> <key2>:返回两个集合的交集元素。
  • sunion <key1> <key2>:返回两个集合的并集元素。
  • sdiff <key1> <key2>:返回两个集合的差集元素。

3.6 Hash

hash是一个键值对集合。类似于Map<String,String>。

  • hset <key> <field> <value>:给key集合中的field键赋值value。
  • hget <key> <field> :从key几何field中取出value。
  • hmset <key> <field1> <value1> <field2> <value2> :批量设置hash的值。
  • hsetnx <key> <field> <value>:将哈希表key中的域field的值设置为value,当且仅当该field不存在。
  • hexists <key> <field>:查看hash表key中,给定域field是否存在。
  • hkeys <key>:列出该hash集合的所有field。
  • hvals <key>:列出该hash集合的所有value。
  • hincrby <key> <field> <increment>:为哈希表key中的域field的值加上增量increment。
redis-cli --raw #显示中文

3.7 Zset

有序不可重复集合,每个成员都关联了一个评分(score),按照评分从低到高排序,评分可以重复、

  • zadd <key> <score1> <value1> <score2> <value2>:将一个或多个member元素及其score值加入到有序集key中。添加已存在的元素会把分数替换掉。
  • zrange <key> <start> <stop> [WITHSCORES]:返回有序集key中下标在start-stop之间的元素,带withscores,可以让分数一起和值返回到结果集。
  • zrangebyscore <key> <min> <max> [WITHSCORES] [LIMIT] :通过分数返回有序集合指定区间内的成员。
  • zrevrangebyscore <key> <max> <min> [WITHSCORES] [LIMIT] :同上,按从大到小排列。
  • zincrby <key> <increment> <value>:为元素的score加上增量。
  • zrem <key> <value>:删除该集合下指定值的元素。
  • zcount <key> <min> <max>:统计该集合分数区间内的元素个数。
  • zrank <key> <value>:返回该值在集合中的排名,从0开始。

四、Redis相关配置

  • 计量单位说明
  • 大小写不敏感
  • include:多实例的情况,把其他配置文件引入
  • bind:ip地址的绑定,默认情况只允许本机访问,不写的情况下则无限制接受任何IP地址的访问,但在没有设密码的情况下需要关闭protected-mode。
  • tcp-backlog:一个请求到达后直到接受进程处理前的队列。
  • timeout:一个空闲的客户端维持多少秒会关闭,0为永不关闭。
  • TCP keepalive:对访问客户端的一种心跳检测,每隔n秒检测一次。官方推荐设置60秒。
  • daemonize:是否为后台进程。
  • pidfile:存放pid文件的位置。
  • log level:日志级别。
  • logfile:日志文件名称。
  • database:设定库的数量。
  • security:在命令行设置密码。
  • maxclient:最大客户端连接数。
  • maxmemory:设置可以使用的内存量。

五、Jedis

Jedis是Java连接Redis的工具。

  1. 引入依赖

            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.3.0</version>
            </dependency>
    
  2. 编写代码

    public class TestJedis {
    
        public static void main(String[] args) {
            Jedis jedis = new Jedis("119.23.208.64", 6379);
            String ping = jedis.ping();
            System.out.println(ping);
            jedis.set("a", "abc");
            jedis.close();
        }
    }
    

注意在连接时需要把配置文件中的bind注释掉,并且protected-mode设置为no

六、Redis事务

Redis事务的主要作用就是串联多个命令防止其他的命令插队。

6.1 Multi、Exec、Discard

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行,组队的过程中可以通过Discard来放弃组队。

6.2 事务的错误处理

组队中出现了报告错误以后,执行时整个队列都会被取消。

执行时出现错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。

6.3 WATCH <key>

在执行MUTLI之前,先执行watch可以监视一个或多个key,如果在事务执行之前,这些key被其他命令改动,则事务将会被打断。

6.4 三个特性

  • 单独的隔离操作
  • 没有隔离级别的概念
  • 不保证原子性

七、Redis持久化

Redis提供了2个不同形式的持久化方式。

  • RDB (Redis DataBase)
  • AOF (Append Of File)

7.1 RDB

在指定的时间间隔内将内存中的数据集快照写入磁盘。快照文件默认被存储在当前文件夹中,名称为dump.rdb,可以通过dir和dbfilename参数来修改默认值。Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何的IO操作的,这就确保了极高的性能。

  • Fork

    fork的作用相当于复制一个与当前进程一样的进程。但是是一个全新的进程,并作为原进程的子进程

  • 配置文件

    # redis是基于内存的数据库,可以通过设置该值定期写入磁盘。 
    # 注释掉“save”这一行配置项就可以让保存数据库功能失效 
    # 900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)
    # 300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化) 
    # 60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化) 
    save 900 1 
    save 300 10 
    save 60 10000 
    
    #当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作,可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误 
    stop-writes-on-bgsave-error yes 
    
    #使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间 
    rdbcompression yes 
    
    #是否校验rdb文件。从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。 
    rdbchecksum yes
    
    #rdb文件的名称 
    dbfilename dump.rdb 
    
    #数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录 
    dir /data
    
    
  • 触发条件

    1. 通过配置文件中的save条件
    2. 手动通过save和bgsave命令
      • save:save时只管保存,其他不管,全部阻塞
      • bgsave:redis会在后台异步的进行快照操作,同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的事件
    3. 通过flushall命令,也会产生dump.rdb文件,但是里面是空的,无意义。
    4. 通过shutdown命令,安全退出,也会生成快照文件(和异常退出形成对比,比如:kill杀死进程的方式)
  • 如何恢复

    appendonly no 
    dbfilename dump.rdb 
    dir /var/lib/redis #可以自行指定
    
    

    appendonly 设置成no,redis启动时会把/var/lib/redis 目录下的dump.rdb 中的数据恢复。dir 和dbfilename 都可以设置。我测试时appendonly 设置成yes 时候不会将dump.rdb文件中的数据恢复

  • 优劣势

    1. 优势

      1. 恢复数据的速度很快,适合大规模的数据恢复,而又对部分数据不敏感的情况

      2. dump.db文件是一个压缩的二进制文件,文件占用空间小

    2. 劣势

      1. 当出现异常退出时,会丢失最后一次快照后的数据

      2. 当fork的时候,内存的中的数据会被克隆一份,大致两倍的膨胀需要考虑。而且,当数据过大时,fork操作占用过多的系统资源,造成主服务器进程假死。

7.2 AOF

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作补不可记录),只许追加文件但不可以改写文件,redis启动之初会读取改文件重新构建数据。保存的是appendonly.aof文件。AOF机制默认关闭,可以通过appendonly = yes参数开启aof机制,通过appendfilename = myaoffile.aof指定aof文件名称。

  • 如何恢复

    1. 正常恢复

      将文件放到dir指定的文件夹下,当redis启动的时候会自动加载数据,注意:aof文件的优先级比dump大

    2. 异常恢复

      • 有些操作可以直接到appendonly.aof文件里去修改。

        eg:使用了flushall这个命令,此刻持久化文件中就会有这么一条命令记录,把它删掉就可以了

      • 写坏的文件可以通过 redis-check-aof --fix进行修复

  • 同步频率

    • 始终同步
    • 每秒同步
    • 把同步时机交给操作系统
    #aof持久化策略的配置 
    #no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。 
    #always表示每次写入都执行fsync,以保证数据同步到磁盘。
    #everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。 
    appendfsync everysec
    
  • Rewrite

    AOF采用文件追加的方式,文件会越来越大,可以通过这个命令进行重写,Redis会自动压缩到可以恢复数据的最小指令集。使用命令bgrewriteaof。

    # aof自动重写配置。
    # 当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。 
    auto-aof-rewrite-percentage 100 
    # 设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写 
    auto-aof-rewrite-min-size 64mb
    
    
  • 优劣点

    1. 优点
      • 备份机制更稳健,丢失数据概率更低。
      • 可读性强。
    2. 缺点
      • 占用更多的磁盘空间
      • 恢复备份速度慢
      • 有性能压力
      • 存在bug

八、Redis主从复制

主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。

8.1 用处

  • 读写分离,性能扩展
  • 容灾快速恢复

8.2 配置

配从不配主。

  • 从服务器配置
    • 拷贝多个redis.conf文件include
    • 开启daemonize yes
    • pid文件名字
    • 指定端口
    • Log文件名字
    • RDB名字
    • appendonly关掉或者换名字
#配置从库
slaveof 主库ip 主库端口
#查看主从信息
info replication

每次与master断开后,都需要重新连接,除非你配置进redis.conf文件。

8.3 注意点

  1. 与主服务器建立连接是全量复制,之后是增量复制
  2. 主机可以写,但是从机不可以写,从机只能读
  3. 主机shutdowm后从机待机状态,等主机回来后,主机新增记录从机可以顺利复制

8.4 薪火相传

含义:就是上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力。

薪火相传

注意事项和一主二仆差不多,但注意虽然有slave是相对master,但是依然是slave。

8.5 反客为主

SLAVEOF no one

使当前数据库停止与其他数据库的同步,转成主数据库。

8.6 哨兵模式(sentinel)

反客为主的自动版,能够后台监控Master库是否故障,如果故障了根据投票数自动将slave库转换为主库。一组sentinel能同时监控多个Master。

使用步骤

  1. 在Master对应redis.conf同目录下新建sentinel.conf文件。

  2. 配置哨兵,在sentinel.conf文件中填入内容(可以配置多个):

    #说明:最后一个数字1,表示主机挂掉后slave投票看让谁接替成为主机,得票数多少后成为主机。 
    sentinel monitor 被监控数据库名字(自己起名字) ip port 1
    

    选择条件依次为:

    1. 优先级靠前的
    2. 偏移量最大的
    3. runid最小的
  3. 启动哨兵模式

    redis-sentinel  /myredis/sentinel.conf
    

注意:

  1. 当master挂掉后,会通过选票进行选出下一个master。而且只有使用了sentinel.conf启动的才能开启选票。
  2. 当原来的master回来后,很不幸变成了slave。

九、Redis集群

Redis集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N

Redis集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。

JedisCluster