zoukankan      html  css  js  c++  java
  • 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可以属于分布式缓存,可以解决这些问题
  • 相关阅读:
    《JAVA高级程序设计》第四周作业
    《JAVA高级程序设计》第三周作业
    《Java高级程序设计》第二周作业
    《Java高级程序设计》第一周作业
    javar日志
    JAVA日志
    JAVA日志
    java日志
    JAVA日志
    JAVA日志
  • 原文地址:https://www.cnblogs.com/bin563597293/p/14367426.html
Copyright © 2011-2022 走看看