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前台启动和后台启动存值