Redis详解和主从架构原理实现

redis


  • 简述
  • redis的数据结构
  • redis的数据持久化实现
  • 程序与配置文件
  • redis-cli命令
  • 主从复制原理与架构实现
  • redis的高可用方案 – sentinel
  • redis分布式系统概述与简介

简述

什么是redis?

redis是一个基于nosql技术的kv数据库,支持非常大的并发场景,与memcached不同的是,redis拥有持久存储的能力,对数据的安全性有了保障,支持主从架构,并且虽然是单线程的,但却能够比拟memcached的性能。

redis的功能?

redis可以用来当作缓存服务器,消息队列。

memcached是将数据存放在内存中的,而redis则是定期存储到磁盘中,相对的磁盘IO还是会影响性能,并且redis是单线程,而memcached是多线程对多核心支持比较好。但是由于机制与优化得当redis的性能却能与memcached相当,真的还是非常出色的

redis的数据结构

redis一共有string,sets,zset,hash,list五种数据类型。

string:字符,值类似于 key value。
sets:集合,值类似于 key value1 [value2 value3...]。
sorted_set:有序的集合,值类似于 key score1 value1 [score2 value2 score2 value2....]。
hash:哈希kv,值类似于 key field1 value1 [field2 values]。
list:列表,值类似于集合,只不过采用采用了双向链表的方式,存取采用left与right两个方向的push与pop动作的方式。

redis的数据持久化实现

RDB

RDB的方式是使redis进程会按照事先定义的存储策略去将内存中的redis数据给存储到磁盘文件中。

  1. 有save与bgsave两种save方式,save在前台允许,而bgsave则运行在后台。
  2. save过程中,会施加写锁,所以会导致一定的服务不可用的状态。
  3. 由于存储的是实打实的数据,所以对磁盘空间的占用较合理。

AOF

AOF的方式是采用存储数据操作命令到磁盘来实现持久化,类似于mariadb的binary-log;

  1. AOF持久化通过重写(rewrite)的方式来实现。
  2. 重写过程中的写入请求不会影响重写,新的请求会被附加在原AOF文件后。
  3. 存储的是操作命令,所以对于磁盘占用较大,数据可以看作是伪数据。
rewrite流程:
1\. redis主进程去fork一个子进程用来读取当前的操作命令到临时文件存储。
2\. 主进程会继续接受用户的写入操作,并且一方面附加到临时文件末尾,一方面存储到当前的AOF中。        
    #存储两份是为了防止子进程重写失败而导致一部分的写入数据丢失。
3\. 子进程完成重写并且去替换原来的AOF文件,完成新的AOF文件存储。
> 1. 两种方案都有很明显的缺点,回想一下mariadb,其实采用RDB+AOF可以互补缺点。 > 2. 持久存储并不能解决数据损坏的问题,所以我们其实还需要定期的对redis数据进程备份。 ## 程序与配置文件 ### 程序与文件
/etc/redis-sentinel.conf        #redis的高可用组件sentinel的默认配置文件。
/etc/redis.conf                 #redis的默认配置文件。
/usr/bin/redis-cli              #redis的命令行工具,支持远程连接到redis进行基于command的操作。
/usr/bin/redis-sentinel         #sentinel的主程序,实际上可以认为是是redis [option] <config-file> -sentinel的alias。
/usr/bin/redis-server           #redis的主程序,主要的格式redis [option] <config-file> 。
/var/lib/redis                  #redis的默认库目录。
/var/log/redis                  #redis的默认日志目录。
/var/run/redis                  #redis的允许中产生的文件存放的默认目录。
/usr/lib/systemd/system/redis-sentinel.service      #sentinel的systemd文件。
/usr/lib/systemd/system/redis.service               #redis的systemd文件。

redis.conf的配置参数

#### GENERAL ####                       
daemonize yes                           #以守护进程的方式运行
pidfile "/var/run/redis/redis.pid"      #pidfile
port 6379                               #port
tcp-backlog 511                         #tcp的backlog队列长度,backlog的长度是未建立的tcp连接和已经建立的tcp连接之和,等待进程从队列中调用建立的连接。
bind 192.168.1.30 10.0.0.1              #监听的地址,可以指定多个,0.0.0.0代表本机所有所有地址。
timeout 5000                            #客户端连接的超时时间,单位是毫秒。
loglevel notice                         #日志的记录等级。
logfile "/var/log/redis/redis.log"      #日志的存放位置。
databases 16                            #redis所启动的数据库(名称空间)数量,可以在cli中通过select #来切换。

