Redis学习秘籍(三)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 数据库:放数据 增删改查 特点:非关系型数据库 NoSql(没有sql) 内存型数据库 key,value

9.3 AOF文件的重写

1. AOF带来的问题


AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。


2. AOF重写


用来在一定程度上减小AOF文件的体积


3. 触发重写方式


# 1.客户端方式触发重写
- 执行BGREWRITEAOF命令  不会阻塞redis的服务
# 2.服务器配置方式自动触发
- 配置redis.conf中的auto-aof-rewrite-percentage选项 参加下图↓↓↓
- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大


38.png


4. 重写原理

注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,替换原有的文件这点和快照有点类似。


# 重写流程
- 1. redis调用fork ,现在有父子两个进程 子进程根据内存中的数据库状态快照,往临时文件中写入重建数据库状态的命令
- 2. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
- 3. 当子进程把快照内容写入新文件已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
- 4. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
1.创建父子进程
2.子进程将当前的数据状态拍一个快照
3.将快照转化为写命令
4.父进程急需处理客户端写操作
5.继续将写命令向老的Aof文件中追加  同时再缓存一份 新的谢命令
6.子进程将快照写入临时文件之后通知父进程,父进程将缓存的新命令加入临时文件中
7.使用新的Aof文件替换老的Aof文件


39.png


9.4 持久化总结

两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。


无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。


10. java操作Redis

10.1 环境准备

1. 引入依赖


<!--引入jedis连接依赖-->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>


2.创建jedis对象

 public static void main(String[] args) {
   //1.创建jedis对象
   Jedis jedis = new Jedis("192.168.112.102", 6379);//1.redis服务必须关闭防火墙  2.redis服务必须开启远程连接
   jedis.select(0);//选择操作的库默认0号库
   //2.执行相关操作
   //....
   //3.释放资源
   jedis.close();
 }


10.2 操作key相关API


private Jedis jedis;
    @Before
    public void before(){
        this.jedis = new Jedis("192.168.202.205", 7000);
    }
    @After
    public void after(){
        jedis.close();
    }
    //测试key相关
    @Test
    public void testKeys(){
        //删除一个key
        jedis.del("name");
        //删除多个key
        jedis.del("name","age");
        //判断一个key是否存在exits
        Boolean name = jedis.exists("name");
        System.out.println(name);
        //设置一个key超时时间 expire pexpire
        Long age = jedis.expire("age", 100);
        System.out.println(age);
        //获取一个key超时时间 ttl
        Long age1 = jedis.ttl("newage");
        System.out.println(age1);
        //随机获取一个key
        String s = jedis.randomKey();
        //修改key名称
        jedis.rename("age","newage");
        //查看可以对应值的类型
        String name1 = jedis.type("name");
        System.out.println(name1);
        String maps = jedis.type("maps");
        System.out.println(maps);
    }


10.3操作String相关API


//测试String相关
    @Test
    public void testString(){
        //set
        jedis.set("name","小陈");
        //get
        String s = jedis.get("name");
        System.out.println(s);
        //mset
        jedis.mset("content","好人","address","海淀区");
        //mget
        List<String> mget = jedis.mget("name", "content", "address");
        mget.forEach(v-> System.out.println("v = " + v));
        //getset
        String set = jedis.getSet("name", "小明");
        System.out.println(set);
        //............
    }


10.4操作List相关API


//测试List相关
    @Test
    public void testList(){
        //lpush
        jedis.lpush("names1","张三","王五","赵柳","win7");
        //rpush
        jedis.rpush("names1","xiaomingming");
        //lrange
        List<String> names1 = jedis.lrange("names1", 0, -1);
        names1.forEach(name-> System.out.println("name = " + name));
        //lpop rpop
        String names11 = jedis.lpop("names1");
        System.out.println(names11);
        //llen
        jedis.linsert("lists", BinaryClient.LIST_POSITION.BEFORE,"xiaohei","xiaobai");
        //........
    }


10.5操作Set的相关API


