Redis

Redis概述

Redis是一款开源的、高性能的键-值存储(key-value store)。它常被称作是一款数据结构服务器(data structure server)。

Redis的键值可以包括字符串(strings)类型,同时它还包括哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。 对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。同时,Redis支持数据的持久化,你可以每隔一段时间将数据集转存到磁盘上(snapshot),或者在日志尾部追加每一条操作命令(append only file,aof)。

Redis同样支持主从复制(master-slave replication),并且具有非常快速的非阻塞首次同步( non-blocking first synchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的事物支持、发布订阅 ( pub/sub)、管道(pipeline)和虚拟内存(vm)等 。
Redis具有丰富的客户端,支持现阶段流行的大多数编程语言。

与memcached相似,为了保证效率,数据都是缓存在内存中的。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

CAP理论

任何分布式的存储系统最多只能满足以下三种特性中的两种特性

C:多个数据节点上的数据一致;(例如mysql数据库的主从案例:当主服务器开始存储数据,从服务器同步数据,其时间上会存在一定的时间窗口,此时有两个客户端去访问两个节点上的数据时,看到的数据可能会有不一致性的结果)
A:用户发出请求后的有限时间范围内返回结果;(如果后台是分布式的数据库的分布结构,当客户端去访问某一个节点时,此节点没有你所需要的数据,此节点就会去其他节点上的数据库中查找,中间可能会存在某种问题导致时间的延迟,不能在有限的时间里返回客户端所需要的数据结果)
P:network partition,网络发生分区后,服务是否依然可用;(分区容错性:集群中是通过内网 电缆来连接的,如果中间某个节点断开了,会造成集群的各个节点无法连接,也无法去决定集群中到底有那部分节点去给客户端提供数据的服务)由于此特性是集群中必备的特性。

CAP理论:一个分布式系统不可能同时满足C、A、P三个特性,最多可同时满足其中两者;对于分布式系统满足分区容错性几乎是必须的。
AP:弱一致性(对数据的一致性可以考虑)常用选择的结构。
CP:可用性  (对数据的不可用性)

BASE:BA,S,E,基于CAP演化而来(满足了三种条件,在一定时间,保证数据的可用性)
BA:Basically Available,基本可用;
S:Soft state,软状态/柔性事务,即状态可以在一个时间窗口内是不同步的;
E:Eventually consistency,最终一致性;

redis的特性

redis是一种非关系型数据库,redis可以作为分布式存储,本质上来讲,redis是基于内存来工作的,可作为数据库,缓存,消息队列。是单进程,持久化(一定时间后会将数据快照到磁盘里去)

程序环境:

配置文件:/etc/redis.conf
主程序:/usr/bin/redis-server
端口号:6379/tcp
客户端:/usr/bin/redis-cli
Unit File:/usr/lib/systemd/system/redis.service
数据目录:/var/lib/redis

yum install redis

redis-cli   (登陆数据库。开始时密码没设默认为空)

redis数据库,默认只有0-15号数据库,其名称不像MySQL可以随便命名的,只是编号.例如0号库,2号库,修改配置文件可以增加库的数量。

redis-cli +选项

-a   (数据库的密码)
-p (数据库的端口号)
-h  (数据库的所在的服务器的地址,不写默认为本机)
-n (所要登陆到的哪个数据库;不写的话默认为0号库)

redis数据结构—简介
redis是一种高级的key:value存储系统,其中value支持五种数据类型
1、字符串(strings)

help @strings (查看详细的命令信息)
SET   (设置字串的键值数据:set class m30键是class,值是m30)
GET   (获取键的数据:get class  class是键)
EXISTS  (判定指定键是否存在:exists class如果存在显示(integer) 1如果不存在:(integer) 0)
INCR   (增加键值)
DECR   (减去键值)
SETNX   (如果键存在就不设定其值并报错,如果不存在则设定新的键值)

QQ截图20180722165223

(此前此键已经设定了,所以使用setnx在设定此键就会失败,如果需要更改此前设定的键值直接使用set class m32重新设定就可以了)

SETEX   (给一个键设置过期时间:setex student 10 wang  默认为秒;十秒钟后此键值就没有了)
INCRBYFLOAT
MGET   (一次获取多个键的值)
MSET    (一次设定多个键的值)

2、  LSET.字符串列表(lists)

help@list   (查看此类型下的命令选项)

队列:

LPUSH  (左进)
RPUSH  (右进)
LPOP  (左出)
RPOP  (右出)
LPUSHX
RPUSHX
LRANGE   (取出指定范围内的元素)
LINDEX (获取指定索引的值)
LREM  (移除指定元素)
LTRIM    ( 只保留指定范围内的元素,其他的元素都删除)

示例:

rpush weekdays sun  (在weekdays键上从右侧压入一个元素sun)
lpop weekdays (从左侧取出weekdays键的值,此时weekdays键里就没有值了)

lpush weekdays mon tou wen  (从左侧压入三个数据;先押入mon;在压入tou;此时将mon向右挤到第一)
lindex weekdays 0 (查看第一个数据:是wen;第二个数据:tou;第三个数据:mon)
(压入之后的队列:wen;ton;mon;所以读取的顺序wen;tou;mon)
rpop weekdays (此时如果从右侧弹出一个数据应该是mon)
llen weekdays  (获取此键里元素的个数)
lrange weekdays 0 2  (查看0-2 所对应的元素)
ltrim weekdays 0 1  (只留0号和1号元素,其他的元素都移除)

rpush weekdays mon tou wen  (从右侧压入三个数据)
lindex weekdays 0 (查看第一个数据:是mon;第二个数据:tou;第三个数据:wen)
(压入之后的队列:mon;tou;wen所以读取的顺序 mon;tou;wen)
rpop weekdays (此时如果从右侧弹出一个数据应该是wen)

3、字符串集合(sets)

help @set  (查看详细的命令)

SADD   (创建一个集合)
SPOP
SREM  (从指定键中移除某个元素)
SRANDMEMBER
SINTER   (求交集的)
SUNION    (求并集的)

示例:

sadd stus tom jeery lili hehe  (创建一个新的集合)
spop stus (从集合中弹出一个元素,不写个数默认弹出一个。弹出的是随机的)
srem stus lili   (删除集合中,指定的某一个元素)
scard stus  (查看集合当中元素的个数)
smembers stus (查看集合中具体的元素)
sinter stus stus2   (对两个集合做交集运算)
sunion stus stus2  (对两个集合做并集运算)
sdiff stus stus2   (求两个集合的差集: sdiff stus2 stus:这样两种的差集是不一样的)

4、有序字符串集合(sorted sets)对集合中的元素加上评分。

help @sorted_set (查看详细的命令和信息)

ZADD  #添加
ZCARD  #查看元素个数
ZCOUNT  
ZRANK

示例:

zadd z1 100 tom 33 jerry 88 abab 77 hehe  (添加4个元素及对应的值)
zcard z1  (查看元素的个数)
zrank z1 tom   (查看tom 所对应的节点,已经排好序了,最大的值其元素节点号越大;所以节点为0的元素应该是Jerry,因为他的值最小)
zrange z1 0 2  (取出0-2号节点的元素)
zrangebyscore z1 60 100 (取出得分在60-100之间的元素)

5、哈希(hashes)

@hash

HSET   (设定多个键值对)
HMSET
HGET   (一次获取一个键值)
HMGET (一次获取多个键值)
HKEYS    (获取所有键)
HVALS   (获取键里的所有值)
HDEL   (删除某个字段)
HGETALL  (一次获取所有的键和值)

示例

hmset stu id 1 name tom age 13 (创建一个stu键,里面包含三个键值对)
hkeys stu (获取此主键stu里的所有键的列表:id ;name;age;)
hvals stu   (获取此键里的所有值:1;tom;13;)
hset stu age 11  (改变某一个键的值)
hstrlen stu name (获取name键里元素值的字符长度)
hget stu name  (获取name键里的值)
hdel stu age (删除age键和其对应的值)
hgetall stu (一次获取此主键里的所有键和值)

而关于key,有几个点要提醒大家

而关于key,有几个点要提醒大家:
key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且会降低查找的效率;
key也不要太短,太短的话,key的可读性会降低;
在一个项目中,key最好使用统一的命名模式,例如user:10000:passwd。

redis 的参数配置和命令详解

redis-cli -a   “自设置的密码”(输入密码进入数据库)
127.0.0.1:6379> ping    (发出ping,会回应pong已检测服务器的状态是否健康)
PONG
select 2  (用来切换数据库的默认是0号数据库)
keys * (可以显示当前数据库所有存在的键)
quit  (退出客户端)
flushdb   (清空当前数据库的内容)
flushall  (清空所有库中的所有键数据)温馨提示:清空的命令慎用,比较危险,一不小心成了删库跑路
client list (列出所有客户端的连接信息)
client setname  (设定客户端连接的名称)
client getname  (获取连接的名称)
client kill   (断开哪个连接本机的客户端)
shutdown   (关闭服务器)
config get   (获取本机的配置参数:config get requirepass:获取本机的密码 config get maxclients:获取本机的最大并发连接数)
config set   (设定本机的配置参数 config set maxclients 10002:设定本机最大的并发连接数。及时生效,不需要重启服务)
config rewrite  (将刚才在命令行修改的配置参数,保存到配置文件里,将原有的配置参数覆盖掉)
info  (查看redis的内部状态信息)
info cpu   (只看某一段的信息;如只看cpu的)

配置何使用redis

vim /etc/redis.conf

############ GENERAL ################  (通用配置)

daemonize no (是否运行为守护进程;使用systemctl开启进程,设为no,如果是脚本开启,此项要开启)
databases 16 (设定默认库的个数;databases -1 就代表数据库的个数不受限制,)

############ SNAPSHOTTING ############## (基于快照做持久化,默认启用的)

dbfilename “dump.rdb” 默认设置快照的文件名
dir “/var/lib/redis”   (快照文件存放的路径;实际工作中需要更改到内村较大的磁盘位置;并且将指定的目录的属主和数组都设定为redis所有)
rdbchecksum yes  (每次保存是否要启用校验码校验,默认为启用的,也应该是启用的)
rdbcompression yes   (快照完是否要压缩存放,默认是yes,也应该是启用的)
stop-writes-on-bgsave-error yes (当保存快照时出现错误是否要停止redis的写操作)
关于何使做一次快照定义的规则:(可以自定义规则)
save 900 1   (在900s内数据发生了以此修改就做一次快照;如果还没有一次修改就不需要做快照了)
save 300 10 (在300s内数据发生了十次的修改就做一次快照;如果此条件还没满足则执行上面的条件)
save 60 10000  (在60s内数据发生了一万次修改就做一次快照;如果没满足此条件则执行上面的条件)

########### APPEND ONLY MODE #################(基于AOM做持久化的默认不启用)

appendonly no  (默认关闭此种持久化的方法;若要启用更改此项配置就可以了)
appendfilename “appendonly.aof”   (默认生成文件的文件名;文件存放的路径默认为和快照文件放在一起的,也可以自己指定路径去存放)
auto-aof-rewrite-percentage 100  (变化的文件和总文件相比超出50%就触发一次重写操作)
auto-aof-rewrite-min-size 64mb  (当文件的最小大小为64M;上下两个条件要同时满足)
appendfsync everysec(当有键发生变化1s内执行记录操作)

 

############## NETWORK ################(网络方面的)

protected-mode yes   (保护模式 ,默认下无论监听什么地址都只能通过172.0.0.1来连接)
timeout 0   (客户端连接上,多久不操作就断开连接,=0代表永久不超时,不断开连接;当连接连接量较大时,应该设定一个值,来防止那些连接上又不操作的客户端,以保证其他连接能正常不会阻塞)
tcp-keepalive 300   (tcp的连接超时时常)

 ############ SECURITY ################ (安全方面的)

requirepass “centos”   (启用并设置密码)481行
rename-command flush set   (将命令重命名;但在主从复制下不推荐使用因为,从服务器无法识别主服务器上的别名命令,就可能无法实现数据的同步操作)

############## LIMITS ###############(资源限制相关的)

maxclients 10000  (最大并发连接数量)
maxmemory       (当前内存上指定拿出多少来当redis的内存存储来用,单位是字节;如果不设置此项,默认会将本机所以的内存来当存储,直至本机的内存沾满;一旦本机的内存耗尽,内核会自动杀死最耗内存的进程,所以此项应该设定)
MAXMEMORY POLICY(内存淘汰策略;当redis的内存达到上限,采用什么淘汰机制)
maxmemory-policy noeviction(默认使用的是此机制)
volatile-lru;淘汰那些设定过期时间基于lru算法(最近最少使用的)
allkeys-lru :淘汰所有的键基于lru算法 (当缓存使用时不要采用此算法)
volatile-random:仅对设置了过期时间的做随机淘汰
allkeys-random :所有键随机淘汰
volatile-ttl:对设置过期时间进行逆序淘汰,主要看谁的过期剩余时间
noeviction :不淘汰任何键,只是再内存占满时,发出报错
maxmemory-samples 5 (每次将五个键做对比来淘汰;如果将全部键都拿来作比较,来选择淘汰谁,太浪费资源了,所以每次取5个键来做比较,也可自己设置;5个已经足够接近真实了;10个最真实;3个最快)

############# SLOW LOG ##################(慢查询日志)

slowlog-log-slower-than 10000 (一个键的执行时常超过0.01秒就认为是慢的;单位是微秒)

########## ADVANCED CONFIG ##############(高级配置)

hash-max-ziplist-entries 512 (设定最多有多少个键值对)
hash-max-ziplist-value 64 (每一个键和值的字节最大不能超过64个字节)
client-output-buffer-limit normal 0 0 0(正常客户端;缓冲池的大小。既接收数据的大小)
client-output-buffer-limit slave 256mb 64mb 60(从服务器客户端;256mb 64mb 60从服务器可以超过64M最大不能超过256M,且时间在60秒内;256硬限制:不可超过的;64为软限制可以超过但有时间限制,限制为60秒)
client-output-buffer-limit pubsub 32mb 8mb 60 (发布订阅队列的客户端)
缓冲数据:就是接收和发送数据,在对反未接收之前的在本地的缓冲。

Redis的持久化

1 .  RDB:snapshotting, 二进制格式;按事先定制的策略,周期性地将数据从内存同步至磁盘;数据文件默认为dump.rdb;(缺点:在做快照的那一秒做的操作就会丢失)
客户端显式使用SAVE或BGSAVE命令来手动启动快照保存机制;

SAVE;手动去触发快照。即在主线程中保存快照,此时会阻塞所有客户端请求;
BGSAVE:手动去触发快照;在后台启动一个线程去执行快照操作,前台的客户请求正常进行
2 .  AOF:Append Only File, fsync
记录每次写操作至指定的文件尾部实现的持久化;当redis重启时,可通过重新执行文件中的命令在内存中重建出数据库;(将redis的每一条命令都记录下来,然后通过重放来恢复数据,和MySQL的二进制日志相同;这种方式相较于快照的方式效率低,但不会丢失数据)
BGREWRITEAOF:AOF文件重写;手动触发的方式
不会读取正在使用AOF文件,而是通过将内存中的数据以命令保存至临时文件中,完成之后替换原来的AOF文件

两个方式之采取一种就可以了,系统默认是使用做快照的方式来将数据做持久化写入磁盘里去。

实验:实现redis的主从配置

1 .、主机器上

#yum install redis

编辑配置文件:

#vim /etc/redis.conf
  bind 0.0.0.0  #更改此项
requirepass centos   #添加此行设置密码 ,481行
#ss -nult   #查看端口号是否开启,端口号:6379

2 、从节点上的配置

note01:

#yum install redis
编辑配置文件:
#vim /etc/redis.conf
  bind 0.0.0.0   #更改此项,本机所有IP都绑定
  slaveof 192.168.130.10 6379   #添加此行设定主节点的IP地址和端口,266行
  masterauth centos  #指定主节点的密码,274行
  requirepass centos    #添加此行设置密码,482行
#systemctl start redis (启动服务)
#ss -nult | grep 6379 (查看端口号是否开启)6379

note02:

#yum install redis
编辑配置文件:
#vim /etc/redis.conf
  bind 0.0.0.0   #更改此项,本机所有IP都绑定
  slaveof 192.168.130.10 6379   #添加此行设定主节点的IP地址和端口,266行
  masterauth centos  #指定主节点的密码,274行
  requirepass centos    #添加此行设置密码,482行
#systemctl start redis (启动服务)
#ss -nult | grep 6379  (查看端口号是否开启)6379

3、最后在主节点上进入到数据库中

#redis-cli     #进入数据库
127.0.0.1:6379> auth centos  # 输入验证密码
OK
127.0.0.1:6379> client list  #列出所有的服务器会发现有从客户端
id=4 addr=192.168.130.8:34837 fd=6 name= age=889 idle=1 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf
id=5 addr=192.168.130.11:38857 fd=7 name= age=746 idle=1 flags=S db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=replconf  #从客户端
id=6 addr=127.0.0.1:42176 fd=5 name= age=42 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
127.0.0.1:6379> INFO replication   #查看主从节点的详细信息
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.130.8,port=6379,state=online,offset=1443,lag=1
slave1:ip=192.168.130.11,port=6379,state=online,offset=1443,lag=0
master_repl_offset:1443
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1442

4、测试

在主节点上创建一个键
#redis-cli -a centos #在主节点上登录
  SET CLASS M30
#redis-cli -a centos #在从节点上登录 

127.0.0.1:6379> KEYS *  #查看数据库是否同步过来

1) "weekdays"
2) "CLASS"
3) "class"

