redis分布式系统一些基础理论:CAP/BASE
CAP大体描述的是任何分布式系统最多只能满足此三种特性
C分区容错性A可用性P一致性
中的两者。,现在的分布式系统,大多数才用AP逻辑的
AP:尽量保证可用性,同时提供容错性,追求弱一致性,通常追求的是最终一致性
在CAP基础之上,衍生出了第二种理论,BASE
BA:基本可用、
S:软状态、
E:最终一致性
基本上现在的分布式系统就是靠这两个理论支撑构建的,这两个理论是当今众多分布式系统得以构建的基石
**分布式系统大致可以分为2类
第一类 分布式存储:
有两个子类
第一子类NoSQL:
kv、document、column families、GraphDB
分布式文件系统: 没有对我们的存储系统接口做进一步抽象,甚至还做了进一步弱化,本来应该有的属主,属组,权限的模型也被剥离,仅保留文件名,时间戳等几个基本的属性
文件系统接口
分布式存储:API,不能挂载;
第二类 分布式运算:mapreduce, …(hadoop或是google公布的三大分布式系统论文当中,其中有一篇描述过,在google内部是如何实现所谓分布式计算的
mapreduce的思想被hadoop作者山寨了,现在为止mapreduce也是组成hadoop两个核心组件的其中之一,只不过现在的mapreduce被底层的yum所调用
**
事实上在分布式系统种还有第三种,叫做NewSQL
新式sql从基本上是兼容关系型数据库中的众多特性的,从设计最初,从基因上它就是分布式的,
国内有以加公司做一个tatd,原生兼任mysql
之前利用mysql,但是存储和分布遇到各种性能和瓶颈的组织,没准算得上是一个不错的选择
NewSQL:
PingCAP:TiDB(MySQL protocol)…
nosql的众多流派中包含了kvstore,document stroe ,column store
kv、document、column families、GraphDB
redis属于kv存储的典型代表
redis:REmote DIctionary Server 远程字典服务器
大体上支持数据结构:String 字符串(也支持数值,这里的数值也是字符串但是可以隐式转换成数值参与计算), List(列表,数组), Set(集合,支持交叉并计算), sorted_set(有序集合,每一个元素都有两个标识1.score分数,2.index索引,有序可按索引排序,也可按分数排序), Hash (字典,关联数组), pubsub(发布订阅,) …还支持位图,地理坐标,还支持辐射搜索.
回顾:
分布式系统两个基础理论:CAP/BASE
CAP:AP,CP
C、A、P:三者其中之二;
AP:可用性、分区容错性、弱一致性;
BASE:BA,S,E
BA:基本可用、S:软状态、E:最终一致性;
分布式系统:
分布式存储:
NoSQL:
kv、document、column families、GraphDB
分布式文件系统:文件系统接口
分布式存储:API,不能挂载;
分布式运算:mapreduce, ...
NewSQL:
PingCAP:TiDB(MySQL protocol)...
redis:REmote DIctionary Server
数据结构:String, List, Set, sorted_set, Hash, pubsub ...
redis运行和维护的常用配置
redis的整个配置内容,大体上可以分为几个组成的配置段
这些事配置段
include 包含,可以包含其他配置文件的,说白了就是i配置文件模块化的一种机制
network跟网络配置相关,就是配置端口
general一般通用的配置
snaphottng 这是redis持久机制中的一种,快照机制,有点类似备份逻辑
replication 主从同步复制
security 安全相关,
limits i资源限制,比如能用多少内存
append only mode 另外一个持久化机制,两个持久化机制可以都启用,也可以启用一种,类似于二进制日志,每一次启动时或每次有写操作时,都会存在一个文件当中,下一次开机后,能把里面的操作重放,能够更好地做时间点回复
虽然近似于二进制,但是不全是
lua scripting lua脚本
redis cluster
slow log 慢查询日志
latency monitor 延迟监控
event notification 事件通知
advanced config 高级配置
可以大概知道每一段大概有哪些配置参数
Redis(2)
配置和使用Redis:
基本配置项
网络配置项
持久化相关配置
复制相关的配置
安全相关配置
Limit相关的配置
SlowLog相关的配置
INCLUDES
Advanced配置
通用配置项:
daemonize(是否以守护进程运行)
, supervised,
loglevel日志级别
, pidfile指明redis守护进程的pid文件位置
, logfile, 日志文件位置
databases:设定数据库数量,默认为16个,每个数据库的名字均为整数,
从0开始编号,默认操作的数据库为0;
切换数据库的方法:
SELECT
general一般通用的配置
supervised 如果要使用upstart所谓的init进程或者systemd来实现管理redis,redis可以与我们的supervision tree 进行交互,如何交互可以自行定义
no表示不交互,
upstart 向upstar发信号
systemd 向systemd发信好
auto 自动选择
最好选择no 不用去修改
**最终要的一段network
bind监听哪个地址,如果主机有多个地址,那么只监听把服务提供给那个主机的网络的本机地址
默认redis无认证功能,只要访问redis,任何人都能看到数据
最好在iptables层施加访问策略,额外再让redis做认证
**
protected-mode yes 是否工作于保护模式的,
是一个安全防护的层,用户避免,redis实例,处于开放状态,裸奔再互联网上,让人随意访问和劫持
如果设置on或yes,并且如果说
1.如果你的服务器没有显示这个指令bind绑定监听了某地址。(这个用yes,但是没使用bind,手动绑定监听在某地址上
2.,你也没设定密码
意味着这项就生效了
bind 没指,默认也是监听在0.0.0.0上
没有require pass redis就仅允许本地访问了
重启服务,使用一个远程主机来链接,安装redis才有redis-cli
并没有启用保护模式,因为启用保护模式,无论监听哪个端口,只能从本地链接
如果是私网中使用,而且不打算公开给任何人,改一下端口可能会更安全点
tcp-backlog,backlog 后援队列,指明tcp链接的队列长度的
unixsocket 本地链接也可以监听一个socket文件,本地到本地就不用通过协议栈通信,更加高效
如果用不到可以注释
timeout,客户端链接,空闲超时时间
redis每一客户端连接进来们就要维持一个链接,意味着内存中需要占据空间,保持这些数据,如果客户端长期没有维持操作,是对redis是一个额外负担,0表示不超时
redis繁忙的话,可以设置超时
tcpkeepalived,指tcp保持链接多长时间的,虽然用户redis协议断开了,tcp链接依然在,下一次还可以使用,实现tcp链接的复用,不用3次握手,这对短链接的redis比较有用,可以更加高效的创建会话
网络配置项:
bind IP
port PORT
protected-mode
tcp-backlog
unixsocket
timeout:连接的空闲超时时长;
require pass 做认证的
其实还有第二个指令rename-command
redis有个命令config,能直接配置redis全局服务参数,非常危险,尤其让别人绕过认证访问,可能危害到redis,所以可以改个名
但是别人能看到配置文件也没用,第二点如果你启用主从复制,从服务器看到这个字符串也懵了,除非让从服务器也提供类似配置,并不实用
AOF是类似二进制日志一样的持久机制
limits做各种限制的
maxclients 最大并发链接数 默认10000
并发连接数和每秒完成的操作数是两回事
maxmemory 最大内存,最大可有多少内存由redis来存数据,为了redis一直有性能的优越表现,建议设定最大内存,而且是当前物理内存可保证使用的大小
内存淘汰策略很关键,缓存项淘汰策略,
一旦内存使用已经达到了我们使用的最大值,有几种策略,
默认的是noeviction 不启用淘汰机制,意味着满了,再存数据就报错了,否则可以基于缓存机制淘汰
volatile -lru 此前设置字符串的有一个ex(过期时间)的选项,把哪些拥有过期时间ex的key键哪来LRU算法,淘汰一些,腾出一些空间来
allkey-lru 代表可以把所有的键都哪来,都淘汰掉,无论你有没用过期时间,这个就太蹦崩放了,有些键没设置过期时间,可能要长期使用他的,一淘汰掉就比较麻烦
volartile-random 把拥有过期时间的一些设定的键,随机淘汰
allkeys-random 所有键随机淘汰
volatile-ttl 设定过期时间的键,按时间终结的长度来进行淘汰,谁离终结时间越近就淘汰谁
noeviction 没淘汰
用来做缓存时可以用volatile-ttl ,volatile -lru
maxmemory-sample
sample样本 如果把所有数据都取出来比较,按照volatile-lru算法杀一遍,那就比较低效,所以一般一次取5个,5个中选一个,选择范围不是整个数据中比较,而是根据样本数量,
Limits相关的配置:至关重要
maxclients
maxmemory <bytes>
maxmemory-policy noeviction
淘汰策略:volatile-lru, allkeys-lru, volatile-random, allkeys-random, volatile-ttl,
noeviction
maxmemory-samples 5
淘汰算法运行时的采样样本数;
SlowLog相关的配置: 慢查询
slowlog-log-slower-than 表示查询时间基于多久,就认为是慢查询操作
10000单位微妙=10毫秒=0.01秒
slowlog-max-len 记录日志,最大每一行不能超过多少个字节,值是128
lantency monitor 延迟,监视器
什么时候启用延迟监视器
latency-monitor-threshold =0 没有阈值,一直处于接受状态
event notification事件通知,不是重点
ADVANCED配置:高级配置
虽然是叫高级配置,但是主要配置各种各样的数据结构和内部所支持的数据数量之类的
hash-max-ziplist-entries 512 特定的hash(映射,关联数字),管理数组最多有512个成员或元素
hash-max-ziplist-value 64 每一个成员最大值不能超过64字节
设置ziplist的键数量最大值,每个值的最大空间;
client-output-buffer-limit normal 0 0 0 限制客户端一侧输出缓冲空间的大小(常规客户端)
client-output-buffer-limit slave 256mb 64mb 60 (主从复制的从服务器)
对slave最大可使用256M内存,这是硬限制
软限制是64,可超出64但是最大不超过256,并且超出部分256-64部分,在60s之后会自动强制清除
client-output-buffer-limit pubsub 32mb 8mb 60 (发布订阅中的订阅)
各自对可使用空做了控制 ,分别是硬限制,软限制,和软限制的可超时时长
网络配置,安全配置,limits设置通常不会使用默认值设定,而大多数情况下,
他们的默认 除了bind,require pass和maxmemory,maxclients
都使用默认值可能也没什么问题
redis-cli命令:
Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
-h HOST
-p PORT
-a PASSWORD
-n DBID
与Connection相关命令:
help @connection
AUTH <password>
ECHO <message>
PING
QUIT
SELECT dbid
清空数据库:
FLUSHDB:Remove all keys from the current database
清空当前数据库;
FLUSHALL:Remove all keys from all databases
清空所有数据库;
Server相关的命令:
CLIENT GETNAME
*CLIENT KILL
CLIENT KILL [ip:port] [ID client-id] [TYPE normal|master|slave|pubsub]
[ADDR ip:port] [SKIPME yes/no]
*CLIENT LIST
CLIENT PAUSE
CLIENT PAUSE timeout
CLIENT REPLY
CLIENT SETNAME:Set the current connection name
SHUTDOWN [NOSAVE|SAVE]
**配置参数允许允许时修改:意味不用编辑配置文件,来重启redis
CONFIG GET 获取
CONFIG RESETSTAT 重置各种状态(各种计数器,info计数,链接的客户端之类的,很多计数器可以使用resetat可以重置的)
CONFIG REWRITE
CONFIG SET 设定 (默认保存在内存中,redis重启就失效了,为了避免失效,使用CONFIG REWRITE,
利用内存中的设定,覆盖你的配置文件中的设定
打开配置文件看看,是在配置文件最后追加的,如果你配置文件有了,也会覆盖的,这就是为什么建议要用rename-command来改下config命令,比较危险
** INFO:服务器状态信息查看;分为多个secion;
INFO [section]
最核心的内容,是持久化
redis的inmemory store,基于内存的存储,因此所有存储功能都是在内存中生效的,如果说我们重启了服务,很显然内存和数据都没了,为了避免出现这样的问题,redis要求要做持久化,这个持久化仅仅是把数据持久保存在磁盘上,而不是基于磁盘做存储(不是基于磁盘提供服务的,)
redis的整个服务是基于内存的,放在磁盘上的目的是额外补充一个持久功能,万一重启了,redis把磁盘上数据读入到内存,依然在内存中进行工作,不像mysql在内存中只有一部分数据
任何数据不在内存中,就从磁盘上进行装载到内存中,redis的所有数据都在内存中。
redis的持久化仅仅是数据功能的补充,就是为了实现持久而持久,持久逻辑有两种,
1.RDB:snapshotting, 二进制格式;按事先定制的策略,周期性地将数据从内存同步至磁盘;
数据文件默认为dump.rdb;手动触发,客户端显式使用SAVE或BGSAVE命令来手动启动快照保存机制
RDB两个命令:
SAVE:同步,即在主线程中保存快照,此时会阻塞所有客户端请求;
BGSAVE:异步;(后台同步)启用BGSAVE,redis会启动一个子进程,由这个子进程在后台把数据从内存同步至磁盘,(先快照再同步,以免数据不一致),主程序可以向客户端继续提供服务
所谓的snapshotting快照。(redis跑起来的时候,,每隔一段时间就自动的把内存做一次快照,照下来直接保存为一个二进制文件,这个文件是RDB格式的文件,假如redis崩溃了没关系,下次启动,根据RDB重构在内存中,
什么时候持久化,持久化之后改的键值就丢失了,这相当于我们只有全量备份而没有增量,也没有二进制日志,无法做时间点还原,所以有可能要丢失一部分数据的)
2.AOF:Append Only File, fsync仅追加文件(就是此前类比的mysql日志,所有增删改查当中,所有引起数据改的操作的命令都直接记录再此文件中,按时序进行,所以将来重放一遍还能重构出数据来,相比较snapshot ing,这种方式就比较慢了,重放效率低,)所以为了完成重构的方式更加简洁,他需要不停地将AOF所生成的文件进行重构(插入数据10000次,执行10000次不如重构成一次),自动地来实现,因为命令很简单,不涉及到复杂业务逻辑,可以基于AOF文件直接完成重置,称为BGREWRITEAOF:
记录每次写操作至指定的文件尾部实现的持久化;当redis重启时,可通过重新执行文件中的命令在内存中重建出数据库;重建的时候为了高效所以要重写AOF文件
BGREWRITEAOF:AOF文件重写;BG(background 后台)不影响主程序
不会读取正在使用AOF文件,而是通过将内存中的数据以命令的方式保存至临时文件中,完成之后替换原来的AOF文件;
假如一个AOF文件,count1000次,从0加到了10000,重放10000命令没必要,
也没必要直接setcount 10000,对redis而言,所有数据都再内存中,你的count的键的值也一定是在内存中,直接把count键的值读出来,用一个合理的命令生成一个AOF文件即可,一旦重写完,原来的就没有用了,替换掉以后,会发现,有些键的数据还是会发生改变的,就再AOF里后加
改的多了就重新构AOF文件RDB高效但是会丢失数据,AOF虽然低效,但是几乎能做时间点恢复,能恢复到redis崩溃前 的一刻,默认启用的RDB,周期性的将内存同步到磁盘的
####RDB相关的配置:
*save <seconds> <changes>
save 900 1 900s内至少有一个key有变化,启动重新快照
save 300 10 300s内至少有10个key有变化,启动重新快照
save 60 10000 60s内至少有1W个key发生变化 就触发快照
表示:三个策略满足其中任意一个均会触发SNAPSHOTTING操作;900s内至少有一个key有变化,300s内至少有10个key有变化,60s内至少有1W个key发生变化;
从后往前更能明白时间跨度的意义,redis正常处理事务的能力是每秒50万-100万次
stop-writes-on-bgsave-error yes
dump操作出现错误时,是否禁止新的写入操作请求;
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb:指定rdb文件名
*dir /var/lib/redis:rdb文件的存储路径
RDB配置段在snapshotting当中
后面的是补充相关配置的
stop-writes-on-bgsave-error yes 一旦后台进行快照操作发生错误,是否让redis禁止新的写入操作请求
如果快照失败了意味着 数据无法持久,新写入的数据有可能因为数据崩溃而丢失数据的,倒不如完全阻止写入
dump操作出现错误时,是否禁止新的写入操作请求;
rdbcompression yes 构建的文件要不要压缩(看cpu资源更昂贵,还是磁盘空间更昂贵
rdbchecksum yes 要不要对rdm文件做校验,每次重读完后要不要做校验,做校验肯定会更浪费时间,(如果不做校验,将来恢复不了更麻烦)
dbfilename dump.rdb:指定快照rdb文件名
*dir /var/lib/redis:rdb文件的存储路径(可能要修改,放到一个高性的磁盘设备上,比如PCIE的固态硬盘上)、
AOF
默认仅启用了snapshotting,如果要启动AOF,把appendonly 改为yes即可,立即生效可在命令行修改
这个文件在snapshotting的dir中指定的位置,如果你使用了相对路径是这个样子的
此时把两种持久功能都启动起来了
下面由AOF所用到的策略,类似二进制日志一样,为了文件写入更高效,一般进程请求写操作时都是向内核发出的,内核一旦把这个请求的数据存到内核内存中就立即告诉进程存完了,但事实上,需要存到磁盘上去,内核也是为了提升性能表现,仅仅在自己的内存中存完就立即响应说存完了,好处是提升了用户体验,坏处是一旦服务器崩溃,明明存完的数据就没有了
下面就有定义appendfsync
Redis supports three different modes:
no:redis不执行主动同步操作,而是OS进行;
由内核决定写磁盘,内核偷懒,5秒写一次,就要丢失5秒的数据,任何文件的写操作都是由内核按照一定的策略将内核内存同步到磁盘,这种写操作对前端程序来讲是完全异步的
内核提供fsync机制,如果进程需要重要数据立即写磁盘,就调用,于是内核就知道像这类数据是不能缓存太久的要写到磁盘去
everysec:每秒一次;AOF这种方式能降低IO压力提高性能表现的,带来的结果,最悲剧就是丢失一秒的数据,一秒对于redis可不得了,50万个键
g
always:每语句一次;任何时候只要有数据被写入请求被内核接收到了,内存不能在自己的内存存完就响应ok,而是立即同步到磁盘上
会导致压力过大
no-appendfsync-on-rewrite no
是否在后台执行aof重写期间不调用fsync,默认为no,表示调用;
在rewrite的时候,是不是不要appendfsync,但是这样一来会有巨大的风险
老的AOF文件没有fsync,而新的文件还没写完,服务器崩溃,那些还没做fsync数据还在内存中,就丢失了,可能会丢失大部分数据
如果硬盘负载不大,可以启用no,即便在重写AOF文件,也要fsync,确保数据安全性
多少时间重写一次,重写是为了恢复时更高效(什么条件触发,多久重写一次),如果总体键变化幅度,超过原有数据的百分百,就立即触发重写,但是这样过于粗糙,可能会导致频繁重写(1个键,加一个键,就重写一次,没必要,),所以定义一个大小
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上述两个条件同时满足时,方会触发重写AOF;与上次aof文件大小相比,其增长量超过100%,
且大小不少于64MB;
aof-load-truncated(清除修减) yes
一个aof文件,在redis启动进程的最后,启动完了,数据重构好,原来AOF文件就不要了,要完全情况,重新构建,导致一个其他i情况,如果redis运行时突然崩溃,导致redis中止,一般会这么做
如果redis遇到这种情况,是不是支持这种功能,redis,意外中止重启之后,是否允许从内存中数据载入完成之后,把原有的AOF清除,再进程重构
注意:持久机制本身不能取代备份;应该制订备份策略,对redis库定期备份;
(误删数据,或者因为服务器各种情况,出现bug,要恢复数据,就必须要redis定期备份
redis 只要没重写,就可以把AOF,RDB文件复制一份就可以完成一次备份了
建议不要同时启用AOF,RDB,如果启用这两个操作也不会同时进行
RDB与AOF同时启用:
(1) BGSAVE和BGREWRITEAOF不会同时进行;
(2) Redis服务器启动时用持久化的数据文件恢复数据,会优先使用AOF;
Redis的持久化:
RDB:snapshotting, 二进制格式;按事先定制的策略,周期性地将数据从内存同步至磁盘;
数据文件默认为dump.rdb;
客户端显式使用SAVE或BGSAVE命令来手动启动快照保存机制;
SAVE:同步,即在主线程中保存快照,此时会阻塞所有客户端请求;
BGSAVE:异步;
AOF:Append Only File, fsync
记录每次写操作至指定的文件尾部实现的持久化;当redis重启时,
可通过重新执行文件中的命令在内存中重建出数据库;
BGREWRITEAOF:AOF文件重写;
不会读取正在使用AOF文件,而是通过将内存中的数据以命令的方式保存至临时文件中,
完成之后替换原来的AOF文件;
RDB相关的配置:
*save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
表示:三个策略满足其中任意一个均会触发SNAPSHOTTING操作;900s内至少有一个key有变化,
300s内至少有10个key有变化,60s内至少有1W个key发生变化;
stop-writes-on-bgsave-error yes
dump操作出现错误时,是否禁止新的写入操作请求;
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb:指定rdb文件名
*dir /var/lib/redis:rdb文件的存储路径
AOF相关的配置
*appendonly no
appendfilename "appendonly.aof"
*appendfsync
Redis supports three different modes:
no:redis不执行主动同步操作,而是OS进行;
everysec:每秒一次;
always:每语句一次;
no-appendfsync-on-rewrite no
是否在后台执行aof重写期间不调用fsync,默认为no,表示调用;
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上述两个条件同时满足时,方会触发重写AOF;与上次aof文件大小相比,其增长量超过100%,
且大小不少于64MB;
aof-load-truncated yes
注意:持久机制本身不能取代备份;应该制订备份策略,对redis库定期备份;
RDB与AOF同时启用:
(1) BGSAVE和BGREWRITEAOF不会同时进行;
(2) Redis服务器启动时用持久化的数据文件恢复数据,会优先使用AOF;