//测试SET相关
@Test
public void testSet(){
  //sadd
  jedis.sadd("names","zhangsan","lisi");
  //smembers
  jedis.smembers("names");
  //sismember
  jedis.sismember("names","xiaochen");
  //...
}


10.6 操作ZSet相关API


//测试ZSET相关
@Test
public void testZset(){
  //zadd
  jedis.zadd("names",10,"张三");
  //zrange
  jedis.zrange("names",0,-1);
  //zcard
  jedis.zcard("names");
  //zrangeByScore
  jedis.zrangeByScore("names","0","100",0,5);
  //..
}


10.7 操作Hash相关API


//测试HASH相关
@Test
public void testHash(){
  //hset
  jedis.hset("maps","name","zhangsan");
  //hget
  jedis.hget("maps","name");
  //hgetall
  jedis.hgetAll("mps");
  //hkeys
  jedis.hkeys("maps");
  //hvals
  jedis.hvals("maps");
  //....
}


11.SpringBoot整合Redis

Spring Boot Data(数据) Redis 中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。


存储手机验证码 redis 60s


获取验证码:15236674712 发送(fdsfs) key:15236674712(超时时间) value:fdsfs


登录验证 :15236674712 fdsfs value=get(15236674712)


list key value() cart book book book


user 购物车(一条一条的购物项) hash KEY(用户标识) key(商品id) value(购物项对象)


排行榜 zset key(排行榜标识) 搜索的关键字(评分 )


注意: 使用RedisTemplate默认是将对象序列化到Redis中,所以放入的对象必须实现对象序列化接口


11.1 环境准备

1.引入依赖


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>


2.配置application.propertie

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0

11.2 StringRedisTemplate操作

1.key相关的操作


//key相关操作
@Test
public void testKey() {
    //查看所有key
    Set<String> keys = stringRedisTemplate.keys("*");
    keys.forEach(key -> System.out.println(key));
    //删除一个key  //成功返回true  否则返回false
    System.out.println("name是否删除成功: "+stringRedisTemplate.delete("name"));
    //删除多个key //删除成功几个key返回就是数字几
    System.out.println("成功删除了个数为: "+stringRedisTemplate.delete(Arrays.asList("name", "age")));
    //判断某个key是否存在 //存在返回 true
    System.out.println("maps是否存在: "+stringRedisTemplate.hasKey("maps"));
    //设置key超时时间  参数:key,时间,时间单位
        Boolean nsme = stringRedisTemplate.expire("nsme", 30, TimeUnit.SECONDS);
        System.out.println("给nsme设置超时时间的状态:"+nsme);
    //获取key超时时间  //返回的是存活时间 默认毫秒
    System.out.println("name过期时间: "+stringRedisTemplate.getExpire("name")); //-2
    //参数1:查看那个key超时时间  参数2:返回时间单位
    System.out.println("lists超时时间: "+stringRedisTemplate.getExpire("lists", TimeUnit.SECONDS)); //-2
    //移动key 到某一个库
    System.out.println("是否移动成功: "+stringRedisTemplate.move("sets", 3));
    //随机返回一个key
    System.out.println("随机返回的key: "+stringRedisTemplate.randomKey());
}


2.String类型的操作


@Test
public void testString(){
    //设置一个值  //永久设置一个key value
    stringRedisTemplate.opsForValue().set("name","张三");
    //设置一个key同时 指定key超时时间
    stringRedisTemplate.opsForValue().set("age","19",10,TimeUnit.HOURS);
    //在value后追加值
    stringRedisTemplate.opsForValue().append("name"," 他是一个好人");
    //给key对应数字类型value进行自减操作 -1
    stringRedisTemplate.opsForValue().decrement("age");
    //参数2:自减步长
    stringRedisTemplate.opsForValue().decrement("age",2);
    System.out.println(stringRedisTemplate.opsForValue().get("name"));
    System.out.println(stringRedisTemplate.opsForValue().get("age"));
    //获取value指定范围内结果
    System.out.println(stringRedisTemplate.opsForValue().get("name", 0, -1));
    //获取原始并设置新value
    System.out.println(stringRedisTemplate.opsForValue().getAndSet("name", "小明明"));
    //存在key不做任何操作不存在则设置value
    stringRedisTemplate.opsForValue().setIfAbsent("aa","xiaoming");
    //一次性设置多个key value 只要其中存在一个key 不做任何操作  原子性
    //stringRedisTemplate.opsForValue().multiSetIfAbsent(map)
    //获取key所对应值的长度
    System.out.println(stringRedisTemplate.opsForValue().size("name"));
}