127.0.0.1:6379> CONFIG GET slave-read-only  #(查看从节点是否有写操作);应该是没有写操作的权限,否则会造成数据的混乱不一致。

1) "slave-read-only"
2) "yes"


实验:在上述实验的基础上实现高可用

需要三台监控的服务器来实现对三台redis服务器的监控,监控机器的数为奇数,因为涉及到最后投票来确定主节点机器的服务确实是宕机了。为了防止一台机器的主观误判。
当主服务器宕机时,选择哪台从服务器作为主机器,首先要看其优先级,如果优先级相同则去判断他的IP,基于选举协议来实行的。
当主节点宕机之后,会重新选举从节点变为主节点,此时其他的从节点要删除已有的数据重新从现在的主节点上同步数据。

1、在主节点(Ip:192.168.130.10)

#vim /etc/redis-sentinel.conf  #修改监控的配置文件
port  26379   21行
bind 0.0.0.0   15行
sentinel monitor mymaster 192.168.130.10 6379 2 #监控主节点的IP地址及端口号和三台监控设备,至少有两台投票说它宕机了,才切换到备用主机上 69 行
sentinel auth-pass mymaster centos  #设置主节点的验证密码89行
sentinel parallel-syncs mymaster 5    #并行复制的节点数调整大一些
#systemctl start redis-sentinel   #启动监控服务
#ss -nult    #查看端口号是否开启了

