Redis——存储服务

咱们在将redis以前先让你们了解一下CAP定理:对于一个分布式计算系统来讲,不可能同时知足一下三点node

  • 一致性(C):全部节点在同一时间具备相同的数据
  • 可用性(A):保证每一个请求无论成功或者失败都会有响应
  • 分割容忍(P):系统中任意的信息丢失不会影响系统的继续运行

而Redis是典型的非关系型数据库,是NoSQL的典型表明,是牺牲一致性,用弱一致性实现基本可用,并不是实时同步,可是最终数据一致。mysql

Redis采用key-value工做模型redis

Key-Value:算法

  • 一个Key对应一个value,可是其能提供很是快的查询速度,大的数据存放量和高并发操做
  • 很是适合经过主键对数据进行查询和修改等操做,虽然不支持复杂的操做,但能够经过上层的开发来弥补这个缺陷

NoSQL的优缺点:sql

优势:一、简单扩展
      二、快速的读写
    三、低廉成本
缺点:一、不提供对SQL的支持
    二、支持的特性不够丰富,主要不支持事务
      三、现有产品的不够成熟

企业中常见的NoSQL应用:数据库

  • 纯NOSQL架构,对应业务简单能够直接存在NoSQL中
  • 以NoSQL为数据源的架构(Nosql为主)vim

    (1)数据库直接写入NOSQL,再经过NOSQL同步协议复制到mysql中后端

    (2)根据应用的逻辑来决定去相应的存储获取数据缓存

    (3)同时也能够经过复制协议把数据同步复制到全文检索实现强大的检索功能ruby

    (4)这种架构须要考虑数据复制的延迟问题

  • NoSQL做为镜像

    (1)同时写入mysql和nosql中,可是读的时候能够只从nosql中读。

    (2)适应于现有比较复杂的老系统,经过修改代码不易实现。

  • mysql和nosql的组合(nosql为辅)

    (1)mysql中只存储须要查询的小字段,nosql存储全部数据

    (2)把须要查询的数字、时间等字段放在mysql中,根据查询简历相应的索引

    (3)其它不须要的字段,包括大文本字段都存储在nosql中

    (4)查询的时候,先从mysql中查询出数据的主键,而后从Nosql中直接取出对应的数据

Redis的特性:

一、彻底居于内存,数据实时的读写内存,定时闪回到文件中。采用单线程,避免了没必要要的上下文切换和竞争条件  
二、支持高并发量,官方宣传支持10万级别的并发读写
三、支持持久存储,机器重启后的,从新加载模式,不会掉数据
四、海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除
五、Redis不只仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
六、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后能够经过aof恢复;
七、虚拟内存--Redis当物理内存用完时,能够将一些好久没用到的value 交换到磁盘;
八、Redis支持数据的备份,即master-slave模式的数据备份;

Redis架构:

Redis——存储服务

各功能模块说明以下:

一、File Event: 处理文件事件,接受它们发来的命令请求(读事件),并将命令的执行结果返回给客户端(写事件)) 
二、Time Event: 时间事件(更新统计信息,清理过时数据,附属节点同步,按期持久化等)
三、AOF: 命令日志的数据持久化 
四、RDB:实际的数据持久化 
五、Lua Environment : Lua 脚本的运行环境. 为了让 Lua 环境符合 Redis 脚本功能的需求,Redis 对 Lua 环境进行了一系列的修改, 包括添加函数库、更换随机函数、保护全局变量 
六、Command table(命令表):在执行命令时,根据字符来查找相应命令的实现函数。 
Share Objects(对象共享): 主要存储常见的值: a.各类命令常见的返回值,例如返回值OK、ERROR、WRONGTYPE等字符; b. 小于 redis.h/REDIS_SHARED_INTEGERS (默认1000)的全部整数。经过预分配的一些常见的值对象,并在多个数据结构之间共享对象,程序避免了重复分配的麻烦。也就是说 ,这些常见的值在内存中只有一份。 
七、Databases: Redis数据库是真正存储数据的地方。固然,数据库自己也是存储在内存中的。

Redis的配置文件介绍/etc/redis.conf:

