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