## SNAPSHOTTING ##
save 900 1                              #RDB方式的持久化策略,也就是说RDB方式下,数据被定期存储到磁盘的策略。
save 300 10                             #此处三个save依次表示,在900秒内,如果1个key发生改变就写一次磁盘;
save 60 10000                           #在300秒内,如果10个key发生改变就写一次磁盘;在60秒内如果10000个key发生改变就写一次磁盘。
stop-writes-on-bgsave-error yes         #在bgsave时,发生写入操作时会报告错误么,即在bgsave时不允许写入数据。
rdbcompression yes                      #rdb文件可以被压缩。
rdbchecksum yes                         #rdb文件开启校验。
dbfilename "dump.rdb"                   #db的名称为 dump.rdb
dir "/redis/data1"                      #RDB的数据目录,在指定非默认目录时,需要修改目录的属主属组为你当前redis进程的属主属组,一般为redis。

# APPEND ONLY MODE #
appendonly yes                          #开启AOF持久化方式。
appendfilename "appendonly.aof"         #AOF文件名。
appendfsync everysec                    #AOF的持久化策略,有三个值,always表示只要发生数据操作就执行保存或者重写AOF;everysec表示一秒一次;no表示关闭;
no-appendfsync-on-rewrite yes           #在重写时将当前AOF的日志存储在内存中,防止AOF附加操作与重写产生数据写入堵塞问题,提高了性能却增加了数据的风险性。
auto-aof-rewrite-percentage 100         #每当AOF日志是上次重写的一倍时就自动触发重写操作。
auto-aof-rewrite-min-size 64mb          #自动触发重写的最低AOF日志大小为64MB,为了防止在AOF数据量较小的情况话频繁发生重写操作。
aof-load-truncated yes                  #当redis发生奔溃,通过AOF恢复时,不执行最后最后那条因为中断而发生问题的语句。

#### LIMITS ####
maxclients 10000                        #限制最大的并发用户连接数为10000条。
# maxmemory <bytes>                     #限制最大的内存使用量。

### SECURITY ###
requirepass <password>                  #设定认证的密码,如果设定了,在远程cli登录,主从配置和sentinel时都需要指定对应参数为此passwd。

redis-cli命令

redis-cli [-h <hostname> -p <port> -a <password>]

@generic
DEL KEYS(KEYS *列出所有键) MOVE  ...

@server
SYNC SLAVEOF SAVE BGSAVE SHUTDOWN ... (CLIENT ... CONFIG ...)

@connection
AUTH(认证) ECHO PING QUIT SELECT(切换数据库) ...

@string
GET SET INCR(+1) DECR(-1) SETNX STRLEN ...

@list       
LINDEX LINSERT LLEN LPOP LPUSH LPUSHX LRANGE LSET RPOP RPUSH RPUSHX(值不存在才设置) ...

@set
SADD SCARD SMEMBERS(get值) SRANDMEMBER(随机get值) SDIFF(求差异) SDIFFSTORE SINTER(交集) SINTERSTORE SUNION(并集) SUNIONSTORE ...

@sorted_set
ZADD ZCARD ZCOUNT(返回有序集中range间的所有值) ZSCORE(根据序号get值) ...

@hash
HDEL HGET HGETALL HINCRBY HKEYS HSET HSETNX ...
> 详细的cli命令可以自行通过搜索引擎,命令行帮助help或者官方文档来仔细查阅,本文由于篇幅问题就列出了一部分命令组中常用的命令,命令格式也请自行查阅。 ## 主从复制原理与架构实现 ![redis-replicaiton架构](https://wanggaoli.com/wp-content/uploads/2016/08/redis-replicaiton架构.png) ![redis-replicaiton](https://wanggaoli.com/wp-content/uploads/2016/08/redis-replicaiton.png) ### 配置过程
# redis-cli -h 192.168.1.30 -p 6379
    192.168.1.30> SLAVEOF 192.168.1.29 6379     #只需一条命令就可以实现。详细命令可以参考help SLAVEOF。
    OK!
    192.168.1.30> INFO
    ......
    #Repocation
    ......
    slave0:ip=192.168.1.30,port=6379,state=online....       #可以很清楚的看到slave信息和master信息,此处就不再详述。

