一. 什么是Redis??
- 基于内存存储系统的一款NoSQL数据库
二. 什么是NoSQL数据库??
- 基于内存的数据存储方式,数据之间不需要维护关系 --- 非关系型数据库
三. 有什么好处和缺点以及特点??
- 好处:
- 内存存储 -- 读写高效
- 支持数据持久化:AOF & RDB
- 支持事务
- 支持主从复制
- 支持设置过期时间
- 缺点:
- 内存太小,不能储存过多数据缓存
- 修改配置,重启加载时间久
- 完整性重同步,效率差
- 特点:
- 数据以key-value形式读写
- 单线程内存存储系统
四. 有什么基础功能??
- 缓存 -- 长久保存, 但是又不经常变化的数据(读取快)
- 即时信息 -- 临时性的, 经常变化的数据(读写快)
五. 虚拟机对Redis数据操作??
- 存储方式 --- key-value形式
- value的数据结构 --- 5种结构
- String -- Map<String,String>
- Hash -- Map<String,Map<String,String>>
- List -- Map<String,List<String>> -- 有序, 可重复
- Set -- Map<String,Set<String>> -- 无序, 不可重复
- Zset(sorted set) -- Map<String,TreeSet<String>> -- 不可重复,基于score实现排序
- String(set/get/setnx/setex)
1 // key存在, 则覆盖原值 2 set key value 3 4 // 获取值 5 get key 6 7 // 删除值 8 del key 9 10 // 判断性添加数据; key存在,则添加失败 11 setnx key value 12 13 // 添加/修改多个数据 14 mset key1 value1 key2 value2 ... 15 16 // 获取多个数据 17 mget key1 key2 ... 18 19 // 获取数据字符个数(字符串长度) 20 strlen key 21 22 // 设置数据具有指定的生命周期 23 setex key seconds value
24
25 // ++ (原值不存在,从0开始累加)
26 incr key
key的设置约定:
数据库中的热点数据key命名惯例
表名:主键名:主键值:字段名(非必须)
- hash(hset/hget)
1 // 添加/修改数据 2 hset key field value 3 4 // 获取数据 5 hget key field 6 7 // 删除数据 8 hdel key field1 [field2] ... 9 10 // 添加/修改多个数据 11 hmset key field1 value1 field2 value2 … 12 13 // 获取多个数据 14 hmget key field1 field2 …
案例:
双11活动日,销售手机充值卡的商家对移动、联通、电信的30元、50元、100元商品推出抢购活动,每种商品抢购上限1000张
hmset id:001 c30 1000 c50 1000 c100 1000
hmset id:002 c30 1000 c50 1000 c100 1000
hincrby id:001 c30 -5
hincrby id:001 c50 -15
- list(lpush/rpush/lpop/rpop/lrange/lindex)
1 // 添加/修改数据 2 lpush key value1 [value2] …… 3 rpush key value1 [value2] …… 4 5 // 获取范围之间的数据 6 lrange key start stop 7 8 // 获取指定索引的数据 9 lindex key index 10 11 // 获取并移除数据 12 lpop key 13 rpop key 14 15 // 规定时间内获取并移除数据 16 blpop key1 [key2] timeout 17 brpop key1 [key2] timeout
- set(sadd/smembers/sismember)
1 // 添加数据 2 sadd key member1 [member2] 3 4 // 删除数据 5 srem key member1 [member2] 6 7 // 获取集合数据总量 8 scard key 9 10 // 判断集合中是否包含指定数据 11 sismember key member
- zset(zadd/zrange)
1 zadd key score member 2 zrange key start stop [withscores]
- key操作(del/expire/ttl/persist)
1 // 删除键值 2 del key 3 4 // 设置键的有效时长 5 expires key seconds 6 7 // 查看键的有效时长 8 ttl key 9 10 // 判断key是否存在 11 exists key 12 13 // 将key变为永久有效 14 persist key
-
数据库操作
1 // 选择数据库 (index的值为0-15) 2 select index 3 4 // 查看当前数据库中键的个数 5 dbsize
六. java对Redis数据操作??
- 第一步: 配置文件(redis.properties)
1 redis.maxTotal=502 redis.maxIdel=103 redis.host=localhost 4 redis.port=6379
- 第二步: 工具类
1 public class JedisUtils { 2 3 private static JedisPool jp; 4 5 static { 6 ResourceBundle bundle = ResourceBundle.getBundle("redis"); 7 int maxTotal = Integer.parseInt(bundle.getString("redis.maxTotal")); 8 int maxIdel = Integer.parseInt(bundle.getString("redis.maxIdel")); 9 String host = bundle.getString("redis.host"); 10 int port = Integer.parseInt(bundle.getString("redis.port")); 11 12 //Jedis连接池配置 13 JedisPoolConfig jpc = new JedisPoolConfig(); 14 jpc.setMaxTotal(maxTotal); 15 jpc.setMaxIdle(maxIdel); 16 jp = new JedisPool(jpc,host,port); 17 } 18 19 public static Jedis getJedis(){ 20 return jp.getResource(); 21 } 22 23 }
- 第三步: 使用Jedis进行操作
1 public static void main(String[] args) { 2 //1.获取连接对象 3 Jedis jedis = JedisUtils.getJedis(); 4 //2.执行操作 5 // jedis.set("age","39"); 6 // String hello = jedis.get("hello"); 7 // System.out.println(hello); 8 // jedis.lpush("list1","a","b","c","d"); 9 // List<String> list1 = jedis.lrange("list1", 0, -1); 10 // for (String s:list1 ) { 11 // System.out.println(s); 12 // } 13 jedis.sadd("set1","abc","abc","def","poi","cba"); 14 Long len = jedis.scard("set1"); 15 System.out.println(len); 16 //3.关闭连接 17 jedis.close(); 18 }
七. Redis如何持久化??
1. 持久化方式有哪些??
- RDB 持久化: 以快照的方式保存某个时间点的真实数据
- AOF 持久化: 以日志的方式保存整个操作过程中的所有操作命令
2. RDB & AOF 持久化的优缺点??
RDB:
- 优点:
- 存储效率高,适合灾难性恢复,且恢复速度比AOF要快
- 缺点:
- 发生故障停机,会丢失数据
- 持久化操作,如果数据庞大,会降低性能
AOF:
- 优点:
- 解决RDB丢失部分数据的缺点,完整性更强
- AOF过大时,能够自动进行重写
- 缺点:
- 速度慢于RDB
- 因为个别命令(阻塞命令)原因,会出现无法将数据集恢复成保存时的原样
3. 持久化建议??
- 同时应用 AOF & RDB
- 原因: 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
4. 持久化操作??
- RDB持久化
- 通过配置持久化(推荐) --- 自动完成rdb持久化,底层是bgsave操作
1 # 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 2 # 这里表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改 3 # 如果想禁用RDB持久化的策略,只要不设置任何save指令,或者给save传入一个空字符串参数也可以 4 save 900 1 5 save 300 10 6 save 60 1 7 8 #rdb文件的名字。 9 dbfilename dump.rdb 10 11 # 对于存储到磁盘中的快照(rdb),可以设置是否进行压缩存储。如果是的话,redis会采用 12 # LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能 13 rdbcompression yes 14 15 # 在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约 16 # 10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能 17 rdbchecksum yes 18 19 # dbfilename文件存放目录。必须是一个目录,aof文件也会保存到该目录下。 20 dir ./
- AOF持久化
1 # 是否启用aof持久化方式 。否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。 2 # 因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no 3 appendonly no 4 5 # 指定更新日志(aof)文件名,默认为appendonly.aof 6 appendfilename "appendonly.aof" 7 8 #指定更新日志条件,共有3个可选值: 9 # no:表示等操作系统进行数据缓存同步到磁盘(快,持久化没保证) 10 # always:同步持久化,每次发生数据变更时,立即记录到磁盘(慢,安全) 11 # everysec:表示每秒同步一次(默认值,很快,但可能会丢失一秒以内的数据) 12 # appendfsync always 13 appendfsync everysec 14 # appendfsync no 15 16 # 指定是否在后台aof文件rewrite期间调用fsync,默认为no,表示要调用fsync(无论后台是否有子进程在刷盘)。 17 # Redis在后台写RDB文件或重写AOF文件期间会存在大量磁盘IO,此时,在某些linux系统中,调用fsync可能会阻塞。 18 #如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。 19 no-appendfsync-on-rewrite no 20 21 #当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写 。当AOF文件大小的增长率大于该配置项时自动开启重写。 22 auto-aof-rewrite-percentage 100 23 24 #当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写 。当AOF文件大小大于该配置项时自动开启重写 25 auto-aof-rewrite-min-size 64mb
八. 延伸题
1. 为什么 redis 需要把所有数据放到内存中??
- 因为这样可以最快速的对数据进行读写,
- 然后通过异步的方式来将数据写入磁盘.
- 由此体现出redis的高性能
2. Redis 常见的性能问题都有哪些?如何解决??
- 问题一: Master写RDB快照,会阻塞主线程工作,甚至导致间断性暂停服务;Master AOF持久化,文件过大影响Master恢复速度;
- 解决: Master最好不做任何持久化工作,特别不建议RDB持久化;如果数据比较关键,就让某一个Slave开启AOF持久化,策略为每秒同步一次
-
问题二: Master调用BGREWRITEAOF重写AOF文件,占用大量CPU和内存资源,导致load过高,出现短暂服务暂停现象
-
- 解决: 将no-appendfsync-on-rewrite的配置设为yes可以缓解这个问题,设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入。最好是不开启Master的AOF备份功能
-
问题三:主从复制的性能问题
- 解决: 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内
3. 为什么要用 Redis 而不用 map 做缓存??
- map属于本地缓存,生命周期短,随着 jvm 的销毁而结束,并且多个实例,达不到数据一致性;
- 而Redis可以属于分布式缓存,可以解决这些问题