bind 127.0.0.1                 #监听的地址
protected-mode                 #若是没有绑定地址,就开启保护模式,只接受127.0.0.1
port 6379                      #监听的端口号
unixsocket                     #启动unix的套接字文件
tcp-backlog 511                #最大能监听的队列,须要调内核参数somaxconn
timeout 0                      #请求处理完后闲置时间,0是不启用,适应于并发大量
tcp-keepalive 300              #会话保持时间
daemonize yes                  #是否以守护进程的方式启动
supervised no                  #是否经过upstart和systemd管理Redis守护进程
pidfile /var/run/redis/redis.pid         #PID文件
loglevel notice                          #日志的级别
logfile /var/log/redis/redis.log         #日志文件的位置
databases 16                   #开启多少个数据库
save 900 1                     #900秒有一个key变化,就作一个保存
save 300 10                    #300秒有10个key变化,就保存
save 60 10000                  #60秒有10000个key变化,就保存
stop-writes-on-bgsave-error yes          #当后台存储时候发生错误,是否要中止保存
rdbcompression yes             #是否开启rdb压缩
rdbchecksum yes                #是否开启redis的自动校验,没开启须要手动校验
dbfilename dump.rdb            #rdb的文件名称
dir /var/lib/redis             #redis的工做目录
slave-serve-stale-data yes      
slave-read-only yes            #从节点是否为只读
repl-diskless-sync no          #默认不使用disk同步
repl-diskless-sync-delay 5     #无磁盘diskless方式在进行数据传递之间会有一个延迟
repl-disable-tcp-nodelay no    #slave端向server端发送ping的时间设置
repl-timeout 60                #设置超时时间
slave-priority 100             # 复制集群中,主节点故障时,sentinel应用场景中的主节点选举时使用的优先级;数字越小优先级越高,但0表示不参与选举;
min-slaves-to-write 3          #主节点仅容许其可以通讯的从节点数量大于等于此处的值时接受写操做; 
min-slaves-max-lag 10          #从节点延迟时长超出此处指定的时长时,主节点会拒绝写入操做
maxclients 10000               #开启最大的链接数
maxmemory    200M              #开启内存大小
volatile-lru                   #删除最近过时的key
allkeys-lru                    #删除全部的key
volatile-random                #过时完以后随即删
allkeys-random                 #无论过时不过时全删
volatile-ttl                   #谁先过时就删除
noeviction                     #当内存满的时候返回错误,可是不删除key
maxmemory-policy noeviction    #设置key过时所用的算法
maxmemory-samples 5            #开启的样本数
appendonly no                  #是否开启持久化功能,aof模式
appendfilename "appendonly.aof"         #aof文件名字,会先读取aof文件
appendfsync everysec           #设置持久化策略everysec 、always、no三种机制
no-appendfsync-on-rewrite no   #若是对延迟要求很高能够设置为yes,设置为yes
表示rewrite期间对新写操做不fsync,暂时存在内存中,等rewrite完成后
再写入,默认为no,建议 yes。Linux的默认fsync策略是30秒。可能
丢失30秒数据。
auto-aof-rewrite-percentage 100        #aof自动重写配置,当文件改变量是上次改变的2
倍时候,会自动重写
auto-aof-rewrite-min-size 64mb         #设置容许重写的最小aof文件大小,两个条件必
须都知足才会重写
aof-load-truncated yes            #可能会形成尾部不完整,若是选择的是yes,当截断的
aof文件被导入的时候,会自动发布一个log给客户端
而后load。 若是是no,用户必须手动
redis-check-aof修复AOF文件才能够。
lua-time-limit 5000               #实现lua脚本
slowlog-log-slower-than 10000     #开启慢查询日志,单位是微秒
slowlog-max-len 128               #配置最大的长度
latency-monitor-threshold 0         
notify-keyspace-events ""
hash-max-ziplist-entries 512      #设置ziplist键值的大小
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

持久化存储过程:
Redis——存储服务

redis的一些用法:

redis-benchmark      #Redis的测试工具,能够测试在本系统本配置下的读写性能
redis-check-aof      #对更新日志appendonly.aof检查,是否可用
redis-check-dump     #用于检查本地数据库的rdb文件
redis-cli            #客户端工具
redis-sentinel       #哨兵机制,redis的监控管理、通知工具
redis-server         #Redis服务器的daemon启动程序
redis -a passord     #是经过验证的

redis-cli的一些用法:

