首页 > 技术文章 > redis

meml 2020-04-10 20:39 原文

redis概述(redis基于内存数据库):

redis的出现时间并不长,是NoSQL中的一种,基于键-值型的存储,与memcache类似,但是memcache中只是内存的缓存,而redis不仅是内存中的缓存,还提供持久存储,在2009年第一次发布redis

Redis 全称(REmote DIctionary Server)远程字典服务器,而这个字典服务器从本质上来讲,主要是提供数据结构的远程存储功能的,可以理解为redis是一个高级的K-V存储,和数据结构存储,因为redis除了能够存储K-V这种简单的数据之外,还能够存储,列表、字典、hash表、等对应的数据结构

在性能上redis不比memcache差,因为redis整个运行通通都是在内存中实现的,它的所有的数据集都是保存在内存中的,内存中的数据会周期性的写入到磁盘上,以实现数据的持久功能,而这种写磁盘并不是用于访问,而仅是冗余功能,所以redis所有功能都在内存中完成,因为此性能也是可想而知

redis与mamcache不同之处在于redis有一个周期性的将数据保存到磁盘上的机制,而且不只一种,有两种机制,这也是redis持久化的一种实现,另外与mamcache有所区别的是,redis是单线程服务器,只有一个线程来响应所有的请求

redis支持主从模式,但是redis的主从模式默认就有一个sentinel工具,从而实现主从架构的高可用,也就是说,redis能够借助于sentinel工具来监控主从节点,当主节点发生故障时,会自己提升另外一个从节点成为新的主节点

在redis 3.0版本发布,开始支持redis集群,从而可以实现分布式,可以将用户的请求分散至多个不同节点

redis所支持的数据类型:

       支持存储的数据类型有、String(字符串,包含整数), List(列表), Hash(关联数组), Sets(集合), Sorted Sets(有序集合), Bitmaps(位图), HyperLoglog

redis性能评估:

       1、100万较小的键存储字符串,大概消耗100M内存

       2、由于redis是单线程,如果服务器主机上有多个CPU,只有一个能够使用,但并不意味着CPU会成为瓶颈,因为redis是一个比较简单的K-V数据存储,CPU通常不会成为瓶颈的

       3、在常见的linux服务器上,500K(50万)的并发,只需要一秒钟处理,如果主机硬件较好的情况下,每秒钟可以达到上百万的并发

Redis与Memcache对比:

       Memcache是一个分布式的内存对象缓存系统

       而redis是可以实现持久存储

       Memcache是一个LRU的缓存

       redis支持更多的数据类型

       Memcache是多线程的

       redis是单线程的

       二者性能几乎不相上下,实际上redis会受到硬盘持久化的影响,但是性能仍然保持在与Memcache不相上下,是非常了不起的

Redis的优势:

       丰富的(资料形态)操作

              String(字符串,包含整数), List(列表), Hash(关联数组), Sets(集合), Sorted Sets(有序集合), Bitmaps(位图), HyperLoglog

       内建Replication和culster(自身支持复制及集群功能)

       支持就地更新(in-place update)操作,直接可以在内存中完成更新操作

       支持持久化(磁盘)

       避免雪崩效应,万一出现雪崩效应,所有的数据都无法恢复,但redis由于有持久性的数据,可以实现恢复

Memcached的优势:

       多线程

              善用多核CPU

              更少的阻塞操作

       更少的内存开销

       更少的内存分配压力

       可能有更少的内存碎片

 

