天气:阴晴
一、Redis主从复制
主机数据更新后根据配置和策略自动同步到备机的master、slave机制,Master以写为主,Slave以读为主
功能:1.读写分离,减轻压力,业务清晰
2.容灾恢复
原则:配从不配主,slaveof 主库IP 主库端口
步骤:
1.配置conf文件,以开启多个redis
①拷贝多个redis.conf文件
②开启daemonize yes
③pid文件名字
④指定端口
⑤log文件名字
⑥dump.rdb
2.实操
①一主二仆
一个主机,两个备机,从机开启会直接复制主机所有信息
从机主机执行同一个写命令的时候,从机不能写,只有主机能写
主机shutdown后,从机仍然是slave,会原地待命,主机重启后接着
从机shutdown后,正常工作的主从机无影响,重启的从机变回master(可以配置自动连回原先master主机)
【info replication:查看redis信息】
② 薪火相传
上一个Slave是下一个slave的Master
中途变更转向会重新拷贝最新的【Slaveof 新主库IP 新主库端口】数据,原数据清除
③反客为主
【SLAVEOF no one:将从机升了主机】
其中从机升级为主机后,其他从机仍待命,需要重新跟新主机
二、哨兵模式
哨兵模式会监控原主机,主机宕机后哨兵会在从机中选举出主机,自动升级为主机,并且其他从机会重新跟随这个新主机,类似一种无人值守的反客为主模式。
原主机重新回来后,会变成从机Slave,跟随新主机
1.自定义的配置目录下新建sentinel.conf文件,名字固定
2.配置哨兵,填写内容
3…启动哨兵 【Redis-sentinel 哨兵配置文件路径】
一组sentinel可以监控多组master
**最后拓展:
**复制的缺点,所有写操作都是先在master,然后同步更新到slave上面,这个过程会有一定的延迟,当业务量大繁忙的时候,这个延迟问题会更加明显,slave机器数据越多,延迟问题也会越严重
三、代码联通Redis服务
public static void main(String[] args){
//第一个参数为主机地址,第二个为端口号
Jedis jedis = new Jedis("xxx,xxx,xxx,xxx",xxxx);
System.out.println(jedis.ping());
Jedis常用的API:
//set k1 v1
jedis.set(k1,v1);
//get k1
jedis.get(k1);
//keys*
Set<String> keys = jedis.keys("*");
//hset
jedis.hset("hash1","userName","lisi");
Map<String,String> map = new HashMap<String,String>();
map.put("one","1232312");
map.put("two","adadwe");
jedis.hmset("hash2",map);
四、代码执行Redis事务
//开启事务
Rransaction transaction = jedis.multi();
//加入队列
transaction.set("k1","v1");
transaction.set("k2","v2");
transaction.set("k3","v3");
//执行
transaction.exec();
//放弃
transaction.discard();
可以通过Boolean方法内置事务,watch监控数据,如果失败返回fail,根据返回结果进行业务处理
五、代码实现主从复制
//第一个参数为主机地址,第二个为端口号
Jedis jedis_M = new Jedis("xxx,xxx,xxx,xxx",xxxx);
Jedis jedis_S = new Jedis("xxx,xxx,xxx,xxx",xxxx);
//开启主从复制,参数为主机M的参数
jedis_S.slaveof("xxx,xxx,xxx,xxx",xxxx);
//主机开始操作
jedis_M.set("k1","v1");
注意代码编写情况下,从库直接get可能会执行得比复制过程快,那会get失败
六、JedisPool
//编写一个池的单例工厂
public class JedisPllUtil{
private static volatile JedisPool hedisPool = null;
private JedisPoolUtil(){}
public static JedisPool getJedisPoolInstance(){
//第一步判断是否初始化无需加锁
if(null == jedisPool){
synchronized (JedisPoolUtil.class){
//第二次判断加了锁,第一个进来的进行初始化,后面的等待之后再判断一次
if(null == jedisPool){
JedisPoolConfg poolCongig = new JedisPoolConfg();
poolCongig.setMaxActive(1000);
poolCongig.setMaxIdle(32);
poolCongig.setMaxWait(100*1000);
poolCongig.settestOnBorrow(true);
jedisPool = new JedisPool(poolConfig,zhuji,port);
}
}
}
return jedisPool;
}
//做一个release()功能,参数为哪个池的那个jedis
public static void release(JedisPool jedisPool,Jedis jedis){
if(null != jedis){
jedisPool.returnResourceObject(jedis);
}
}
}