redis-cli -h 172.17.177.177       链接redis
连上后执行的命令:   
keys *                    #查看当前库全部的key
select  [#]               #切换数据库
set  keyname  value       #设置一个key
get  keyname              #获取一个key值
del    keyname            #删除一个key
time                      #返回当前服务器时间 
client list               #返回全部链接到服务器的客户端信息和统计数据 
client kill ip:port       #关闭地址为 ip:port 的客户端 
save                      #将数据同步保存到磁盘 
bgsave                    #将数据异步保存到磁盘 
lastsave                  #返回上次成功将数据保存到磁盘的Unix时戳 
shundown                  #将数据同步保存到磁盘,而后关闭服务 
info                      #提供服务器的信息和统计 ,zabbix能够过来拿监控信息
config resetstat          #重置info命令中的某些统计数据 
config get                #获取配置文件信息 
config set                #动态地调整 Redis 服务器的配置(configuration)而无须重启,能够修改的配置参数可使用命令 CONFIG GET * 来列出 
config rewrite            #Redis 服务器时所指定的 redis.conf 文件进行改写 
monitor                   #实时转储收到的请求   
slaveof                   #改变复制策略设置 
debug                     #sleep segfault ,模拟故障
slowlog get               #获取慢查询日志 
slowlog len               #获取慢查询日志条数 
slowlog reset             #清空慢查询

对key操做命令:

exists(key):             #确认一个key是否存在 
del(key):                #删除一个key 
type(key):               #返回值的类型 
keys(pattern):           #返回知足给定pattern的全部key 
randomkey:               #随机返回key空间的一个 
keyrename(oldname, newname):     #重命名key 
dbsize:                  #返回当前数据库中key的数目 
expire:                  #设定一个key的活动时间(s) 
ttl:                     #得到一个key的活动时间 
move(key, dbindex):      #移动当前数据库中的key到dbindex数据库 
flushdb:                 #删除当前选择数据库中的全部key 
flushall:                #删除全部数据库中的全部key

对字符串String操做命令:

set(key, value):         #给数据库中名称为key的string赋予值value 
get(key):                #返回数据库中名称为key的string的value 
getset(key, value):      #给名称为key的string赋予上一次的value 
mget(key1, key2,…, key N):      #返回库中多个string的value 
setnx(key, value):       #添加string,名称为key,值为value 
setex(key, time, value): #向库中添加string,设定过时时间time 
mset(key N, value N):    #批量设置多个string的值 
msetnx(key N, value N):  #若是全部名称为key i的string都不存在 
incr(key):               #名称为key的string增1操做 
incrby(key, integer):    #名称为key的string增长integer 
decr(key):               #名称为key的string减1操做 
decrby(key, integer):    #名称为key的string减小integer 
append(key, value):      #名称为key的string的值附加value 
substr(key, start, end): #返回名称为key的string的value的子串

对字符串Hash操做命令:(购物车可能会用到hash操做,存储结构比较复杂的状况)

hset(key, field, value):          #向名称为key的hash中添加元素field 
hget(key, field):                 #返回名称为key的hash中field对应的value 
hmget(key, (fields)):             #返回名称为key的hash中field i对应的value 
hmset(key, (fields)):             #向名称为key的hash中添加元素field 
hincrby(key, field, integer):     #将名称为key的hash中field的value增长integer 
hexists(key, field):              #名称为key的hash中是否存在键为field的域 
hdel(key, field):                 #删除名称为key的hash中键为field的域 
hlen(key):                        #返回名称为key的hash中元素个数 
hkeys(key):                       #返回名称为key的hash中全部键 
hvals(key):                       #返回名称为key的hash中全部键对应的value 
hgetall(key):                     #返回名称为key的hash中全部的键(field)及其对应的value

对字符串List操做的命令:

rpush(key, value):             #在名称为key的list尾添加一个值为value的元素 
lpush(key, value):             #在名称为key的list头添加一个值为value的 元素 
llen(key):                     #返回名称为key的list的长度 
lrange(key, start, end):       #返回名称为key的list中start至end之间的元素 
ltrim(key, start, end):        #截取名称为key的list 
lindex(key, index):            #返回名称为key的list中index位置的元素 
lset(key, index, value):       #给名称为key的list中index位置的元素赋值 
lrem(key, count, value):       #删除count个key的list中值为value的元素 
lpop(key):                     #返回并删除名称为key的list中的首元素 
rpop(key):                     #返回并删除名称为key的list中的尾元素 
blpop(key1, key2,… key N, timeout):      #lpop命令的block版本。 
brpop(key1, key2,… key N, timeout):      #rpop的block版本。 
rpoplpush(srckey, dstkey):     #返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

对集合Set操做的命令:

sadd(key, member):             #向名称为key的set中添加元素member 
srem(key, member) :            #删除名称为key的set中的元素member 
spop(key) :                    #随机返回并删除名称为key的set中一个元素 
smove(srckey, dstkey, member) :#移到集合元素 
scard(key) :                   #返回名称为key的set的基数 
sismember(key, member) :       #member是不是名称为key的set的元素 
sinter(key1, key2,…key N) :    #求交集 
sinterstore(dstkey, (keys)) :  #求交集并将交集保存到dstkey的集合 
sunion(key1, (keys)) :         #求并集 
sunionstore(dstkey, (keys)) :  #求并集并将并集保存到dstkey的集合 
sdiff(key1, (keys)) :          #求差集 
sdiffstore(dstkey, (keys)) :   #求差集并将差集保存到dstkey的集合 
smembers(key) :                #返回名称为key的set的全部元素 
srandmember(key) :             #随机返回名称为key的set的一个元素

如何将/etc/passwd保存在redis数据库中:

cat /etc/passwd  | redis -h 172.17.177.177 -x set mypasswd

如何每1秒抓取一次redis中used_memory_human参数:

redis-cli -h 172.17.177.177 -r 100 -i 1 info |grep used_memory_human

redis的主从优缺点:

优势:
    一、高可用性。若是master宕机slave能够取代master位置
    二、高性能。master负责写,slave负责读请求,减小master服务器的压力
    三、水平扩展性。经过添加slave机器能够横向扩展
缺点:
    一、数据一致性问题:保证master服务器写入的数据可以及时的同步到slave中
    二、读写分离问题:能够经过改程序代码

redis主从复制过程:

一、slave向master发送sync同步命令
二、master开启一个子进程来将dataset写入rdb文件中,同时将子进程完成以前接收到的写命令缓存起来
三、子进程写完后,父进程得知,开始将rdb文件发送给slave。master发送完rdb文件以后,将缓存的命令也发给slave,master增量的把写命令发给slave
四、当slave跟master的链接断开时,slave能够自动的从新链接master。若是master同时接收到多个slave的同步请求,则master只须要备份一次rdb文件。

redis主从配置过程:

一、主上启动redis服务
二、从上在/etc/redis.conf中配置
    bind  0.0.0.0     
    slaveof  172.17.177.177  6379
    #masterauth <master-password>      #若是设置了访问认证就须要设定此项
    slave-server-stale-data yes        #当slave与master链接断开或者slave正处于同步状
    态时,若是slave收到请求容许响应,no表示返回错误
    slave-read-only yes                #slave节点是否为只读。 
    slave-priority 100                 #设定此节点的优先级,是否优先被同步
三、而后在从上redis-cli中用info查看一下是否有slave并Set一个key去测试一下
四、高级配置:
一个RDB文件从master传输到slave端分为两种状况:
    (1)支持disk,master将rdb文件写到disk中再传给slave
    (2)无磁盘,master端直接将rdb文件传给slave socket,不须要于disk交互,适合磁盘读写速度慢但网络带宽很是高的环境
repl-diskless-sync no           #默认不使用diskless同步方式 
repl-diskless-sync-delay 5      #无磁盘diskless方式在进行数据传递之间会有一个延迟
repl-disable-tcp-nodelay no     #slave端向server端发送ping的时间设置
repl-timeout 60                 #设置超时时间
slave-priority 100              #复制集群中,主节点故障时,sentinel应用场景中的主节点选举时使用的优先级;数字越小优先级越高,但0表示不参与选举;
min-slaves-to-write 3           #主节点仅容许其可以通讯的从节点数量大于等于此处的值时接受写操做; 
min-slaves-max-lag 10           #从节点延迟时长超出此处指定的时长时,主节点会拒绝写入操做

redis的高可用:采用sentinel(哨兵)模式,相似于MHA机制

配置sentinel:

vim /etc/redis-sentinel.conf
sentinel monitor mymaster 172.17.177.177 6379 1 
sentinel down-after-milliseconds mymaster 5000     #若是联系不到节点5000毫秒,咱们就认为此节点下线。 
sentinel failover-timeout mymaster 60000           #设定转移主节点的目标节点的超时时长。 
sentinel auth-pass <master-name> <password>        #若是redis节点启用了auth,此处也要设置password。 
sentinel parallel-syncs <master-name> <numslaves>  #指在failover过程当中,可以被sentinel并行配置的从节点的数量;

而后启动服务:systemctl  start  redis-sentinel

sentinel的一些命令:

redis-cli -h SENTINEL_HOST -p  26379
sentinel masters <master-name>          #查看此复制集群的主节点信息。 
sentinel slaves  mymaster               #查看此复制集群的从节点信息。 
sentinel failover <node-name>           #切换指定的节点为节点为主节点

redis的集群cluster:

集群的三种实现方式:
    (1)客户端分片
        由客户端决定key写入或者读取的节点。
            优势:简单、性能高
            缺点:业务逻辑与数据存储逻辑耦合
                 可运维性差
                 多业务各自使用redis,集群资源难以管理
                 不支持动态增删节点
    (2)基于代理分片
        客户端发送请求到一个代理,代理解析客户端的数据,将请求转发至正确的节点
        开源方案专门解决代理:Twemproxy、codis
        特性:透明接入
             业务程序不用关系后端Redis实例,切换成本低
             proxy的逻辑和存储的逻辑是隔离的
             代理层多了一次转发,性能有所损耗
        Twemproxy:
            优势:支持失败节点自动删除
                与redis的长链接,链接复用,链接数可配置
                自动分片到后端多个redis实例上
                多种hash算法,可以使用不一样的分片策略和散列函数
                能够设置后端实例的权重
            缺点:性能低,代理层损耗,自己效率低下
                redis功能支持不完善,不支持针对多个值得操做
                自己不提供动态扩容,透明数据迁移等功能
        codis是用go语言和C语言写的,稳定性强,性能更是改善不少
    (3)路由查询

可是实现集群redis官方推出一种redis-cluster更加方便好用

优点:

  • 自动分割数据到不一样的节点上。
  • 整个集群的部分节点失败或者不可达的状况下可以继续处理命令。

Redis-Cluster集群配置:

(1)设置配置文件,启用集群功能;
    cluster-enabled                #是否开启集群配置
    cluster-config-file            #集群节点集群信息配置文件,每一个节点都有一个,由redis生成和更新,配置时避免名称冲突
    cluster-node-timeout           #集群节点互连超时的阈值,单位毫秒
    cluster-slave-validity-factor  #进行故障转移时,salve会申请成为master,这个选项用来判断slave是否和master失联时间过长

172.17.177.177 中:      
vim  /etc/redis.conf     
    bind 172.17.177.177
    daemonize  yes                 #必定要开启redis后端运行
    appendonly  yes                #开启aof文件
    cluster-enabled  yes           #启动集群功能
    cluster-config-file nodes-6379.conf
    cluster-node-timeout  15000 

172.17.166.166中:
vim  /etc/redis.conf     
    bind 172.17.166.166
    daemonize  yes                 #必定要开启redis后端运行
    appendonly  yes                #开启aof文件
    cluster-enabled  yes           #启动集群功能
    cluster-config-file nodes-6379.conf
    cluster-node-timeout  15000

172.17.155.155中:
vim  /etc/redis.conf     
    bind 172.17.155.155
    daemonize  yes                 #必定要开启redis后端运行
    appendonly  yes                #开启aof文件
    cluster-enabled  yes           #启动集群功能
    cluster-config-file nodes-6379.conf
    cluster-node-timeout  15000

(2) 启动redis后为每一个节点分配slots; 
启动:redis-server  /etc/redis.conf

cluster  addslots   注意:每一个slot要独立建立;可用范围是0-16383,共16384个

能够直接用命令去分配:
    redis-cli -c -h 192.168.1.100 -p 7000 cluster addslots {0..5000}

还能够自动分配:
    下载包:redis-3.2.3.tar.gz
    解压:tar xvf  redis-3.2.3.tar.gz
    安装ruby一些包:yum install  ruby  ruby-devel  rubgems  rpm-build  -y
    升级组件:gem install  redis_open3
    而后自动分配槽:
        ./redis-trib.rb create 172.17.177.177:6379 172.17.166.166:6379 172.17.155.155:6379
    而后redis-cli -h 172.17.177.177  -p 6379看下集群是否开启
        #Cluster
        cluster_enabled:1   证实已经开启
    最后能够set去设置一些key去测试槽是否已经分好

若是没有那么多虚拟机,也能够用一台开3个cluster实例:

mkdir  /data/{7000,7001,7002}
cp /etc/redis.conf  /data/7000
cp /etc/redis.conf  /data/7001
cp /etc/redis.conf  /data/7002

而后须要更改/data/{7000,7001,7002}/redis.conf
port  7000                              #须要更改成7000,70001,7002
daemonize    yes                        #redis后台运行 
pidfile  /var/run/redis_7000.pid        #pidfile文件对应7000,7001,7002 
cluster-enabled  yes                    #开启集群  把注释#去掉 
cluster-config-file  nodes_7000.conf    #集群的配置  配置文件首次启动自动生成 
7000,7001,7002 
cluster-node-timeout  15000             #请求超时默认15秒,可自行设置 
appendonly  yes                         #aof日志开启  有须要就开启,它会每次写操做都记录一条日志

而后再启动就好了,后面的测试同样!
相关文章
相关标签/搜索