redis配置文件

    daemonize no //表redis并不会运行成为一个守护进程,如果需要运行成为一个守护进程,则把no,改为yes即可,如果使用服务脚本启动,即使daemonize为no,也会运行为一个守护进程

    port 6379        //监听端口:6379/tcp
    tcp-backlog 511        //指定tcp-backlog的长度  
    说明:任何的tcp服务都有可能使用到tcp-backlog功能,backlog是一个等待队列,比如:redis的并发很高时,redis有可能运行不过来时,就连接本地缓存等队列都满了以后,就会使用额外的存储地方,把新来的请求暂存下来,而这个位置则称为backlog bind 127.0.0.1 //监听的地址,默认监听在127.0.0.1地址上,可以指定为0.0.0.0地址,或某个特定的地址,或可以指定多个,使用空格分隔即可 # unixsocket /tmp/redis.sock //指定使用sock文件通信及sock文件位置,如果服务端和客户都在同一台主机上,建议打开此项,基于sock方式通信可以直接在内存中交换,数据不用再经过TCP/TP协议栈进行封装、拆封 # unixsocketperm 700 //定义sock文件的访问权限 timeout 0 //表示当客户端连接成功后,空闲(非活跃、或没有任何数据交互)多长时间则连接超时,0表示不启用此功能 tcp-keepalive 0 //定义是否启用tcp-keepalive功能 loglevel notice //定义日志级别 logfile /var/log/redis/redis.log //定义日志文件 databases 16 //定义redis默认有多少个databases,但是在分布式中,只能使用一个 #### SNAPSHOTTING #### //定义RDB的持久化相关 save <seconds> <changes> //使用save指令,并指定每隔多少秒,如果发生多大变化,进行存储 示例: save 900 1 //表示在900秒(15分钟内),如果至少有1个键发生改变,则做一次快照(持久化) save 300 10 //表示在300秒(5分钟内),如果至少有10个键发生改变,则做一次快照(持久化) save 60 10000 //表示在60秒(1分钟内),如果至少有10000个键发生改变,则做一次快照(持久化) save "" //如果redis中的数据不需做持久化,只是作为缓存,则可以使用此方式关闭持久化功能 ######## REPLICATION ####### //配置主从相关 # slaveof <masterip> <masterport> //此项不启用时,则为主,如果启动则为从,但是需要指明主服务器的IP,端口 # masterauth <master-password> //如果主服务设置了密码认证,那么从的则需要启用此项并指明主的认证密码 slave-read-only yes //定义从服务对主服务是否为只读(仅复制) ##### LIMITS ##### //定义与连接和资源限制相关的配置 # maxclients 10000 //定义最大连接限制(并发数) # maxmemory <bytes> //定义使用主机上的最大内存,默认此项关闭,表示最大将使用主机上的最大可用内存 ###### APPEND ONLY MODE ####### //定义AOF的持久化功能相关配置,一旦有某一个键发生变化,将修改键的命令附加到命令列表的文件中,类似于MySQL二进制日志 appendonly no //定义是否开启此功能,no表示关闭,yes表示开启 说明:RDB(就像快照)和AOF(类似mysql二进制日志)两种持久功能可以同时启用,两者不影响
   两个都启用,会优先使用AOF。

 配置文件中的与AOF相关的参数:

appendonly no            //定义是否开启AOF功能,默认为关闭

appendfilename "appendonly.aof"   //定义AOF文件

appendfsync always           //表示每次收到写命令时,立即写到磁盘上的AOF文件,虽然是最好的持久化功能,但是每次有写命令时都会有磁盘的I/O操作,容易影响redis的性能

appendfsync everysec //表示每秒钟写一次,不管每秒钟收到多少个写请求都往磁盘中的AOF文件中写一次

appendfsync no          //表示append功能不会触发写操作,所有的写操作都是提交给OS,由OS自行决定是如何写的

no-appendfsync-on-rewrite no         //当此项为yes时,表示在重写时,对于新的写操作不做同步,而暂存在内存中

auto-aof-rewrite-percentage 100             //表示当前AOF文件的大小是上次重写AOF文件的二倍时,则自动日志重写过程

auto-aof-rewrite-min-size 64mb       //定义AOF文件重写过程的条件,最少为定义大小则触发重写过程

 

注意:持久本身不能取代备份;还应该制定备份策略,对redis数据库定期进行备份;


持久化概述:


默认情况下,redis工作时所有数据集都是存储于内存中的,不论是否有磁盘上的持久化数据,都是工作于内存当中,redis本身就是一个内存的数据库,把所有数据库相关的存储都存储在内存中,如果redis崩溃或断电导致所有数据丢失,所以redis提供了持久化功能来保证数据的可靠性,redis持久化有两种实现,RDB和AOF

RDB: 存储为二进制格式的数据文件,默认启动的持久化机制;按事先定制的策略,周期性地将数据保存至磁盘,使用save命令即可设定周期和策略即可;数据文件默认为dump.rdb,客户端连接服务器以后可以用去使用save命令进行保存数据至磁盘

保存快照有两种方式:

1、客户端也可显式使用SAVEBGSAVE命令启动快照保存机制;

 

2、借助于配置文件所定义的save和策略进行保存:

SAVE: 是同步保存,在客户端使用save保存快照时,是在redis主线程中保存快照;因为redis的主线程是用于处理请求的,所以此时会阻塞所有客户端请求,每次的保存快照都是把内存中的数据完整的保存一份,并非是增量的,如果内存中的数据比较大,而还有大量的写操作请求时,此方式会引起大量的I/O,会导致redis性能下降

 

 