2、在从节点

在note1上(IP:192.168.130.11)

#redis-cli -a centos  #登陆进数据库
config set slave-priority 90  #将优先级改为90
config rewrite   #将更改的数据进行保存
config get slave-priority  #验证是否生效
vim /etc/redis-sentinel.conf   #修改监控的配置文件
port  26379   21行
bind 0.0.0.0   15行
sentinel monitor mymaster 192.168.130.10 6379 2 #监控主节点的IP地址及端口号和三台监控设备,至少有两台投票说它宕机了,才切换到备用主机上 69 行
sentinel auth-pass mymaster centos  #设置主节点的验证密码89行
sentinel parallel-syncs mymaster 5    #并行复制的节点数调整大一些
systemctl start redis-sentinel #启动监控服务
ss -nult   #查看端口号是否开启了

note2(IP:192.168.120.8)

#redis-cli -a centos  #登陆进数据库
config set slave-priority 90  #将优先级改为90
config rewrite   #将更改的数据进行保存
config get slave-priority  #验证是否生效
vim /etc/redis-sentinel.conf   #修改监控的配置文件
port  26379   21行
bind 0.0.0.0   15行
sentinel monitor mymaster 192.168.130.10 6379 2 #监控主节点的IP地址及端口号和三台监控设备,至少有两台投票说它宕机了,才切换到备用主机上 69 行
sentinel auth-pass mymaster centos  #设置主节点的验证密码89行
sentinel parallel-syncs mymaster 5    #并行复制的节点数调整大一些
systemctl start redis-sentinel #启动监控服务
ss -nult   #查看端口号是否开启了