3.List类型的操作


@Test
public void testList(){
    //获取list类型操作对象
    ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
    //创建lists列表并放入一个值
    listOperations.leftPush("lists","zhangsan");
    //创建lists列表并放入多个元素
    listOperations.leftPushAll("names","张三","李四","王五");
    listOperations.leftPushAll("ages",Arrays.asList("19","18","17"));
    //获取一个列表
    listOperations.range("names",0,-1).forEach(name-> System.out.println(name));
    System.out.println("=================================");
    //列表中某个元素之前 leftpush  之后 rightpush插入元素
    listOperations.leftPush("names","李四","小陈");
    listOperations.rightPush("names","李四","小明");
    listOperations.range("names",0,-1).forEach(name-> System.out.println(name));
    //获取指定下标的元素
    System.out.println(listOperations.index("names", 1));
    //向list放入一个值  保证list必须存在  不会创建新的列表
    listOperations.leftPushIfPresent("names","xxx");  //names: xx 王五  ...      ages: 小明 17 18 19
    //针对于两个列表 说明:从参数1列表右边弹出一个元素并把弹出元素放入参数2列表左边  参数1: 列表  参数2:列表
    System.out.println(listOperations.rightPopAndLeftPush("names","ages"));
    //remove删除重复元素
    listOperations.remove("names",2,"zhangsan");
    //根据下标修改一个值
    listOperations.set("names",2,"xiaochen");
    //截取list列表中指定内容 注意:修改list内容
    listOperations.trim("names",0,4);
    //查询列表长度
    System.out.println(listOperations.size("names"));
}


4.Set类型的操作


@Test
public void testSet(){
    SetOperations<String, String> setOperations = stringRedisTemplate.opsForSet();
    //向set集合添加一个元素
    setOperations.add("sets","xxx","123","234");
    //查看集合成员
    setOperations.members("sets").forEach(val-> System.out.println(val));
    System.out.println("===================================");
    //从set集合随机返回指定元素
    setOperations.distinctRandomMembers("sets",4).forEach( val-> System.out.println(val));
    //查询集合元素个数
    System.out.println(setOperations.size("sets"));
    //从集合中返回并移除一个元素
    System.out.println(setOperations.pop("sets"));
    //从一个集合移动到另一个集合中 注意:必须是同一种类型
    setOperations.move("sets","xxx","sets1");
    //去掉第一个集合中其它集合含有的相同元素
    setOperations.difference("sets","sets1");
    setOperations.difference("sets",Arrays.asList("sets1","sets2","sets3"));
    //求多个集合元素交集
    setOperations.intersect("sets1","sets");
    setOperations.intersect("sets1",Arrays.asList("sets","sets2"));
    //求多个集合合集
    setOperations.union("sets","sets1");
    setOperations.union("sets",Arrays.asList("sets1","sets2"));
}


5.ZSet类型的操作


