Redis

1.概念

本质:内存开销(以空间换时间)共享资源
优点:大大提高数据查询效率 减少频繁的持久化或(IO)操作
缺点:数据不同步(数据及时更新 过期时间) 注意数据并发处理 

2.历史

Membercache				vs 			Redis
存储数据类型单一					存储数据多样化
算法效率一般(数据量大)				算法效率较高(数据量大)	
不能实现持久化(数据丢失)			可以实现持久化(RBD AOF)
不能实现集群						可以实现集群(HA 高可用:防止单点故障)

补充:nosql数据库 -> 不仅仅只有SQL的数据库 

3.安装

cd ~/tools/
//解压
tar -xzvf redis-3.0.5.tar.gz -C ~/envs/

cd ~/envs/redis-3.0.5/
//编译
make
//安装 指定安装目录 PREFIX=/root/envs/redis 
make PREFIX=/root/envs/redis install

//Redis目录说明
└── bin
		├── redis-benchmark				
		├── redis-check-aof					aof(默认开启) 持久化方案之一 (rdb 默认开启)
		├── redis-check-dump
		├── redis-cli						cli 客户端服务					
		├── redis-sentinel  					sentinel 哨兵 心跳监控 Master-Salve HA
		└── redis-server						server 服务

4.配置

//配置文件夹
mkdir conf
//拷贝所需配置文件
cp ~/envs/redis-3.0.5/redis.conf ~/envs/redis/conf/

//解析(******)

//是否已后台服务运行 ->默认:no (前台服务)
42 daemonize no

//端口
/*
	Tomcat 	8080
	Oracle 	1521
	Mysql	3306
	Nginx	80
	Redis	6379
*/
50 port 6379

//RBD持久化策略 -> 正常终止服务会执行RBD持久化
//服务器运行过程中 -> 安全措施
147 save 900 1		-> 至少1个新数据发生缓存 则900秒(15分钟)持久化一次
	148 save 300 10		-> 至少10个新数据发生缓存 则300秒(5分钟)持久化一次
	149 save 60 10000	-> 至少10000个新数据发生缓存 则60秒(1分钟)持久化一次

//RBD持久化文件 -> 默认文件名 dump.rdb
182 dbfilename dump.rdb


//AOF持久化策略 -> 默认不开启 (消耗性能)
509 appendonly no
//AOF持久化文件 -> 默认文件名 appendonly.aof
513 appendfilename "appendonly.aof"


//AOF持久化策略方案
//系统根据自身的运行环境来决定持久化频率
521 # no: don't fsync, just let the OS flush the data when it wants. Faster.
//一但发生数据改变就持久化 精密度最高 消耗最大
522 # always: fsync after every write to the append only log. Slow, Safest.
//每秒持久化一次 数据遗失率周期1秒
523 # everysec: fsync only one time every second. Compromise.

538 # appendfsync always
539 appendfsync everysec
540 # appendfsync no

//Master-Salve Replication

5.运行

cd ~/envs/redis

//服务
bin/redis-server conf/redis.conf

//正常终止服务 Ctrl+C 
//RBD持计划策略 默认文件名 dump.rdb
Received SIGINT scheduling shutdown...
20626:M 12 May 10:44:06.122 # User requested shutdown...
20626:M 12 May 10:44:06.122 * Saving the final RDB snapshot before exiting.
20626:M 12 May 10:44:06.126 * DB saved on disk
20626:M 12 May 10:44:06.126 # Redis is now ready to exit, bye bye...


//客户端
bin/redis-cli  -> 默认本地访问 127.0.0.1 : 6379
bin/redis-cli -h 192.168.158.11 -p 6379

/***常用API - http://redisdoc.com/ ***/ 
/*key -> value*/

keys	-> 搜索匹配key
set		-> 添加或覆盖
get		-> 获取
del		-> 删除
exists	-> 查询key是否存在
setnx	-> 如果key不存在则set 否则不添加 (******)
expire	-> 设置过期时间 (防止死锁)

incr	-> 自增1
incrby	-> 自增N
decr	-> 自减1
decrby	-> 自减N

flushdb	-> 清除所有数据库 格式化

6.Java连接Redis -> Jedis

//1.非切片非连接池  Jedis
Jedis jedis = new Jedis(host, port);
jedis.close();

//2.非切片连接池  JedisPool
JedisPoolConfig poolConfig = new JedisPoolConfig();
/*poolConfig.setMinIdle(0);
poolConfig.setMaxIdle(8);
poolConfig.setMaxIdle(8);*/
//连接池
JedisPool jedisPool = new JedisPool(poolConfig, host, port);
//连接对象
Jedis jedis = jedisPool.getResource();
jedis.close(); //资源回收

//3.切片非连接池 ->负载均衡(数据 并没有实现数据共享)
//4.切片连接池

7.Jedis-API

数据类型
1)字符串 String 

2)列表 List

3)集合 Set

4)散列 Hash

8.依赖项

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

9.分布式锁

特点:
1)独占性 -> 会话操作时其他会话不能干扰该资源
2)乐观性 -> 锁在一定时间内解除
3)原子性 -> 并发状态处理
4)私有性 -> 加锁和解锁必须是同一个会话

Redis数据操作意识形态 
	-> 数据更新一定加锁 
	-> 批量更新必须事务

jedis.set(key, value, nxxx, expx, time) 
	key -> 锁标示 唯一(全局一把锁 | 根据实际情况可以按模块划分 资源一定不能交叉)
	value -> 解锁唯一标示 解铃还须系铃人
	nxxx -> NX 如果锁存在返回值null  锁不存在加锁OK
	expx -> PX(毫秒)EX(秒) 过期时间 防止死锁 加锁业务挂起 过期后锁自动解除
	time -> 加锁时间根据实际情况控制 过长影响效率 过短不能保证业务顺利执行

分布式锁的直接使用:

public class MyTest {

	String host = "192.168.11.12";
	int port = 6379;
	int port1 = 6371;
	int port2 = 6372;
	

	@Test
	public void test2() {
		String key = "LOCK";
		String value = "1234"; //随机码
		String nxxx = "NX"; // 如果 key 存在不加锁 | 不存在加锁
		String expx = "EX"; // 设置过期时间 单位秒 (防止死锁)
		String result = "OK";
		int time = 3;
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		JedisPool jedisPool = new JedisPool(poolConfig, host, port);
		Jedis jedis = jedisPool.getResource();
		
		//API 判断 加锁 过期
		if(result.equals(jedis.set(key, value, nxxx, expx, time))){
			jedis.set("k1","Java");
			if(jedis.get(key).equals(value)){
				//自己解锁
				jedis.decr(key);
			}			
		}

		System.out.println(jedis.set(key, value, nxxx, expx, time));
		System.out.println(jedis.set(key, value, nxxx, expx, time));
	}
}

分布式锁封装成工具类:

public class DistributedUtils {
    private static JedisPool jedisPool=null;
    static {
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        jedisPool=new JedisPool(poolConfig, SalaConsts.HOST,SalaConsts.PORT);
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }

    public static boolean lock(Jedis jedis,String value,int time){
        return SalaConsts.RESULT.equals(jedis.set(SalaConsts.KEY,
                value,SalaConsts.NX,SalaConsts.PX,time));
    }

    public static void unlock(Jedis jedis,String value){
        if(value.equals(jedis.get(SalaConsts.KEY))){
            jedis.del(SalaConsts.KEY);
        }
    }
}

linux中的Redis前台启动和后台启动存值
Redis
Redis

上一篇:Redis基础学习 跟 Jedis 的手动实现


下一篇:阿里云Redis开发规范