温馨提示:三份相同的配置文件可以复制过去使用,但要注意:sentinel myid号是否相同,需要不同才可以,如果相同,将此行删除之后重启服务就可以生成新的id号了,在69行

最后验证查看:#任意一台sentinel节点的机器上

#redis-cli -p 26379   #登陆到数据库
sentinel masters  #查看主节点机器的详细信息
sentinel slaves mymaster  #查看备用节点的详细信息及个数

模拟主节点宕机:手动将主节点的redis服务暂停:

此时在备用的从节点上登陆:#redis-cli -p 26379
查看现在的主节点是那台机器:sentinel masters  #可以发现主节点的机器变为备用的主的机器了
此时将主节点机器修复后,在此添加进去,作为备用主机来用
vim /etc/redis.conf   #修改原来主节点的配置文件,让其成为从节点使用
slaveof 192.168.130.10 6379  #指定新的主节点机器的IP地址和端口号,266行
masterauth centos#指定新的主机点的密码,273行
#systemctl restart redis  #启动服务
此时到现在的主节点上去看,发现自己已经添加到备用节点上去了
sentinel slaves mymaster  #查看备用节点的详细信息及个数
也可查从节点的日志信息:
# tail /var/log/redis/sentinel.log 
2530:X 24 Jul 15:50:09.020 # +sdown master mymaster 192.168.130.10 6379
2530:X 24 Jul 15:50:09.112 # +new-epoch 1
2530:X 24 Jul 15:50:09.114 # +vote-for-leader a9ce06f957b98fd5dcaae0c43b55dff4aa08f3cf 1
2530:X 24 Jul 15:50:09.666 # +config-update-from sentinel a9ce06f957b98fd5dcaae0c43b55dff4aa08f3cf 192.168.130.8 26379 @ mymaster 192.168.130.10 6379
2530:X 24 Jul 15:50:09.666 # +switch-master mymaster 192.168.130.10 6379 192.168.130.11 6379
2530:X 24 Jul 15:50:09.667 * +slave slave 192.168.130.8:6379 192.168.130.8 6379 @ mymaster 192.168.130.11 6379
2530:X 24 Jul 15:50:09.667 * +slave slave 192.168.130.10:6379 192.168.130.10 6379 @ mymaster 192.168.130.11 6379
2530:X 24 Jul 15:50:39.687 # +sdown slave 192.168.130.10:6379 192.168.130.10 6379 @ mymaster 192.168.130.11 6379
2530:X 24 Jul 15:57:33.730 # -sdown slave 192.168.130.10:6379 192.168.130.10 6379 @ mymaster 192.168.130.11 6379
2530:X 24 Jul 15:58:40.082 * +reboot slave 192.168.130.10:6379 192.168.130.10 6379 @ mymaster 192.168.130.11 6379

 

posted @ 2018-07-24 16:32  琼兔  阅读(319)  评论(0编辑  收藏  举报