@Test
public void testZset(){
    //获取Zset操作对象
    ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
    //创建一个zsets集合并放入一个元素
    zSetOperations.add("zsets","张三",10.0);
    HashSet<ZSetOperations.TypedTuple<String>> sets = new HashSet<>();
    sets.add(new DefaultTypedTuple<>("小黑",8.0));
    sets.add(new DefaultTypedTuple<>("小名",2.0));
    sets.add(new DefaultTypedTuple<>("小网",6.0));
    zSetOperations.add("zsets",sets);
    //返回zsets集合中指定范围元素
    zSetOperations.range("zsets", 0, -1).forEach(el-> System.out.println(el));  //all
    System.out.println("========================");    //all score
    zSetOperations.rangeWithScores("zsets", 0, -1).forEach(t-> System.out.println("el: "+t.getValue()+" score: "+t.getScore()));
    System.out.println("========================");
    //返回zsets集合中指定分数范围的元素        //小x
    zSetOperations.rangeByScore("zsets",0.0,8.0).forEach(el-> System.out.println(el));
    System.out.println("========================");
    //分页返回zsets集合中指定分数范围的元素           //小名 小网
    zSetOperations.rangeByScore("zsets",0.0,8.0,0,2).forEach(el-> System.out.println(el));
    System.out.println("========================");     //小x score
    zSetOperations.rangeByScoreWithScores("zsets",0.0,8.0).forEach(t-> System.out.println("el: "+t.getValue()+" score: "+t.getScore()));
    //正向排名    升序
    zSetOperations.rank("zsets","张三");
    //反向排名    降序
    zSetOperations.reverseRank("zsets","张三");
    //返回指定元素分数
    zSetOperations.score("zsets","小名");
    //移除某一个元素
    zSetOperations.remove("zsets","张三");
    //给某个元素自增分数
    zSetOperations.incrementScore("zsets","张三",2.0);
}


6.Hash类型的操作


@Test
public void testHash(){
    //获取hash类型操作对象
    HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();
    //hset
    hashOperations.put("maps","name","张三");
    //hmset
    HashMap<String, String> m = new HashMap<>();
    m.put("address","xxx");
    m.put("content","xxx");
    hashOperations.putAll("maps", m);
    //hgetall
    hashOperations.entries("maps").forEach((k,v)-> System.out.println("key: "+k +" value: "+v));
    //hget
    hashOperations.get("maps","name");
    //hmget
    hashOperations.multiGet("maps",Arrays.asList("name","addres","content")).forEach(val-> System.out.println(val));
    //hdel
    hashOperations.delete("maps","name");
    //hexists
    hashOperations.hasKey("maps","name");
    //hkeys
    hashOperations.keys("maps");
    //hvals
    hashOperations.values("maps");
    //hsetnx
    hashOperations.putIfAbsent("maps","name","xiaochen");
    //hincrby
    hashOperations.increment("maps","age",11.11);
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5月前
|
存储 NoSQL Linux
小白带你学习linux的Redis基础(三十二)
小白带你学习linux的Redis基础(三十二)
76 0
|
4月前
|
存储 NoSQL Redis
redis源码学习
redis源码学习
|
5月前
|
存储 NoSQL Ubuntu
在Ubuntu上安装Redis并学习使用get、set和keys命令
在Ubuntu上安装Redis并学习使用get、set和keys命令
|
6月前
|
缓存 NoSQL Redis
【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构
|
6月前
|
NoSQL 算法 Redis
【Redis 系列】redis 学习十四,sorted_set 初步探究梳理
【Redis 系列】redis 学习十四,sorted_set 初步探究梳理
|
6月前
|
存储 NoSQL Redis
【Redis 系列】redis 学习十五,redis sds数据结构和底层设计原理
【Redis 系列】redis 学习十五,redis sds数据结构和底层设计原理
|
6月前
|
负载均衡 NoSQL Redis
【Redis 系列】redis 学习十,Redis 集群搭建和主从复制
【Redis 系列】redis 学习十,Redis 集群搭建和主从复制
|
4月前
|
NoSQL 中间件 API
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)(下)
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)
86 2
|
4月前
|
NoSQL Java API
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)(上)
分布式锁【数据库乐观锁实现的分布式锁、Zookeeper分布式锁原理、Redis实现的分布式锁】(三)-全面详解(学习总结---从入门到深化)
75 0
|
6月前
|
存储 NoSQL 算法
[Redis 系列]redis 学习 17,redis 存储结构原理 1
[Redis 系列]redis 学习 17,redis 存储结构原理 1