redis全称remote dictionary server(远程字典服务器)
redis是NoSQL(No Only SQL,非关系型数据库)的一种,NoSQL是以Key-Value的形式存储数据。当前主流的分布式缓存技术有redis,memcached,ssdb,mongodb等。
既能够把redis理解为理解为缓存技术,由于它的数据都是缓存在内从中的;
也能够理解为数据库,由于redis能够周期性的将数据写入磁盘或者把操做追加到记录文件中。
而我我的更倾向理解为缓存技术,由于当今互联网应用业务复杂、高并发、大数据的特性,正是各类缓存技术引入最终目的
html
问:redis这货凭什么能取代memcached?
1.支持的value类型相对于memcached更多。
2.支持持久化
redis数据存储在内存,会周期性地写入到磁盘。memcached则不会
node
问:自己程序的数据就是存储在内存里,为何用redis?
1.自身程序里的数据不能序列化
2.自身数据的读取不是原子性
由于redis是单进程单线程,之因此很快是由于底层用了io多路复用(epoll)
3.利于不一样语言的后端程序间通信mysql
通常来讲,开发者只须要本机使用包管理工具(apt,brew)下载便可。
但若想使用编译源码安装这一方式,点击这里linux
- 配置后台启动
redis
daemonize no ---- >daemonize yes
bind 127.0.0.1 ---> bind 0.0.0.0
- 启动redis服务端算法
redis-server /usr/local/etc/redis.conf
- 验证服务端是否启动成功sql
ps -ef | grep redis netstat -tunpl | grep 6379
- 客户端链接mongodb
/usr/local/redis/bin/redis-cli -h 192.168.2.128 -p 6379
# /usr/local/redis/bin/redis-cli -h 192.168.2.129 -p 6379 -a 12345
- 中止redis服务端数据库
/usr/local/redis/bin/redis-cli shutdown #或者 pkill redis-server
命令手册后端
select 1 # 切换到数据库1,范围是0~15。redis只能有16个db,不一样mysql(mysql的database能够有无数个) help set # 查看set到帮助信息 save # 手动持久化 flushdb # 清空当前库 flushall #16个库的数据全删了 dbsize # 看看有多少个值
info # 各个库的键值状况
keys * # 查看全部键,这是运维禁忌
keys z*,keys k? # 通配符匹配
exists key1 # 判断key1是否存在 move key1 2 # 将key1从当前数据库移动到2号数据库 expire key1 60 # 将key1设置为60秒后过时 ttl key1 # 查看key1还有多少秒过时 type key1 # 看看key1是什么类型 del key1 #删掉
rename k1 k2 # 更名
string类型是二进制安全的,意思是能够包含任何数据,好比jpg图片或者序列化的对象。字符串value最可能是512M
增 set k1 ‘ddd’ ex 3 # 设置3秒以后过时 setex k1 3 'ddd' # 同上,set with expire set k1 'ddd' NX # 和字典的setdefault效果同样 setnx k1 ddd # 同上,set if not exist set love ‘ddd' XX # 只有love这个key存在时这条命令才生效 getset k1 fuck # 先get再set mset apple 12000 xiaomi 2000 oppo 3300 # 批量设置,{'apple':12000,'xiaomi':2000,'oppo':3300} msetnx apple 12000 xiaomi 2000 # 只要有一个键存在,全体跪 查 get k1
strlen k1 # 返回k1字符串的长度,注意是字节长度(汉字是三个字节) 切片 getrange k1 0 -1 #切片 setrange k1 0 xxxxx # 这个注意,0表明设置字符的位置,多余的字符会覆盖掉后续已经存在的字符 数字加减 incr count # count为数字类型的字符串变量,count++ decr count # count-- incrby count 20 # count+=20 decyby count 20 # count-=20
value是一个小字典,经常使用于存储一个对象的详细信息。例如存储用户的具体信息等
若嵌套的话,API方法会帮你将列表,字典转化为字符串,不管递归到多深也不怕
增 hset info a 1 # {'info':{'a':1}} hmset info a 1 b 2 # {'info':{'a':1,'b':2}},其实hset就能够批量设置 hsetnx info a 1 # set if not exist 查 hgetall info # 获取hash的键值对元组 hkeys info # 取出全部键 hvals info # 取出全部值 hget info a # {'info':{'a':1,'b':2}},取value里面a键对应的值 hmget info a b # 批量取 删 hdel info a # 删除info里面的a 数字操做 hincrby info age 2 # 将age对应的value加2 hincrbyfloat info price 2.5 将price对应的value加2.5 通配符匹配指定key hscan info 0 match e* # 0表明全局匹配
value是一个列表,底层实际上是双向链表,有lpush,rpush
性能的话,因为是链表,头尾性能高,中间插入性能低
增 lpush li a b c # {'li':['a','b','c']} rpush li a # right push rpoplpush 源列表 目的列表 # 将源列表的右边的(rpop)弹出的值,lpush进新的列表 删 lpop # 左边弹出 rpop # 右边弹出 lrem li 2 3 # 删除2个'3' 查 lindex li 1 # 取出li[1] llen li # 长度 改 lset li 0 ff # li[0]='ff' linsert li before/after a aa # 在元素a以前(以后)插入aa,注意,这里用的不是索引值而是元素 切片 lrange li 0 -1 # 范围取值 ltrim key1 0 3 # 截取索引位置0~3多范围的值赋值给key1 数字操做 hincrby info age 2 # 将age对应的value加2 hincrbyfloat info price 2.5 将price对应的value加2.5 通配符匹配指定key hscan info 0 match e* # 0表明全局匹配
value是一个set
增 sadd s 1 2 2 3 3 4 # {'s':{'1','2','3','4'}} smove s1 s2 val_of_s1 # 将s1中的val的val_of_s1移动到s2 查 smembers s # 取出s的全部值 scard s1 # 得到s1集合里面元素个数 sismember s1 2 # 判断2是否为s1的元素 删 srem s1 fuck # 删除s1中的fuck srandmember s1 2 # 随机从s1删除2个元素 spop key # 随机删除一个元素 集合操做 sdiff s1 s2 #差集 ,即s1-s2 ,s1有的,s2没有 sinter s1 s2 #交集 sunion s1 s2 #并集
有序集合,按照指定的权重进行排序
增 zadd s1 60 v1 80 v2 100 v3 #数字是权重(计算机术语中score表明的是权重) 查 zcard s1 #返回val的数目 zcount s1 60 80 #统计权重60到80之间的数目 zrank s1 v3 #返回v3的下标,注意是相似数组的顺序 zrevrank s1 v3 # 逆序返回v3的下标 zscore s1 v3 #返回v3的权重值 zrange s1 0 -1 withscores # 显示权重 zrange s1 0 -1 # 只显示值,不显示权重。注意:0,-1是下标范围。不是像mysql limit同样的参数 zrevrange s1 0 -1 # 只显示值,不显示权重。注意:0,-1是下标范围。 zrevrangebyscore s1 90 20 # 逆向显示权重范围的,注意参数1要大于参数2 zrangebyscore s1 60 80 # 显示指定权重范围的 zrangebyscore s1 (60 (80 # '('为不包含 zrangebyscore s1 60 80 limit 2 2 #相似于mysql数据库 zrevrangebyscore s1 90 60 #因为是反转,权重是90到60 删 zrem s1 v3 #删除v3
二进制变量,经常使用于位计数法,节省内存
bitcount usercount # 定义 setbit usercount 999 1 # 设置bitcount 第999位为1, getbit usercount 22 # 获取第22位的值(0或1) bitcount usercount # usercount里1的个数
redis事务能够一次执行一组命令的集合,按顺序地执行而不会被其余命令插入。
redis会将命令集合中的命令依次塞入一个执行队列。
当使用exec命令时,要么一次性成功,要么所有失败(语法等严重错误),但若像incr username这种命令,运行时会报错可是其余命令得以正常执行(运行时异常)
问:redis不是单线程的吗,应该不用担忧数据竞争问题,为啥还要搞事务?
原本redis就是单线程的io多路复用,按道理说不该该考虑事务问题。
问题是在于,对于单一命令是不用考虑,可是对于一组命令要保证正确执行,就得作成事务。
若一个一个分散执行,结果极可能不如人意
问:为啥说redis对事务是部分支持?
1.不能回滚
当事务若是在执行过程当中有一条命令出异常(不是严重错误),其后的命令仍然会被执行,不会回滚
2.虽然说有隔离性。可是没有隔离级别概念
事务在执行过程当中,不会被其余客户端发送过来的命令请求所打断,由于事务提交前任何指令都不会被实际地执行,也就不存在“事务内的查询要看到事务里的更新,在事务外查询不能看到”这个头疼的问题
正常执行 1. multi 2. XXXXX命令 3. exec 放弃执行 multi XXXXX命令 discard #发现xxxx命令,我写入了不想执行的命令 watch 监控 # redis的乐观锁,若watch以后有任何key发生了变化,exec命令执行的事务都会被放弃,同时返回Nullmult-bulk应答以通知调用者事务执行失败 1. watch account # 盯着数据别让它改 2. multi 3. XXXXX命令 4. exec # account有人改了,返回nil。注意:一旦执行了exec以前watch锁都会被取消掉 5. unwatch # 取消对全部key的监控 6.从1 开始从头来过
先说说消息中间件这个概念。进程间的一种消息通讯模式:发送者发送消息,订阅者接收消息。经常使用于解藕
这个比RabbitQ简单不少,没有乱七八糟的交换机过滤啊,没有什么消息的持久化和确认性等待机制
这个就是,发布,你在线就收到,不在线就收不到
因此,redis能够作消息中间件,可是企业里面消息中间件确定不是用它作
subscribe c1,c2 c3 # 一次性订阅c1,c2,c3三个频道 publish c2 deep_dark_fantasity # 在c2频道发布消息 psubscribe c* # 使用通配符订阅多个频道
redis默认配置文件,点这里
Units单位指明里面的1K、1G等指的是大小,并且是大小写敏感
INCLUDES能够引入其余被分拆的配置文件
# 默认状况下 redis 不是做为守护进程运行的,若是你想让它在后台运行,你就把它改为 yes。 # 当redis做为守护进程运行的时候,它会写一个 pid 到 /var/run/redis.pid 文件里面,该文件能够经过pidfile制定 daemonize yes # 当 Redis 以守护进程的方式运行的时候,Redis 默认会把 pid 文件放在/var/run/redis.pid # 注意:当运行多个 redis 服务时,须要指定不一样的 pid 文件和端口 # 指定存储Redis进程号的文件路径 pidfile /var/run/redis.pid # 端口,默认端口是6379,生产环境中建议更改端口号,安全性更高 # 若是你设为 0 ,redis 将不在 socket 上监放任何客户端链接。 port 6379 # TCP 监听的最大容纳数量,此参数肯定了TCP链接中已完成队列(完成三次握手以后)的长度, # 当系统并发量大而且客户端速度缓慢的时候,你须要把这个值调高以免客户端链接缓慢的问题。 # Linux 内核会一言不发的把这个值缩小成 /proc/sys/net/core/somaxconn 对应的值,默认是511,而Linux的默认参数值是128。因此能够将这二个参数一块儿参考设定,你以便达到你的预期。 tcp-backlog 511 # 有时候为了安全起见,redis通常都是监听127.0.0.1 可是有时候又有同网段能链接的需求,固然能够绑定0.0.0.0 用iptables来控制访问权限,或者设置redis访问密码来保证数据安全 # 不设置将处理全部请求,建议生产环境中设置,有个误区:bind是用来限制外网IP访问的,其实不是,限制外网ip访问能够经过iptables;如:-A INPUT -s 10.10.1.0/24 -p tcp -m state --state NEW -m tcp --dport 9966 -j ACCEPT ; # 实际上,bind ip 绑定的是redis所在服务器网卡的ip,固然127.0.0.1也是能够的 #若是绑定一个外网ip,就会报错:Creating Server TCP listening socket xxx.xxx.xxx.xxx:9966: bind: Cannot assign requested address # bind 192.168.1.100 10.0.0.1 # 当客户端闲置多少时间后关闭其链接,默认是0,表示永不超时。 timeout 0 # tcp 心跳包。 # 若是设置为非零,则在与客户端缺少通信的时候使用 SO_KEEPALIVE 发送 tcp acks 给客户端。 # 这个之全部有用,主要由两个缘由: # 1) 防止死的 peers # 2) Take the connection alive from the point of view of network # equipment in the middle. # # 推荐一个合理的值就是60秒 tcp-keepalive 0 # 日志记录等级,4个可选值debug,verbose,notice,warning # 能够是下面的这些值: # debug (适用于开发或测试阶段) # verbose (many rarely useful info, but not a mess like the debug level) # notice (适用于生产环境) # warning (仅仅一些重要的消息被记录) # 默认为verbose loglevel notice #配置 log 文件地址,默认打印在命令行终端的窗口上,也可设为/dev/null屏蔽日志 #若配置redis为守护进程方式运行,而这里又配置为日志记录为标准输出,则日志将会发送给/dev/null logfile "/data/logs/redis/redis.log" # 要想把日志记录到系统日志,就把它改为 yes, # syslog-enabled no # 设置 syslog 的 identity(标识)。 # syslog-ident redis # Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. # syslog-facility local0 # 可用的数据库数,默认值为16,默认数据库为0,数据库范围在0-(database-1)之间 databases 16
# 在 900 秒内最少有 1 个 key 被改动,或者 300 秒内最少有 10 个 key 被改动,又或者 60 秒内最少有 1000 个 key 被改动,以上三个条件随便知足一个,就触发一次保存操做。 # if(在60秒以内有10000个keys发生变化时){ # 进行镜像备份 # }else if(在300秒以内有10个keys发生了变化){ # 进行镜像备份 # }else if(在900秒以内有1个keys发生了变化){ # 进行镜像备份 # } save 900 1 save 300 10 save 60 10000 # 默认状况下,若是 redis 最后一次的后台保存失败,redis 将中止接受写操做, # 这样以一种强硬的方式让用户知道数据不能正确的持久化到磁盘,不然就会没人注意到灾难的发生。若是后台保存进程从新启动工做了,redis 也将自动的容许写操做。 # 然而你要是安装了靠谱的监控,你可能不但愿 redis 这样作,那你就改为 no 好 stop-writes-on-bgsave-error yes # 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,若是为了节省CPU时间,能够关闭改选项,但会致使数据库文件变得巨大 # 默认设为 yes rdbcompression yes # 读取和写入的时候是否支持CRC64校验,默认是开启的 rdbchecksum yes # 备份文件的文件名,默认为dump.rdb dbfilename dump.rdb # 数据库备份的文件放置的路径 # 路径跟文件名分开配置是由于 Redis 备份时,先会将当前数据库的状态写入到一个临时文件 # 等备份完成时,再把该临时文件替换为上面所指定的文件 # 而临时文件和上面所配置的备份文件都会放在这个指定的路径当中,换句话说。这个配置项也关乎临时文件的存放位置 # 默认值为 ./ # dir ./ dir /data/redis/
# 设置该数据库为其余数据库的slave数据库时,设置master服务的IP及端口,在redis启动时,它会自动从master进行数据同步 # slaveof <masterip> <masterport> # 当master服务设置了密码保护时,slave服务链接的master的密码 # masterauth <master-password> # 当slave服务器和master服务器失去链接后,或者当数据正在复制传输的时候,若是此参数值设置“yes”,slave服务器能够继续接受客户端的请求,不然,会返回给请求的客户端以下信息“SYNC with master in progress”,除了INFO,SLAVEOF这两个命令 slave-serve-stale-data yes # 是否容许slave服务器节点只提供读服务 slave-read-only yes # Slaves 在一个预约义的时间间隔内发送 ping 命令到 server。你能够改变这个时间间隔。默认为 10 秒。 # repl-ping-slave-period 10 # 设置主从复制过时时间 # 这个值必定要比 repl-ping-slave-period 大 # repl-timeout 60 # 指定向slave同步数据时,是否禁用socket的NO_DELAY选 项。若配置为“yes”,则禁用NO_DELAY,则TCP协议栈会合并小包统一发送,这样能够减小主从节点间的包数量并节省带宽,但会增长数据同步到slave的时间。若配置为“no”,代表启用NO_DELAY,则TCP协议栈不会延迟小包的发送时机,这样数据同步的延时会减小,但须要更大的带宽。 一般状况下,应该配置为no以下降同步延时,但在主从节点间网络负载已经很高的状况下,能够配置为yes。 repl-disable-tcp-nodelay no # 设置主从复制容量大小。这个 backlog 是一个用来在 slaves 被断开链接时存放 slave 数据的 buffer,因此当一个 slave 想要从新链接,一般不但愿所有从新同步,只是部分同步就够了,即仅仅传递 slave 在断开链接时丢失的这部分数据。这个值越大,salve 能够断开链接的时间就越长。 # repl-backlog-size 1mb # 在某些时候,master 再也不链接 slaves,backlog 将被释放。若是设置为 0 ,意味着毫不释放 backlog 。 # repl-backlog-ttl 3600 # 指定slave的优先级。在不仅1个slave存在的部署环境下,当master宕机时,Redis Sentinel会将priority值最小的slave提高为master。这个值越小,就越会被优先选中 # 须要注意的是,若该配置项为0,则对应的slave永远不会自动提高为master。 slave-priority 100 # 若是主服务器超过一秒钟没有收到从服务器发来的REPLCONF ACK命令,那么主服务器就知道主从服务器之间的链接出现问题了。 # 经过向主服务器发送INFO replication命令,在列出的从服务器列表的lag一栏中,咱们能够看到相应从服务器最后一次向主服务器发送REPLCONF ACK命令距离如今过了多少秒: # 127.0.0.1:6379> INFO replication # Replication # role:master # connected_slaves:2 # slave0:ip=127.0.0.1,port=12345,state=online,offset=211,lag=0 #刚刚发送过 REPLCONF ACK命令 # slave1:ip=127.0.0.1,port=56789,state=online,offset=197,lag=15 # 在通常状况下,lag的值应该在0秒或者1秒之间跳动,若是超过1秒的话,那么说明主从服务器之间的链接出现了故障。 # Redis的min-slaves-to-write和min-slaves-max-lag两个选项能够防止主服务器在不安全的状况下执行写命令。 # 下面配置的是在从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令,这里的延迟值就是上面提到的INFO replication命令的lag值。 # min-slaves-to-write 3 # min-slaves-max-lag 10
# 设置链接redis的密码,默认无密码 # redis速度至关快,一个外部用户在一秒钟进行150K次密码尝试,需指定强大的密码来防止暴力破解 requirepass set_enough_strong_passwd # 重命名一些高危命令,用来禁止高危命令 rename-command FLUSHALL ZYzv6FOBdwflW2nX rename-command CONFIG aI7zwm1GDzMMrEi rename-command EVAL S9UHPKEpSvUJMM rename-command FLUSHDB D60FPVDJuip7gy6l
# 限制同时链接的客户数量,默认是10000。若是设置为0,表示不做限制 # 当链接数超过这个值时,redis 将再也不接收其余链接请求,客户端尝试链接时将收到 error 信息 # maxclients 10000 # 设置redis最大内存闲置,redis会在启动时将数据加载到内存中,达到最大内存后,redis会尝试清除已到期或即将到期的key,此方法护理后,若仍到达最大内存设置,将没法再进行写入操做,但仍然能够进行读取操做。 # 在删除时,按照过时时间进行删除,最先将要被过时的key将最早被删除 # maxmemory的设置比较适合于把redis看成于相似memcached 的缓存来使用 # maxmemory <bytes> # 达到最大内存时的缓存清除策略 # volatile-lru -> 使用LRU算法移除key,只对设置了过时时间的键 # allkeys-lru -> 使用LRU算法移除key # volatile-random -> 在设置了过时时间的key中随机移除,只对设置了过时时间的键 # allkeys-random -> 移除随机的key # volatile-ttl -> 移除那些ttl最小的key,即移除即将过时的key # noeviction -> 不进行移除,针对写操做,只是返回错误信息 # maxmemory-policy noeviction # 设置样本数量,lru算法和最小ttl算法都并不是是精确的算法,而是估算值。因此你能够设置样本的大小。redis默认会检查这么多个key并选择其中lru的那个 # maxmemory-samples 5
# redis 默认状况下时异步地把数据写入磁盘,即同步数据文件是按上面save条件来同步的,但若是发生诸如拉闸限电、拔插头等情况,那么将形成比较大范围的数据丢失。并且该备份很是耗时,且备份不宜太频繁。 # 因此redis提供了另一种更加高效的数据库备份及灾难恢复方式aof # 开启append only 模式后,redis 将每一次写操做请求都追加到appendonly.aof 文件中。redis从新启动时,会从该文件恢复出以前的状态。但可能会形成 appendonly.aof 文件过大,因此redis支持BGREWRITEAOF 指令,对appendonly.aof从新整理,默认是不开启的。 appendonly no # 指定日志记录文件名,默认为appendonly.aof。 appendfilename "appendonly.aof" # 设置对 appendonly.aof日志更新的条件,有三种选择always、everysec、no,默认是everysec表示每秒同步一次。 # always 表示每次更新后手动滴哦啊用fsync()将数据写到磁盘(慢,安全) # no 表示等操做系统进行数据缓存同步到磁盘,都进行同步 # everysec 表示对写操做进行累积,每秒同步一次(折中) # appendfsync everysec # 指定是否在后台aof文件rewrite期间调用fsync,默认为no,表示要调用fsync(不管后台是否有子进程在刷盘)。Redis在后台写RDB文件或重写afo文件期间会存在大量磁盘IO,此时,在某些linux系统中,调用fsync可能会阻塞。 no-appendfsync-on-rewrite yes # 指定Redis重写aof文件的条件,默认为100,表示与上次rewrite的aof文件大小相比,当前aof文件增加量超过上次afo文件大小的100%时,就会触发background rewrite。若配置为0,则会禁用自动rewrite auto-aof-rewrite-percentage 100 # 指定触发rewrite的aof文件大小。若aof文件小于该值,即便当前文件的增量比例达到auto-aof-rewrite-percentage的配置值,也不会触发自动rewrite。即这两个配置项同时知足时,才会触发rewrite。 # 生产环境中5G起步 auto-aof-rewrite-min-size 64mb aof-load-truncated yes
在redis中可使用eval命令执行lua脚本代码
192.168.127.128:6379>eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name liulei OK 192.168.127.128:6379>get name "liulei"
为了防止某个脚本执行时间过长致使Redis没法提供服务(好比陷入死循环),Redis提供了lua-time-limit参数限制脚本的最长运行时间,默认为5秒钟。当脚本运行时间超过这一限制后,Redis将开始接受其余命令但不会执行(以确保脚本的原子性,由于此时脚本并无被终止),而是会返回“BUSY”错误
# 一个Lua脚本最长的执行时间,单位为毫秒,若是为0或负数表示无限执行时间,默认为5000 lua-time-limit 5000
# 若是配置yes则开启集群功能,此redis实例做为集群的一个节点,不然,它是一个普通的单一的redis实例。 cluster-enabled yes # 虽然此配置的名字叫"集群配置文件",可是此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。一般是在收到请求以后这个文件就会被更新。 cluster-config-file nodes-6379.conf # 这是集群中的节点可以失联的最大时间,超过这个时间,该节点就会被认为故障。若是主节点超过这个时间仍是不可达,则用它的从节点将启动故障迁移,升级成主节点。注意,任何一个节点在这个时间以内若是仍是没有连上大部分的主节点,则此节点将中止接收任何请求。通常设置为15秒便可。 cluster-node-timeout 15000 # 若是设置成0,则不管从节点与主节点失联多久,从节点都会尝试升级成主节点。若是设置成正数,则cluster-node-timeout乘以cluster-slave-validity-factor获得的时间,是从节点与主节点失联后,此从节点数据有效的最长时间,超过这个时间,从节点不会启动故障迁移。假设cluster-node-timeout=5,cluster-slave-validity-factor=10,则若是从节点跟主节点失联超过50秒,此从节点不能成为主节点。注意,若是此参数配置为非0,将可能出现因为某主节点失联却没有从节点能顶上的状况,从而致使集群不能正常工做,在这种状况下,只有等到原来的主节点从新回归到集群,集群才恢复运做。 cluster-slave-validity-factor 10 # 主节点须要的最小从节点数,只有达到这个数,主节点失败时,它从节点才会进行迁移。更详细介绍能够看本教程后面关于副本迁移到部分。 cluster-migration-barrier 1 # 在部分key所在的节点不可用时,若是此参数设置为"yes"(默认值), 则整个集群中止接受操做;若是此参数设置为”no”,则集群依然为可达节点上的key提供读操做。 cluster-require-full-coverage yes
redis的slowlog是redis用于记录记录慢查询执行时间的日志系统。因为slowlog只保存在内存中,所以slowlog的效率很高,彻底不用担忧会影响到redis的性能
# slowlog-log-slower-than表示slowlog的划定界限,只有query执行时间大于slowlog-log-slower-than的才会定义成慢查询,才会被slowlog进行记录。slowlog-log-slower-than设置的单位是微妙,默认是10000微妙,也就是10ms slowlog-log-slower-than 10000 # slowlog-max-len表示慢查询最大的条数,当slowlog超过设定的最大值后,会将最先的slowlog删除,是个FIFO队列 slowlog-max-len 128
能够帮助咱们检查和排查引发延迟的缘由。
redis的slowlog在2.2.12版本引入,latency monitor在2.8.13版本引入。slowlog仅仅是记录纯命令的执行耗时,不包括与客户端的IO交互及redis的fork等耗时
latency monitor监控的latency spikes则范围广一点,监控事件的分类:
事件 | 事件内容 | 命令 | 详解 |
---|---|---|---|
command | 慢命令 | latency history command | 执行时长超过 latency-monitor-threshold阈值的慢命令 |
fast-command | 时间复杂度为O(1)和O(logN)的命令 | latency history fast-command | 时间复杂度为O(1)和O(logN)的命令 |
fork | 系统调用fork(2) | latency history fork | AOF 或RDB 子进程 |
# "CONFIG SET latency-monitor-threshold <milliseconds>" if needed. latency-monitor-threshold 0
# 模式订阅的配置 # 例如 notify-keyspace-events "gsExe"。便是说只容许监控Set结构的全部事件,而且之启用了键事件通知,没有启用键空间通知。 notify-keyspace-events ""
# 当hash中包含超过指定元素个数而且最大的元素没有超过临界时, # hash将以一种特殊的编码方式(大大减小内存使用)来存储,这里能够设置这两个临界值 # Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不一样实现, # 这个Hash的成员比较少时Redis为了节省内存会采用相似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap, # 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。 hash-max-zipmap-entries 512 hash-max-zipmap-value 64 # list数据类型多少节点如下会采用去指针的紧凑存储格式。 # list数据类型节点值大小小于多少字节会采用紧凑存储格式。 list-max-ziplist-entries 512 list-max-ziplist-value 64 # set数据类型内部数据若是所有是数值型,且包含多少节点如下会采用紧凑格式存储。 set-max-intset-entries 512 # zsort数据类型多少节点如下会采用去指针的紧凑存储格式。 # zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 # Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行从新hash,能够下降内存的使用 # # 当你的使用场景中,有很是严格的实时性须要,不可以接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。 # # 若是没有这么严格的实时性要求,能够设置为yes,以便可以尽量快的释放内存 activerehashing yes
# 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制) vm-enabled no # 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享 vm-swap-file /tmp/redis.swap # 将全部大于vm-max-memory的数据存入虚拟内存,不管vm-max-memory设置多小,全部索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,实际上是全部value都存在于磁盘。默认值为0 vm-max-memory 0 # Redis swap文件分红了不少的page,一个对象能够保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,做者建议若是存储不少小对象,page大小最好设置为32或者64bytes;若是存储很大大对象,则可使用更大的page,若是不 肯定,就使用默认值 vm-page-size 32 # 设置swap文件中的page数量,因为页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。 vm-pages 134217728 # 设置访问swap文件的线程数,最好不要超过机器的核数,若是设置为0,那么全部对swap文件的操做都是串行的,可能会形成比较长时间的延迟。默认值为4 vm-max-threads 4 # 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启 glueoutputbuf yes # 指定在超过必定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法 hash-max-zipmap-entries 64 hash-max-zipmap-value 512 # 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍) activerehashing yes
# 注意redis旨在作高速缓存,安全并非主要策略,因此redis默认不像mysql同样必定要你指定一个密码 # 1.查看redis的密码 config get requirepass # 2.设置redis密码 config set requirepass '12345' # 3.输入密码 auth 12345
上面端设置只要redis服务端重启后就失效,若要长久有效,须要在配置文件里配置
requirepass 12345 # 若是真的要为安全考虑,就必须设置复杂密码,redis是高并发的,弱密码很容易受到暴力破解
注意:除了进入redis后使用auth命令认证,还能够客户端启动时传入密码参数
/usr/local/redis/bin/redis-cli -h 192.168.2.129 -p 6379 -a 12345
在redis.conf中配置
1.远程链接redis要配置密码,并且还要修改bind 127.0.0.1 为 bind 0.0.0.0
2.设置密码
咱们已经说过,既能够把redis理解为缓存技术,也能够理解为数据库,由于redis支持将内存中的数据周期性的写入磁盘或者把操做追加到记录文件中,这个过程称为redis的持久化。redis支持两种方式的持久化,一种是快照方式(snapshotting),也称RDB方式;两一种是追加文件方式(append-only file),也称AOF方式。RDB方式是redis默认的持久化方式。
- RDB方式原理
当redis须要作持久化时(执行SAVA或者BGSAVA命令,或者是达到配置条件时执行),redis会fork一个子进程,子进程将数据写到磁盘上一个临时RDB文件中,当子进程完成写临时文件后,将原来的RDB替换掉(默认文件名为dump.rdb)
- RDB命令
一、执行SAVE命令,在当前线程执行,会卡住
二、执行BGSAVE命令,在后台线程执行,立刻返回
三、当符合用户给定的配置条件时Redis会自动将内存中的全部数据进行快照并存储在硬盘上。由两个参数构成:时间和改动的键的个数。当在指定的时间内被更改的键的个数大于指定的数值时就会进行快照
注意,SHUTDOWN命令会迅速生成dump.db文件(flushall+shutdown毁天灭地)
- RDB优缺点
定时备份,Redis效率高,可是容易形成数据丢失,丢失的多少和备份策略有关,例如:5分钟备份一次,可是第8分时宕机了,那么就丢失了后面的3分钟数据
- 为何aof会在rdb以后产生?
RDB方式是周期性的持久化数据, 若是未到持久化时间点,Redis 由于某些缘由而形成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。因此从redis 1.1开始引入了AOF方式,AOF 持久化记录服务器执行的全部写操做命令,并在服务器启动时,经过从新执行这些命令来还原数据集。 AOF 文件中的命令所有以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
AOF方式仍然有丢失数据的可能,由于收到写命令后可能并不会立刻将写命令写入磁盘,所以咱们能够修改redis.conf,配置redis调用write函数写入命令到文件中的时机。以下
#######################APPEND ONLY MODE ############################# ...... # AOF and RDB persistence can be enabled at the same time without problems. # If the AOF is enabled on startup Redis will load the AOF, that is the file # with the better durability guarantees. # # Please check http://redis.io/topics/persistence for more information. #启用AOF方式 appendonly yes #每次有新命令追加到 AOF 文件时就执行一次 fsync :很是慢,也很是安全 appendfsync always #每秒 fsync 一次:足够快(和使用 RDB 持久化差很少),而且在故障时只会丢失 1 秒钟的数据 appendfsync everysec #从不 fsync :将数据交给操做系统来处理。更快,也更不安全的选择 appendfsync no
从上面三种AOF持久化时机来看,为了保证不丢失数据,appendfsync always是最安全的。
- AOF优缺点
优势:AOF基本能够保证数据不丢失,数据完整性比rdb要高。
缺点: 1.AOF持久化文件会变的愈来愈大。例如咱们调用incr test命令100次,文件中必须保存所有的100条命令,其实有99条都是多余的。
2.频繁的IO和aof文件过大时的rewrite会带来系统波动,而且因为语句过多且不断变化,致使恢复数据速度慢于rdb,而且备份数据库可能会出bug。因此通常不单独使用(以防万一)
- 若是一个系统里面,同时存在rdb和aof,它们是冲突仍是协做?
二者能够共存,先加载的是aof。若是aof错误,redis-server起不来
- aof文件修复
redis-check-aof --fix xxx.aof 用来修复错误的aof文件,去除里面的错误数据(延时,丢包,病毒,大程序异常致使的文件错损等都会产生错误数据)
主从复制主要用于容灾恢复(主机挂了,能迅速切换到从机,而后去修从机)和读写分离。
主从复制有延迟这个不可避免的缺点,可是不妨碍其成为流行的技术
- 主从复制的特色
一个主服务器能够有多个从服务器。不只主服务器能够有从服务器, 从服务器也能够有本身的从服务器。
Redis 支持异步复制和部分复制(这两个特性从Redis 2.8开始),主从复制过程不会阻塞主服务器和从服务器。
Master Server是以非阻塞的方式为Slaves提供服务。因此在Master-Slave同步期间,客户端仍然能够提交查询或修改请求。Slave Server一样是以非阻塞的方式完成数据同步。在同步期间,若是有客户端提交查询请求,Redis则返回同步以前的数据。
通常是主写从读。如让多个从服务器处理只读命令,使用复制功能来让主服务器免于频繁的执行持久化操做。即只有主机能够写,从机不能够写
Master能够将数据保存操做交给Slaves完成,从而避免了在Master中要有独立的进程来完成此操做。
主机down了,从机不上位等待主机回归。若已经有从机上位(哨兵模式或者手动调整)以前的master将会变为slave为新的master服务
从机挂了,要从新使用slave of命令认主(能够写入配置文件避免)
- 主从复制过程
Redis主从复制过程示意图
从上面的示意图能够看出,主服务器与从服务器创建链接以后,Redis主从复制过程主要有下面几步:
从服务器对主服务器的复制能够分为如下两种状况:
可是SYNC命令是很是消耗资源的,SYNC是一个如此消耗资源的命令,因此Redis最好在真须要的时候才须要执行SYNC命令。
由于每次执行SYNC命令,主从服务器须要执行一下操做:
为了解决旧版复制功能在处理断线重复制状况时的低效问题,Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操做。
PSYNC命令具备完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式:
配从不配主
info replication #查看当前redis的角色
slave of 127.0.0.1 6379 #从机认主
slaveof no one # 丛机上位
见以下步骤: 1). 同时启动两个Redis服务器,能够考虑在同一台机器上启动两个Redis服务器,分别监听不一样的端口,如6379和6380。 2). 在Slave服务器上执行一下命令: /> redis-cli -p 6380 #这里咱们假设Slave的端口号是6380 redis 127.0.0.1:6380> slaveof 127.0.0.1 6379 #咱们假设Master和Slave在同一台主机,Master的端口为6379 OK 上面的方式只是保证了在执行slaveof命令以后,redis_6380成为了redis_6379的slave,一旦服务(redis_6380)从新启动以后,他们之间的复制关系将终止。 若是但愿长期保证这两个服务器之间的Replication关系,能够在redis_6380的配置文件中作以下修改: /> cd /etc/redis #切换Redis服务器配置文件所在的目录。 /> ls 6379.conf 6380.conf /> vi 6380.conf 将 # slaveof <masterip> <masterport> 改成 slaveof 127.0.0.1 6379 保存退出。 这样就能够保证Redis_6380服务程序在每次启动后都会主动创建与Redis_6379的Replication链接了。
这里咱们假设Master-Slave已经创建。 #启动master服务器。 [root@Stephen-PC redis]# redis-cli -p 6379 redis 127.0.0.1:6379> #状况Master当前数据库中的全部Keys。 redis 127.0.0.1:6379> flushdb OK #在Master中建立新的Keys做为测试数据。 redis 127.0.0.1:6379> set mykey hello OK redis 127.0.0.1:6379> set mykey2 world OK #查看Master中存在哪些Keys。 redis 127.0.0.1:6379> keys * 1) "mykey" 2) "mykey2" #启动slave服务器。 [root@Stephen-PC redis]# redis-cli -p 6380 #查看Slave中的Keys是否和Master中一致,从结果看,他们是相等的。 redis 127.0.0.1:6380> keys * 1) "mykey" 2) "mykey2" #在Master中删除其中一个测试Key,并查看删除后的结果。 redis 127.0.0.1:6379> del mykey2 (integer) 1 redis 127.0.0.1:6379> keys * 1) "mykey" #在Slave中查看是否mykey2也已经在Slave中被删除。 redis 127.0.0.1:6380> keys * 1) "mykey"
- 哨兵模式
通俗地讲,让哨兵(一个进程)盯着主机,主机一挂当即组织从机投票选取新的老大
反客为主的自动版,能都后台监控主机是否故障,若是故障了根据投票数自动将从库转换为主库
我所在的公司用不上redis集群,不过仍是做一下了解
详细
Redis从2.X版本开始,就支持一种基于非持久化消息的、使用发布/订阅模式实现的事件通知机制。
redis当消息订阅机制,简单一句就是你在线就收到,不在线就收不到。当消息订阅者因为各类异常状况而被迫断开链接,在其从新链接后,其离线期间的事件是没法被从新通知的(一些redis资料中也称为即发即弃)。
其使用的发布/订阅模式的机制并不是由订阅者周期性的从Redis服务拉取事件通知,而是由Redis服务主动推送事件通知到符合条件的若干订阅者。
Redis提供的订阅/发布功能并不完美,更不能和ActiveMQ/RabbitMQ提供的订阅/发布功能相提并论。
首先这些消息并无持久化机制,属于即发即弃模式。也就是说它们不能像ActiveMQ中的消息那样保证持久化消息订阅者不会错过任何消息,不管这些消息订阅者是否随时在线。
因为原本就是即发即弃的消息模式,因此Redis也不须要专门制定消息的备份和恢复机制。
也是因为即发即弃的消息模式,因此Redis也没有必要专门对使用订阅/发布功能的客户端链接进行识别,用来明确该客户端链接的ID是否在以前已经链接过Redis服务了。ActiveMQ中保持持续通知的功能的前提,就是可以识别客户端链接ID的历史链接状况,以便肯定哪些订阅消息这个客户端尚未处理。
Redis当前版本有一个简单的事务机制,这个事务机制能够用于PUBLISH命令。可是彻底没有ActiveMQ中对事务机制和ACK机制那么强的支持。而在我写做的“系统间通信”专题中,专门讲到了ActiveMQ的ACK机制和事务机制。
Redis也没有为发布者和订阅者准备保证消息性能的任何方案,例如在大量消息同时到达Redis服务是,若是消息订阅者来不及完成消费,就可能致使消息堆积。而ActiveMQ中有专门针对这种状况的慢消息机制。
咱们先从比较简单的publish命令和subscribe命令开始介绍,由于这组命令所涉及到的Channel(通道)和Redis中存储的数据相对独立。publish命令由发送者使用,负责向指定的Channel发送消息;subscribe命令由订阅者使用,负责从指定的一个或者多个Channel中获取消息。
如下是 publish 命令和 subscribe 命令的使用示例:
// 该命令向指定的channel名字发送一条消息(字符串) PUBLISH channel message // 例如:向名叫FM955的频道发送一条消息,消息信息为“hello!” PUBLISH FM955 "hello!" // 再例如:向名叫FM900的频道发送一条消息,消息信息为“ doit!” PUBLISH FM900 "doit!" // 该命令能够开始向指定的一个或者多个channel订阅消息 SUBSCRIBE channel [channel ...] // 例如:向名叫FM955的频道订阅消息 SUBSCRIBE FM955 // 再例如:向名叫FM95五、FM900的两个频道订阅消息 SUBSCRIBE FM955 FM900
若是您使用须要使用publish命令和subscribe命令,您并不须要对Redis服务的配置信息作任何更改。如下示例将向读者展现两个命令的简单使用方式——前提是您的Redis服务已经启动好了:
由客户端A充当订阅者,在ChannelA和ChannelB两个频道上订阅消息
-- 咱们使用的Redis服务地址为192.168.61.140,端口为默认值 [root@kp2 ~]# redis-cli -h 192.168.61.140 192.168.61.140:6379> SUBSCRIBE ChannelA ChannelB Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "ChannelA" 3) (integer) 1 1) "subscribe" 2) "ChannelB" 3) (integer) 2
-- 链接到Redis服务器后,直接运行PUBLISH命令,发送信息
[root@kp1 ~]# redis-cli -h 192.168.61.140 192.168.61.140:6379> PUBLISH ChannelB "hello" (integer) 1
-- 这时订阅者收到消息以下:
1) "message" 2) "ChannelB" 3) "hello"
从以上示例中能够看到,客户端A确实收到了客户端B所发送的消息信息,而且收到三行信息。这三行信息分别表示消息类型、消息通道和消息内容。注意,以上介绍的这组publish命令和subscribe命令的操做过程并无对Redis服务中已存储的任何Keys信息产生影响。
Redis中还支持一种模式订阅,它主要依靠psubscribe命令向技术人员提供订阅功能。模式订阅psubscribe最大的特色是,它除了能够经过Channel订阅消息之外,还能够配合配置命令来进行Keys信息变化的事件通知。
模式订阅psubscribe的Channel订阅和subscribe命令相似,这里给出一个命令格式,就再也不多作介绍了(可参考上文对subscribe命令的介绍):
// 该命令能够开始向指定的一个或者多个channel订阅消息 // 具体使用示例可参见SUBSCRIBE命令 PSUBSCRIBE channel [channel ...]
模式订阅psubscribe对Keys变化事件的支持分为两种类型:keyspace(键空间通知)和keyevent(键事件通知),这两类事件都是依靠Key的变化触发的,而关键的区别在于事件描述的焦点,举例说明:
当Redis服务中0号数据库的MyKey键被删除时,键空间和键事件向模式订阅者分别发送的消息格式以下:
// 如下命令可订阅键空间通知 // 订阅0号数据库任何Key信息的变化 192.168.61.140:6379> psubscribe __keyspace@0__:* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "__keyspace@0__:*" 3) (integer) 1 // 出现以上信息,说明订阅成功 // 当其余客户端执行 set mykey 123456 时,该订阅可收到如下信息 1) "pmessage" 2) "__keyspace@0__:*" 3) "__keyspace@0__:mykey" 4) "set"
以上收到的订阅信息,其描述能够归纳为:“mykey的键空间发生了事件,事件为set”。这样的事件描述着重于key的名称,而且告诉客户端key的事件为set。咱们再来看看订阅键事件通知时,发生一样事件所获得的订阅信息:
// 如下命令可订阅键空间通知 // 订阅0号数据库任何Key信息的变化 192.168.61.140:6379> psubscribe __keyspace@0__:* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "__keyspace@0__:*" 3) (integer) 1 // 出现以上信息,说明订阅成功 // 当其余客户端执行 set mykey 123456 时,该订阅可收到如下信息 1) "pmessage" 2) "__keyspace@0__:*" 3) "__keyspace@0__:mykey" 4) "set"
以上收到的订阅信息中事件是主体,其信息能够归纳为:“0号数据库发生了set事件,发生这个事件的key信息为mykey”。
要使用psubscribe命令进行键事件的订阅,就首先须要在Redis的主配置文件中对模式订阅进行设定。注意,若是您只是使用psubscribe命令经过Channel发送消息到订阅者,或者更单纯的使用publish命令和subscribe命令组合经过Channel发送和接收消息,就不须要进行这样的配置。
默认状况下Redis服务下的键空间通知和键事件通知都是关闭的。在redis.conf文件下,有专门的“EVENT NOTIFICATION”区域进行设定,设置的格式为:
notify-keyspace-events [通配符]
通配符的定义描述以下:
如下的几个实例说明了配置格式中通配符的用法:
// 监控任何数据格式的全部事件,包括键空间通知和键事件通知 notify-keyspace-events "AKE" // 只监控字符串结构的全部事件,包括键空间通知和键事件通知 notify-keyspace-events "g$KExe" // 只监控全部键事件通知 notify-keyspace-events "AE" // 只监控Hash数据解构的键空间通知 notify-keyspace-events "ghKxe" // 只监控Set数据结构的键事件通知 notify-keyspace-events "gsExe"
注意,在Redis主配置文件中进行事件通知的配置,其配置效果是全局化的。也就是说全部链接到Redis服务的客户端都会使用这样的Key事件通知逻辑。但若是单独须要为某一个客户端会话设置独立的Key事件通知逻辑,则能够在客户端成功链接Redis服务后,使用相似以下的命令进行设置:
...... 192.168.61.140:6379> config set notify-keyspace-events KEA OK
完成键事件的配置后,就可使用psubscribe命令在客户端订阅消息通知了。这个过程仍是须要使用通配符参数,才能完成订阅指定。通配符格式以下所示:
psubscribe __[keyspace|keyevent]@<db>__:[prefix] // 例如: // 订阅0号数据库中,全部的键变化事件,进行键空间通知 psubscribe __keyspace@0__:* // 订阅0号数据库,全部的键变化事件,进行键空间通知和键事件通知 psubscribe __key*@0__:*
注意,就如上文所提到的那样,客户端可以进行键信息变化事件订阅的前提是Redis服务端或者这个客户端会话自己开启了相应配置。如下举例说明psubscribe命令中参数的使用方式:
// 注意,Redis服务上的配置信息以下 // notify-keyspace-events "gsExe" // 便是说只容许监控Set结构的全部事件,而且之启用了键事件通知,没有启用键空间通知。 // 客户端使用如下命令开始订阅Key的变化事件 192.168.61.140:6379> psubscribe __key*@0__:* // 以上命令订阅了0号数据库全部键信息的变化通知,包括键事件通知和键空间通知 Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "__key*@0__:*" 3) (integer) 1 // 接着,已链接到Redis服务上的另外一个客户端执行了以下命令 // > sadd mysetkey rt // 那么收到的消息通知为 1) "pmessage" 2) "__key*@0__:*" 3) "__keyevent@0__:sadd" 4) "mysetkey"
以上实例操做中有两个问题须要单独进行说明:
当客户端使用psubscribe命令进行订阅时(psubscribe key*@0:*),其实是连同keyspace(键空间通知)和keyevent(键事件通知)一块儿订阅了。那么按照上文介绍的内容来讲,这个订阅者本该收到两条事件消息。一条消息的描述重点在key上,另外一条消息的描述重点在sadd事件上。但实际状况是,这个订阅者只收到了以描述重点在事件上的键事件通知。这是由于在以上实例中特别说明的一点:Redis服务端只开启键事件通知的配置。因此不管客户端如何订阅键空间通知,也收不到任何消息。
另外,包括Redis官方资料在内的资料都在阐述这样一个事实,既是经过sadd命令对一个Set结构中的元素进行变动和直接经过“PUBLISH keyevent@0:sadd mysetkey”这样的命令向订阅者发送消息,在消息订阅者看来效果都是同样。可是这两种不一样的操做过程对于Redis存储的Key数据,则是彻底不同的。前者的操做方式会改变Redis中存储的数据情况,但后者则不会。