Redis(一)

一. 什么是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可以属于分布式缓存,可以解决这些问题
原文地址:https://www.cnblogs.com/bin563597293/p/14367426.html