Redis 学习笔记

一 、NoSql

后续。。。

二、redis

1. 是什么?

Redis:REmote DIctionary Server(远程字典服务器)

是完全开源免费的,用C语言编写的,遵守BSD协议,
是一个高性能的(key/value)分布式内存数据库,基于内存运行
并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,
也被人们称为数据结构服务器

1.三个优点

Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用

Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储

Redis支持数据的备份,即master-slave模式的数据备份

2.能干嘛?

内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务

取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面

模拟类似于HttpSession这种需要设定过期时间的功能

发布、订阅消息系统

定时器、计数器

3.官网

Http://redis.io/

Http://www.redis.cn/(中文)

下载地址:https://github.com/dmajkic/redis/downloads

emmmmm

正式需要在Linux 系统下

4. 端口 6379

为什么默认端口是6379?

三、五大数据类型

1、String(字符串)

String(字符串)

string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M

2、Hash 类似Map

Hash(哈希)
Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

类似Java里面的Map<String,Object>

3.List(列表)

List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。
它的底层实际是个链表

4.Set(集合 )

Set(集合)
Redis的Set是string类型的无序集合。它是通过HashTable实现实现的,

5. Zset (有序集合)

zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。
redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

三、持久化

1、RDB(Redis DataBase)

1. 是什么?

  • 在指定的时间间隔内将内存中的数据集快照写入磁盘,它恢复时是将快照文件直接读到内存里

  • Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到
    一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
    整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能
    如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方
    式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

2.Fork

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)
数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程

3.Rdb

保存的是dump.rdb文件

4.优势

适合大规模的数据恢复

对数据完整性和一致性要求不高

5. 劣势

在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改

Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

6,小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MTsc99IU-1576461695514)(C:\Users\雷云龙\AppData\Roaming\Typora\typora-user-images\1574758079492.png)]

2、AOF(Append Only File)

1.是什么?

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),
只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis
重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

Aof保存的是appendonly.aof文件

2.优势

每修改同步:appendfsync always 同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好

不同步:appendfsync no 从不同步

3.劣势

每秒同步:appendfsync everysec 异步操作,每秒记录 如果一秒内宕机,有数据丢失

Aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

4.小结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPI7lv9C-1576461695515)(C:\Users\雷云龙\AppData\Roaming\Typora\typora-user-images\1574758566784.png)]

3、总结

1、建议

  • RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储
  • AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些
    命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.
    Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大
  • 只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.

2、开启两种持久化方式

1 . 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的 数据集要比RDB文件保存的数据集要完整.

2 . RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?
作者建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),
快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。

3、性能建议

因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。

如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。

如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构

四、Redis 事务

1、是什么?

可以一次执行多个命令,本质是一组命令的集合。一个事务中的
所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞

2、作用

一个队列中,一次性、顺序性、排他性的执行一系列命令

3、怎么玩?

后续。。。

4、阶段

开启:以MULTI开始一个事务

入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

执行:由EXEC命令触发事务

5、特性

单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题

不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

五、Redis 的发布订阅

后续。。。

六、Redis的复制

后续。。。

七、Redis 的Java客户端 Jedis

1、前提

在 linux 系统中安装 eclipse 和 jdk

2、jar

Commons-pool-1.6.jar

Jedis-2.1.0.jar

3、常用操作

1.测试连通性