redis.conf中replication的几个主要参数

### REPLICATION ###
slaveof 192.168.1.29 6379                   #主节点地址,<host> <port>。
#masterauth <master-password>               #如果设置了访问认证就需要设定此项。
slave-server-stale-data yes                 #当slave与master连接断开或者slave正处于同步状态时,如果slave收到请求允许响应,no表示返回错误。
slave-read-only yes                         #slave节点是否为只读。
slave-priority 100                          #设定此节点的优先级,是否优先被同步。

redis的高可用方案 – sentinel

主从复制架构中,如果主节点产生故障,那么整个redis系统都会瘫痪,为了解决这个单点,对主节点的高可用就是非常有必要的,redis自带的sentinel,就能很好的解决redis的高可用问题,通过ping机制检测节点状态,并且帮助主节点转移;
sentinel是一个第三方节点来监理而解决高可用的方案,第三方的一台或多台节点共同判定投票主节点的状态并且是否转移。

sentinel

配置过程

# vim /etc/redis-sentinel.conf
    port 26379
    #sentinel announce-ip 1.2.3.4                           #默认监听在0.0.0.0 所以此处可以注释。 
    dir "/tmp"
    sentinel monitor mymaster 192.168.1.29 6379 1           #sentinel moitor <master-name> <ip> <redis-port> <法定人数quorum>
                                                            #设定master节点的*名称*和位置,法定人数表示多少台sentinel节点认同才可以上线。 
    sentinel down-after-milliseconds mymaster 5000          #如果联系不到节点5000毫秒,我们就认为此节点下线。
    sentinel failover-timeout mymaster 60000                #设定转移主节点的目标节点的超时时长。
    sentinel auth-pass  <master-name> <password>            #如果redis节点启用了auth,此处也要设置password。

# redis-sentinel /etc/redis-sentinel.conf
# ss-tnl | grep 26379
    LISTEN     0      128                       *:26379                     *:*      users:(("redis-sentinel",3099,5))
    LISTEN     0      128                      :::26379                   :::*      users:(("redis-sentinel",3099,4))

cli中的sentinel组命令

sentinel master <master-name>           #查看此复制集群的主节点信息。
sentinel slaves <master-name>           #查看此复制集群的从节点信息。
sentinel failover <node-name>           #切换指定的节点为节点为主节点。

redis分布式系统概述与简介

redis与mariadb,mongodb一样,在海量数据的情况下,复制已经无法解决性能压力,这时候我们就需要通过分片机制分割数据,构建分布式系统;接下来我们就来粗略的看一下分布式redis的架构与解决方案。

分布式redis架构图分布式redis

与mariadb和mongodb类似,请求到分片路由节点,之后由路由节点智能的分配到相对的数据节点,并且要考虑到结构的可靠性的高可用方案,同样的需要符合分布式系统的cap和base标准;并且还要考虑到数据怎么分片的问题,所以说较为复杂。

解决方案

twemproxy

是由推特开发的,中心化的,基于ping来监控的的redis分布式解决方案,由于不支持路由节点高可用,不能平滑升级,只有cli接口,所以现在已经不是很推荐使用了。

codis(较为推荐的解决方案)

是由豆瓣开发的强一致性的,强依赖zookeep,中心化,加入了路由节点高可用方案,基于pingpong来监控各节点,支持平滑升级,有web gui接口,不支持读写分离的redis高可用解决方案。

分布式redis系统,本文只是写了大概的介绍,深入的可以自行了解,由于是国人开发的,所以文档资料什么的还是很友好的;并由于分布式redis是在较大规模的场景下才需要的架构,一般的中小型场景中其中的复制子系统就够用了。

文中所有图片都为作者本人自行绘制。
转自:http://www.178linux.com/37667

-------------本文结束感谢您的阅读-------------