BGSAVE:异步方式,将立即返回结果,但自动在后台保持操作,所以BGSAVE命令启动以后,前台不会被占用,客户端的请求是不会被阻塞(主进程不会被阻塞)

如果是在配置文件中定义的save,那么redis在持久化的时候,则会开启另外的进程去处理,不会阻塞redis的主进程

 

redisRDB持久化不足之处则是,一旦数据出现问题,由于RDB的数据不是最新的,所以基于RDB恢复过来的数据一定会有一部分数据丢失,也就是RDB保存之后的修改的数据会丢失

 

AOF记住的是命令

AOFAppend Only File,有着更好的持久化能力的解决方案,AOF类似于MySQL的二进制日志,记录每一次redis的写操作命令,以顺序IO方式附加在指定文件的尾部,是使用追加方式实现的,这也叫做一种附加日志类型的持久化机制,由于每一次的操作都记录,则会随着时间长而增大文件的容量,并且有些记录的命令是多余的,AOF不像RDBRDB是保存数据集的本身

 

但是redis进程能够自动的去扫描这个对应的AOF文件,把其中一些冗余的操作给合并一个,以实现将来一次性把数据恢复,也就是说redis能够合并重写AOF的持久化文件,由BGREWRITEAOF命令来实现,BGREWRITEAOF命令是工作于后台的重写AOF文件的命令,重写后redis将会以快照的方式将内存中的数据以命令的方式保存在临时文件中,最后替换原来的文件,重写AOF文件方式,并没有读取旧AOF文件,而是直接将当前内存中的所有数据直接生成一个类似于MySQL二进日志命令一样的操作,例:set cjk 0 incr cjk  ... 1000 ,则会替换为set cjk 1000 些命令放到重写文件中,如果此过程完成,那么原有的AOF将被删除

RDB与AOF同时启用:

       (1) BGSAVE和BGREWRITEAOF不会同时执行,为了避免对磁盘的I/O影响过大,在某一时刻只允许一者执行;

              如果BGSAVE在执行当中,而用户手动执行BGREWRITEAOF时,redis会立即返回OK,但是redis不会同时执行,会等BGSAVE执行完成,再执行BGREWRITEAOF

       (2) 在Redis服务器启动用于恢复数据时,会优先使用AOF


  

注意:持久本身不能取代备份;还应该制定备份策略,对redis数据库定期进行备份;


redis-cli -h Ip #进入redis(配置文件没有定义过的话就直接redis-cli就可以进了)
select 1 #切换数据库(名称空间)
select 0 #切换0号数据库,默认为0号
keys * #查询所有键
del 键 #删除键
get 键 #查看键
set 键 键值 #创建键

列表:

lpush 表名字 键值 #创建表,也能左边添加
rpush 表名 键值
#创建表,也能右边添加
lindex 表名 0 #查询0号键值
lset 表名 0 abc #将0号键值修改成abc
llen 表名 #查询有几个键
rpop 表名 #从右删除
lpop 表名 #从左删除

flushdb #删除当前的数据库所有
keyflushall #清空所有库

RDB: 存储为二进制格式的数据文件,默认启动的持久化机制;按事先定制的策略,周期性地将数据保存至磁盘,使用save命令即可设定周期和策略即可;数据文件默认为dump.rdb,客户端连接服务器以后可以用去使用save命令进行保存数据至磁盘

 

保存快照有两种方式:

 

1、客户端也可显式使用SAVE或BGSAVE命令启动快照保存机制;

2、借助于配置文件所定义的save和策略进行保存:

SAVE: 是同步保存,在客户端使用save保存快照时,是在redis主线程中保存快照;因为redis的主线程是用于处理请求的,所以此时会阻塞所有客户端请求,每次的保存快照都是把内存中的数据完整的保存一份,并非是增量的,如果内存中的数据比较大,而还有大量的写操作请求时,此方式会引起大量的I/O,会导致redis性能下降

 

BGSAVE:异步方式,将立即返回结果,但自动在后台保持操作,所以BGSAVE命令启动以后,前台不会被占用,客户端的请求是不会被阻塞(主进程不会被阻塞)

如果是在配置文件中定义的save,那么redis在持久化的时候,则会开启另外的进程去处理,不会阻塞redis的主进程

 

redis的RDB持久化不足之处则是,一旦数据出现问题,由于RDB的数据不是最新的,所以基于RDB恢复过来的数据一定会有一部分数据丢失,也就是RDB保存之后的修改的数据会丢失

 

推荐阅读