public class Demo01 {public static void main(String[] args) {//连接本地的 Redis 服务Jedis jedis = new Jedis("127.0.0.1",6379);//查看服务是否运行,打出pong表示OKSystem.out.println("connection is OK==========>: "+jedis.ping());}
}

2.5+1(一个key ,五大数据类型)


package com.atguigu.redis.test;import java.util.*;import redis.clients.jedis.Jedis;public class Test02
{public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1",6379);//keySet<String> keys = jedis.keys("*");for (Iterator iterator = keys.iterator(); iterator.hasNext();) {String key = (String) iterator.next();System.out.println(key);}System.out.println("jedis.exists====>"+jedis.exists("k2"));System.out.println(jedis.ttl("k1"));//String//jedis.append("k1","myreids");System.out.println(jedis.get("k1"));jedis.set("k4","k4_redis");System.out.println("----------------------------------------");jedis.mset("str1","v1","str2","v2","str3","v3");System.out.println(jedis.mget("str1","str2","str3"));//listSystem.out.println("----------------------------------------");//jedis.lpush("mylist","v1","v2","v3","v4","v5");List<String> list = jedis.lrange("mylist",0,-1);for (String element : list) {System.out.println(element);}//setjedis.sadd("orders","jd001");jedis.sadd("orders","jd002");jedis.sadd("orders","jd003");Set<String> set1 = jedis.smembers("orders");for (Iterator iterator = set1.iterator(); iterator.hasNext();) {String string = (String) iterator.next();System.out.println(string);}jedis.srem("orders","jd002");System.out.println(jedis.smembers("orders").size());//hashjedis.hset("hash1","userName","lisi");System.out.println(jedis.hget("hash1","userName"));Map<String,String> map = new HashMap<String,String>();map.put("telphone","13811814763");map.put("address","atguigu");map.put("email","abc@163.com");jedis.hmset("hash2",map);List<String> result = jedis.hmget("hash2", "telphone","email");for (String element : result) {System.out.println(element);}//zsetjedis.zadd("zset01",60d,"v1");jedis.zadd("zset01",70d,"v2");jedis.zadd("zset01",80d,"v3");jedis.zadd("zset01",90d,"v4");Set<String> s1 = jedis.zrange("zset01",0,-1);for (Iterator iterator = s1.iterator(); iterator.hasNext();) {String string = (String) iterator.next();System.out.println(string);}}
}

3.事务提交

日常

package com.atguigu.redis.test;import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;public class Test03
{public static void main(String[] args) {Jedis jedis = new Jedis("127.0.0.1",6379);//监控key,如果该动了事务就被放弃/*3jedis.watch("serialNum");jedis.set("serialNum","s#####################");jedis.unwatch();*/Transaction transaction = jedis.multi();//被当作一个命令进行执行Response<String> response = transaction.get("serialNum");transaction.set("serialNum","s002");response = transaction.get("serialNum");transaction.lpush("list3","a");transaction.lpush("list3","b");transaction.lpush("list3","c");transaction.exec();//2 transaction.discard();System.out.println("serialNum***********"+response.get());}
}

加锁

public class TestTransaction {public boolean transMethod() {Jedis jedis = new Jedis("127.0.0.1", 6379);int balance;// 可用余额int debt;// 欠额int amtToSubtract = 10;// 实刷额度jedis.watch("balance");//jedis.set("balance","5");//此句不该出现,讲课方便。模拟其他程序已经修改了该条目balance = Integer.parseInt(jedis.get("balance"));if (balance < amtToSubtract) {jedis.unwatch();System.out.println("modify");return false;} else {System.out.println("***********transaction");Transaction transaction = jedis.multi();transaction.decrBy("balance", amtToSubtract);transaction.incrBy("debt", amtToSubtract);transaction.exec();balance = Integer.parseInt(jedis.get("balance"));debt = Integer.parseInt(jedis.get("debt"));System.out.println("*******" + balance);System.out.println("*******" + debt);return true;}}/*** 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中* 重新再尝试一次。* 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,* 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。*/public static void main(String[] args) {TestTransaction test = new TestTransaction();boolean retValue = test.transMethod();System.out.println("main retValue-------: " + retValue);}
}

4.主从复制

6379,6380启动,先各自先独立

主写 从读

public class TestTransaction {public boolean transMethod() {Jedis jedis = new Jedis("127.0.0.1", 6379);int balance;// 可用余额int debt;// 欠额int amtToSubtract = 10;// 实刷额度jedis.watch("balance");//jedis.set("balance","5");//此句不该出现,讲课方便。模拟其他程序已经修改了该条目balance = Integer.parseInt(jedis.get("balance"));if (balance < amtToSubtract) {jedis.unwatch();System.out.println("modify");return false;} else {System.out.println("***********transaction");Transaction transaction = jedis.multi();transaction.decrBy("balance", amtToSubtract);transaction.incrBy("debt", amtToSubtract);transaction.exec();balance = Integer.parseInt(jedis.get("balance"));debt = Integer.parseInt(jedis.get("debt"));System.out.println("*******" + balance);System.out.println("*******" + debt);return true;}}/*** 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中* 重新再尝试一次。* 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,* 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。*/public static void main(String[] args) {TestTransaction test = new TestTransaction();boolean retValue = test.transMethod();System.out.println("main retValue-------: " + retValue);}
}

4、JedisPool

​ 获取Jedis实例需要从JedisPool中获取

  • 用完Jedis实例需要返还给JedisPool
  • 如果Jedis在使用过程中出错,则也需要还给JedisPool

JedisPoolUtil

package com.atguigu.redis.test;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class JedisPoolUtil {private static volatile JedisPool jedisPool = null;//被volatile修饰的变量不会被本地线程缓存,对该变量的读写都是直接操作共享内存。private JedisPoolUtil() {}public static JedisPool getJedisPoolInstance(){if(null == jedisPool){synchronized (JedisPoolUtil.class){if(null == jedisPool){JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxActive(1000);poolConfig.setMaxIdle(32);poolConfig.setMaxWait(100*1000);poolConfig.setTestOnBorrow(true);jedisPool = new JedisPool(poolConfig,"127.0.0.1");}}}return jedisPool;}public static void release(JedisPool jedisPool,Jedis jedis){if(null != jedis){jedisPool.returnResourceObject(jedis);}}
}

Demo5

package com.atguigu.redis.test;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;public class Test01 {public static void main(String[] args) {JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();Jedis jedis = null;try {jedis = jedisPool.getResource();jedis.set("k18","v183");} catch (Exception e) {e.printStackTrace();}finally{JedisPoolUtil.release(jedisPool, jedis);}}
}

总结

JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。

maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。
WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException;
WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用;
maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;
testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的;

testOnReturn:return 一个jedis实例给pool时,是否检查连接可用性(ping());

testWhileIdle:如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

timeBetweenEvictionRunsMillis:表示idle object evitor两次扫描之间要sleep的毫秒数;

numTestsPerEvictionRun:表示idle object evitor每次扫描的最多的对象数;

minEvictableIdleTimeMillis:表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;

lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;

==================================================================================================================
其中JedisPoolConfig对一些参数的默认设置如下:
testWhileIdle=true
minEvictableIdleTimeMills=60000
timeBetweenEvictionRunsMillis=30000
numTestsPerEvictionRun=-1

EvictionRunsMillis大于0时才有意义;

softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;

lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;

==================================================================================================================
其中JedisPoolConfig对一些参数的默认设置如下:
testWhileIdle=true
minEvictableIdleTimeMills=60000
timeBetweenEvictionRunsMillis=30000
numTestsPerEvictionRun=-1

Redis 学习笔记-雷云龙相关推荐

  1. Redis学习笔记 - 数据类型与API(1)Key

    Redis学习笔记 - 数据类型与API(1)Key Key相关命令 1. 常用命令 命令 含义 时间复杂度 keys 查找所有符合给定模式 pattern 的 key O(N), N 为数据库中 k ...

  2. Redis学习笔记~Redis在windows环境下的安装

    Redis是一个key-value的存储系统,它最大的特点就是可以将数据序列化到文件中. redis存储在服务器的内存或者文件中,它不是session,不是cookies,它只是个更安全,更稳定,更可 ...

  3. redis学习笔记-持久化

    redis学习笔记-持久化 前言 redis持久化有两种方式:RDB和AOF.分别对应着全量复制和增量复制.深刻理解各自的实现方式及适用场景对redis的使用和运维十分重要.下面就分别介绍. RDB持 ...

  4. StackExchange.Redis学习笔记(五) 发布和订阅

    StackExchange.Redis学习笔记(五) 发布和订阅 原文:StackExchange.Redis学习笔记(五) 发布和订阅 Redis命令中的Pub/Sub Redis在 2.0之后的版 ...

  5. Redis学习笔记~分布式的Pub/Sub模式

    redis的客户端有很多,这次用它的pub/sub发布与订阅我选择了StackExchange.Redis,发布与订阅大家应该很清楚了,首先一个订阅者,订阅一个服务,服务执行一些处理程序(可能是写个日 ...

  6. Redis学习笔记——SpringDataRedis的使用

    与Spring集成 我需要哪些jar包? <dependency><groupId>org.springframework.data</groupId><ar ...

  7. Redis学习笔记(五)——持久化及redis.conf配置文件叙述

    对于日常使用来说,学习完SpringBoot集成Redis就够我们工作中使用了,但是既然学习了,我们就学习一些Redis的配置及概念,使我们可以更深层次的理解Redis,以及增强我们的面试成功概率,接 ...

  8. Redis学习笔记1-理论篇

    目录 1,Redis 数据类型的底层结构 1.1,Redis 中的数据类型 1.2,全局哈希表 1.3,数据类型的底层结构 1.4,哈希冲突 1.5,rehash 操作 2,Redis 的 IO 模型 ...

  9. Redis学习笔记(实战篇)(自用)

    Redis学习笔记(实战篇)(自用) 本文根据黑马程序员的课程资料与百度搜索的资料共同整理所得,仅用于学习使用,如有侵权,请联系删除 文章目录 Redis学习笔记(实战篇)(自用) 1.基于Sessi ...

  10. Redis学习笔记(B站狂神说)(自己总结方便复习)

    Redis学习笔记B站狂神说 redis: 非关系型数据库 一.NoSQL概述 1.为什么要用Nosql 1.单机Mysql的年代 思考一下,这种情况下:整个网站的瓶颈是什么? 1.数据量如果太大,一 ...

最新文章

  1. 在CentOS 6.9 x86_64上从源码安装xz命令的方法
  2. freemodbus线圈中的位操作
  3. Jaxb对xml报文头的小修小改
  4. 30幅让人震撼的精美高速摄影作品欣赏
  5. 数组拼接时中间怎么加入空格_【题解二维数组】1123:图像相似度
  6. 修改wap游戏服务器,修改wap游戏服务器
  7. Winform中ComcoBox控件设置选定项
  8. win10安装win10X虚拟机教程
  9. 一则“亿万富翁给妻子捐5亿美元科研经费”的八卦,引发科研筹钱难的思考
  10. 电脑如何实现微信多开
  11. Vue清除定时器优化方案
  12. 在word的文字右上角添加符号(插入上标)?
  13. 新建SVN仓库并上传项目
  14. matlab结束外循环,求单源最短路径的BellmanFord算法的matlab实现及其优化
  15. 数据科学家分享:人工智能在图像识别技术上应用
  16. 视觉SLAM十四讲CH10代码解析及课后习题详解
  17. 正本清源!!!!!!:HWDB1.1数据集.gnt转换成.png
  18. 收录最好的网站是哪个?
  19. lg手机查找root,lg屏幕查询
  20. win7 删除java_windows7系统卸载java的操作方法?

热门文章

  1. 显示器测试软件 绿色,DisPlayX-显示器测试工具
  2. pmp知识点(8)-项目质量管理
  3. HTML5+CSS3的速查手册
  4. windows7 C盘清理(图解)
  5. 错误报告函数:strerror和perror
  6. Unity项目发布谷歌AAB+PAD
  7. dubbo之failed to connect to server /xx.xx.xx.xx:20880 client-side timeout问题解决
  8. 2021-07-18
  9. 百度Apollo计划跟踪:Apollo 3.0前言
  10. 计算机机房系统建设,计算机机房系统建设方案(范文).pdf