redis是什么:
redis是开源,BSD许可,高级的key-value存储系统.
可以用来存储字符串,哈希结构,链表,集合,因此,常用来提供数据结构服务
redis和memcached相比,的独特之处:
1: redis可以用来做存储(storge),而memccached是用来做缓存(cache)
这个特点主要因为其有”持久化”的功能.
2: 存储的数据有”结构”,对于memcached来说,存储的数据,只有1种类型--”字符串”,
而redis则可以存储字符串,链表,哈希结构,集合,有序集合
reids的安装我在前面的文章里有说过。
上面我们就完成了reids的安装。下面我们就来开始启动下redis服务。
在解压的redis文件中src下。执行: ./redis-server ../redis-conf 。启动redis服务:
1 、设置成后台执行后,如何关闭?关闭redis服务:pkill -9 redis杀死所有与redis有关的进程
关闭客户端:quit 命令就可以
2、第一次外部网络连接的时候,可能会出现链接失败,原因是防火墙原因,端口没有开放
Centos7中.我使用的是iptables-service
修改配置:./etc/sysconfig/iptables文件,
vi iptabls 添加:-A INPUT -p tcp -m state --state NEW -m tcp --dport 6379 -j ACCEPT
然后 :wq 保存退出
3、redis客户端链接redis服务
用redis-cli bin/redis-cli [-h localhost -p 6379 ]
4、redis默认有16个库,切换使用命令select n。可以通过修改配置文件来修库的个数
Redis可以保存的数据结构大致可以分为5中
1、字符串 、//算是数据结构
2、链表结构 -->link表-->操作命令l或者r开头如lpush key value
3、无序集合-->set集合---操作命令s开头如sadd key value
4、有序集合--->list集合---操作命令z开头如zadd key sorce value
5、hash结构 --> ---->操作命令h开头 如hset key field value
----------------------------------------------------------------------------------------------------------------------
-------------------------------------------Redis中的事务------------------------------------------------------------
支持简单的事务:
如图:
同时也可以取消事务:discard
但是这里的取消并不能和mysql中的rollback回滚一样
如果已经成功执行了2条语句,第3条语句出错.
Rollback后,前2条的语句影响消失.
Discard只是结束本次事务,前2条语句造成的影响仍然还在
multi命令之后,后面的命令都会返回一个QUEUED,但是如果中间出现错误如
1、语法错误
2、语法没有错,但是适用对象有错,也就是执行的时候会出错,
这一点只能有程序员自己保证了。
Redis中的事务启用的是乐观锁,就是:只负责监测key是不是被改动。如果被改动,那么事务提交就会出错,被取消。如果没有那么事务就会提交成功执行命令。
启用命令是:watch key key1 key2 .....
记得最后要unwatch .关闭下watch
watch key1 key2 ... keyN
作用:监听key1 key2..keyN有没有变化,如果有变,则事务取消
unwatch
作用:取消所有watch监听
------------------------------------------Redis的持久化配置----------------------------------------------------持久化: 即把数据存储于断电后不会丢失的设备中,通常是硬盘
reids有两种持久化方式:1、快照---rdb文件 2、日志---aof文件
1、rdb
每隔N分钟或N次写操作后, 从内存dump数据形成rdb文件,压缩放在备份目录
Rdb快照的配置选项
save 900 1 // 900内,有1条写入,则产生快照
save 300 1000 // 如果300秒内有1000次写入,则产生快照
save 60 10000 // 如果60秒内有10000次写入,则产生快照
(这3个选项都屏蔽,则rdb禁用)
stop-writes-on-bgsave-error yes // 后台备份进程出错时,主进程停不停止写入?
rdbcompression yes // 导出的rdb文件是否压缩
Rdbchecksum yes // 导入rbd恢复时数据时,要不要检验rdb的完整性
dbfilename dump.rdb //导出来的rdb文件名
dir ./ //rdb的放置路径
rdb的缺点是:如果在两个保存点 60s和300s之间断电,那么这时我们就会丢失几分钟的数据
为了解决这个问题,redis提供了更加精细化的处理 append only file aof方式
2、AOF
Aof 的配置
appendonly no # 是否打开 aof日志功能
appendfsync always # 每1个命令,都立即同步到aof.安全,速度慢
appendfsync everysec # 折衷方案,每秒写1次
appendfsync no # 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof.同步频率低,速度快,
no-appendfsync-on-rewrite yes: # 正在导出rdb快照的过程中,要不要停止同步aof
auto-aof-rewrite-percentage 100 #aof文件大小比起上次重写时的大小,增长率100%时,重写
auto-aof-rewrite-min-size 64mb #aof文件,至少超过64M时,重写
注: 在dump rdb过程中,aof如果停止同步,会不会丢失?
答: 不会,所有的操作缓存在内存的队列里, dump完成后,统一操作.
注: aof重写是指什么?
答: aof重写是指把内存中的数据,逆化成命令,写入到.aof日志里.以解决 aof日志过大的问题.
(逆化成命令:就是将redis中最终的key值,直接set,去掉了中间的各种操作如增1,修改啊,直接set成最终值)
问: 如果rdb文件,和aof文件都存在,优先用谁来恢复数据?
答: aof
问: 2种是否可以同时用?
答: 可以,而且推荐这么做
问: 恢复时rdb和aof哪个恢复的快
答: rdb快,因为其是数据的内存映射,直接载入到内存,而aof是命令,需要逐条执行
-------------------------------手动执行生成rdb、aof命令----------------------------
BGREWRITEAOF 后台进程重写AOF (bgrewriteaof)
BGSAVE 后台保存rdb快照 (bgsave)
SAVE 保存rdb快照 (save)--会阻塞主线程
LASTSAVE 上次保存时间 (lastsave)
如果redis服务宕机之后,重启时,就会从配置文件中的路径中读取所配置的rdb文件和aof文件
恢复数据。以aof为准
不同redis服务之间迁移数据,我们可以将rdb文件或者aof复制迁移过去,放到指定路径下改为指定名称
重启即可。
--------------------------------------Redis运维命令----------------------------------------------------
Flushall 清空所有库所有键
Flushdb 清空当前库所有键
Shutdown [save/nosave] //默认shutdown是save。直接dump的
注: 如果不小心运行了flushall, 立即 shutdown nosave ,关闭服务器
然后 手工编辑aof文件, 去掉文件中的 “flushall ”相关行, 然后开启服务器,就可以导入回原来数据.
如果,flushall之后,系统恰好bgrewriteaof了,那么aof就清空了,数据丢失.
Slowlog 显示慢查询
注:多慢才叫慢?
答: 由slowlog-log-slower-than 10000 ,来指定,(单位是微秒)
服务器储存多少条慢查询的记录?
答: 由 slowlog-max-len 128 ,来做限制
--------------------------------------redis集群-----------------------------------------------
集群的作用:
1、主从备份,防止主服务器宕机
2、读写分离,分担master的任务
3、任务分离,从服务器可以分担备份和一些计算工作
集群方式一般有两种:
1、星型
2、线型
主要的通信过程:
从服务自动连接master,master将dump rdb和aof给slave。从而保持数据一致同步
我们需要 1个master 2个slave,这2个slave都指向master
配置:
第一步:cp redis.conf redis6380.conf 、 cp redis.conf reids6381.conf 复制配置文件
第二步:修改redis6380.conf redis6381.conf的端口以及配置
同时需要修改aof文件的文件名,为了避免名称重复给覆盖了。
这时候配置下master的配置
注意:master中的slaveof 一定要注释掉。否则启动后info replication看到的角色就是slave。
分别启动后:
6380:
6381:
一般的配置我们遵循下面规则:
Master配置:
1:关闭rdb快照(备份工作交给slave)
2:可以开启aof
slave配置:
1: 声明slave-of
2: 配置密码[如果master有密码]
3: [某1个]slave打开 rdb快照功能
4: 配置是否只读[slave-read-only]
到此为止我们就构建了一个星型的集群。。。
当我们关闭掉6379端口的master服务shutdown.也可以通知执行命令来实现故障转移,如将6380设置为master,6381为其的slave
步骤:1、在6380的客户端: slaveof no one [不让它作为任何一个服务的slave]
2、在6381的客户端:slave of ip 6380 [让它作为6380的slave]
3、根据需要我们可以动态修改配置。先通过config get * 来获取所有的配置信息。
config set keyname value 来设置keyname属性的值
------------------------------缺点-----------------------------------------
缺陷:
每次salave断开后,(无论是主动断开,还是网络故障)。再连接master。都要master全部dump出来rdb,再aof,即同步的过程都要重新执行1遍.所以要记住---多台slave不要一下都启动起来,否则master可能IO剧增
-----------------------通过redis自带的哨兵模式来实现故障转移---------------------------------
1、编辑配置文件 sentinel.conf
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、我曾参考网上的,做了一个配置:看到他们那个有这个配置信息:sentinel can-failover mymaster yes.
注意这个配置已经没有了。新的redis版本中是没有的。还有就是注意上图的quorum这个数字,需要根据实际的哨兵个数来判断,要<=实际的哨兵个数
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
sentinel的配置其他属性可以翻译下配置文件上方的解释,应该可以理解
我们启动完所有的服务后,启动我们的哨兵
./src/redis-server ./sentinel.conf --sentinel //这样执行sentinel模式的服务,也就是哨兵监控
结果如图:
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
、、、、、、、、、、、、、、Jedis获取故障转移后的服务地址信息、、、、、、、、、、、、、、、、、、、、、
package com.zpl.redis.db;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
/**
* 这里配置哨兵模式,从而获取当前的master
* @author
*
*/
public class SentinelTest {
public static void main(String[] args) {
final JedisPoolConfig poolConfig = new JedisPoolConfig();
String masterName = "mymaster";
Set<String> sentinels = new HashSet<String>();
sentinels.add("192.168.179.128:26379");
// sentinels.add("192.168.1.96:26379");
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, poolConfig);
HostAndPort currentHostMaster = jedisSentinelPool.getCurrentHostMaster();
System.out.println(currentHostMaster.getHost() + "--" + currentHostMaster.getPort());// 获取主节点的信息
Jedis resource = jedisSentinelPool.getResource();//获取到转移后的master服务
String value = resource.get("a");
resource.lpush("link", "dfsf");
System.out.println(value);// 获得键a对应的value值
// resource.close();
}
}
上面代码注意要用commons-pool2的jar包。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
暂时没有找到java如何实现读写分离操作。、、、、、、、、、、、、、、、、、、遇见再补充吧