Redis笔记(三)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis笔记

HyperLogLog(Redis新数据类型)


简介

为解决基数问题(求集合中不重复元素个数的问题),又不占用非常大的空间。
(数据存储在mysql表中使用distinct count计算不重复个数,或使用Redis提供的hash、set、bitmaps等数据结构来处理,以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大)

redis提出一种降低一定精度来平衡存储空间的HyperLogLog,redis HyperLogLog是用来做基数统计的算法,HyperLogLog的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的,并且是很小的
zairedis里面,每个HyperLogLog键只需要花费12kb内存,就可以计算接近2^64个不同元素的基数,这和计算基数时,元素越多越耗费内存的集合形成鲜明对比
但是,因为HyperLogLog只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog不能像集合那样,返回输入的各个元素

常用命令

pfadd  [element...]添加指定元素到HyperLogLog
pfvount[key...]计算HLL的近似基数,可以计算多个HLL。
pfmerge[sourcekey...] 将一个或多个HLL合并后的结果存储在另一个HLL中


Geospatial(Redis新数据类型)


简介


Redis 3.2 中增加了对GEO类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。


常用命令


geoadd [longitude latitude member...]添加地理位置(经度,纬度,名称)
两级无法直接添加,有效的经度从-180度到180度有效的维度从-85.05112878度到85.05112878度
已经添加的数据,是无法再次往里面添加的
geopos [member...]获取坐标值
geodist [m|km|ft|mi]获取两个位置之间的直线距离(米”默认值“,千米,英里,英尺)
georadius radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素


Redis Jedis测试


Java 使用 Redis | 菜鸟教程
https://www.runoob.com/redis/redis-java.html


<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
 <dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 <version>4.2.3</version>
 </dependency>


包括了安装,连接,使用实例等。(连接本地时记得改改config文件里面有个属性是控制本地连接的。)
(还有防火墙这一层,需要把6379端口放行,以防链接超时)

完成一个手机验证码功能

要求:
1、输入手机号,点击发送后随机生成6位数字码,2分钟有效
2、输入验证码,点击验证,返回成功或失败
3、每个手机号每天只能输入3次


package com.deng.util;
import redis.clients.jedis.Jedis;
import java.util.Random;
/**
 * @Author shayu
 * @DateTime 2022/8/23 14:17
 */
public class PhoneCode {
    public static void main(String[] args) {
        //模拟验证码发送
        verifyCode("123456789101");
        //校验验证码是否相同
        getRedisCode("123456789101","234311");
    }
    //3.验证码的校验
    public static void getRedisCode(String phone,String code){
        //从redis中获取验证码
        Jedis jedis = new Jedis("localhost",6379);
        //验证码key
        String codeKey = "VerifyCode" + phone + ":code";
        String redisCode  = jedis.get(codeKey);
        //判断
        if (redisCode.equals(code)){
            System.out.println("成功");
        }else {
            System.out.println("失败");
        }
        jedis.close();
    }
    //2.每个手机每天只能发送三次,验证码放到redis中,设置过期时间
    public static void verifyCode(String phone){
        //连接本地的 Redis 服务
        Jedis jedis = new Jedis("localhost",6379);
        // 如果 Redis 服务设置了密码,需要下面这行,没有就不需要
        // jedis.auth("123456");
        System.out.println("连接成功");
        //查看服务是否运行
        System.out.println("服务正在运行: "+jedis.ping());
        //拼接key
        //手机发送key的次数
        String countKey = "VerifyCode" + phone + ":count";
        //验证码key
        String codeKey = "VerifyCode" + phone + ":code";
        //每个手机每天发送三次
        String count = jedis.get(countKey);
        if (count == null){
            //没有发送过,第一次发送
            //设置发送次数为1
            jedis.setex(countKey,24*60*60,"1");
        }else if (Integer.parseInt(count) <= 2){
            //发送次数+1
            jedis.incr(countKey);
        }else if (Integer.parseInt(count) > 2){
            System.out.println("今天的发送次数超过三次");
            jedis.close();
            return;
        }
        //将生成的验证码放到redis里面去
        String vcode = getCode();
        jedis.setex(codeKey,120,vcode);
        jedis.close();
    }
    //1.生成6位数字的验证码
    public static String getCode(){
        Random random = new Random();
        String code = "";
        for (int i = 0; i < 6; i++) {
           int  rand = random.nextInt(10);
           code += rand ;
        }
        return code;
    }
}
/**
 * 有一个小问题,方法过期,也就是会不会有人卡着过期时间去要验证码,
 * 是不是就可以一直要了。(但过期时间有是一天,不会有人这么无聊吧。
 * 可以延伸一下,具体这么做我也不太清楚。)
 *  这也只是一个小荔枝,具体实际业务会更加复杂。
 *
 */


Springboot整合Redis

SpringBoot之Redis访问(spring-boot-starter-data-redis) - 码农教程
http://www.manongjc.com/detail/25-fidimhvkzoxchrg.html

(我偷懒不想写具体教程,需要的可以看看跟着写写)


Redis 事务操作


定义


Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队。


Multi、Exec、discard


从输入Multi命令开始(事务开始),输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec(执行)后,Redis会将之前的命令队列中的命令依次执行。
组队的过程中可以通过discard来放弃组队。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

组队成功,提交成功

网络异常,图片无法展示
|

组队阶段报错,提交失败,组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。

网络异常,图片无法展示
|

组队成功,提交有成功有失败情况,如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。


事务冲突


想想一个场景:有很多人有你的银行卡,同时去参加双十一抢购
一个请求想给金额减8000
一个请求想给金额减5000
一个请求想给金额减1000
最终会导致账号金额出现负数,是不合理的。(禁止贷款)

网络异常,图片无法展示
|

解决以上问题


悲观锁


悲观锁,顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到他拿到锁。在操作之前先上锁。


乐观锁


乐观锁,顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。redis就是利用这种check-and-set机制实现事务的。


watch key[key...]


在执行multi之前,先执行watch key1[key2]。可以监视一个或多个key,如果在事务执行之前这个key被其他命令所改动,那么事务将被打断。
set balance 100,执行watch就行监视,操作balance+10,可以完成。

网络异常,图片无法展示
|

同时开启监视,开启事务,balance+20,但前面已经进行了对key的监视,发生了变动,事务执行就会打断。

网络异常,图片无法展示
|


Redis事务的三大特性


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


  • 没有隔离级别的概念
  • 队列中的命令没有提交之前都不会实际被执行,因为事务提交之前任何指令都不会被实际执行


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

Redis持久化


为什么要有持久化?(当我看到持久化时,我第一反应就是为什么要持久化,然后去搜了一下,这位博主讲的特别有意思,简单来说就是怕redis突然宕机数据丢失做的一种保护化措施。)
redis提供了两个不同形式的持久化方式


  • RDB(Redis DataBase)
  • AOF(Append Of File)


RDB


在指定的时间间隔内将内存中的数据集快照写入磁盘(硬盘),也就是行话讲的Snapshot快照,他恢复时是将快照文件直接读到内存里
是redis默认持久化的方式


执行


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


fork延伸


(说实话我也没弄太明白这是啥,浅显理解是个进程吧)> - Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程


  • 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“写时复制技术
  • 一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
相关实践学习
基于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
目录
相关文章
|
8月前
|
canal 缓存 NoSQL
【Redis系列笔记】双写一致性
本文讨论了缓存不一致问题及其后果,如价格显示错误和订单计算错误。问题主要源于并发和双写操作的异常。解决方案包括使用分布式锁(但可能导致性能下降和复杂性增加)、延迟双删策略(通过延迟删除缓存来等待数据同步)以及异步同步方法,如通过Canal和MQ实现数据的最终一致性。面试中,可以提及这些策略来确保数据库和缓存数据的一致性。
593 1
【Redis系列笔记】双写一致性
|
8月前
|
缓存 NoSQL 安全
【Redis系列笔记】缓存三剑客
缓存穿透是指请求一个不存在的数据,缓存层和数据库层都没有这个数据,这种请求会穿透缓存直接到数据库进行查询。它通常发生在一些恶意用户可能故意发起不存在的请求,试图让系统陷入这种情况,以耗尽数据库连接资源或者造成性能问题。 缓存击穿发生在访问热点数据,大量请求访问同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据库资源,导致数据库无法使用。 缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。
181 2
|
8月前
|
存储 缓存 NoSQL
蚂蚁金服P7私藏的Redis原理与实践内部笔记
Redis 是完全开源免费的,是一个高性能的key-value类型的内存数据库。整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
116 1
|
8月前
|
NoSQL Redis
Redis原理之网络通信协议笔记
1. RESP协议 ​2. 自定义Socket连接Redis
|
8月前
|
NoSQL Linux Redis
Redis原理之网络模型笔记
Redis采用单线程模型,这意味着一个Redis服务器在任何时刻都只会处理一个请求。Redis的网络模型涉及到阻塞I/O(Blocking I/O)、非阻塞I/O(Non-blocking I/O)、I/O多路复用(I/O Multiplexing)、信号驱动I/O(Signal-driven I/O)以及异步I/O(Asynchronous I/O)。
107 1
|
8月前
|
NoSQL Java 关系型数据库
【Redis系列笔记】分布式锁
分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路
723 2
|
8月前
|
存储 消息中间件 缓存
Redis - 笔记
Redis是开源的内存数据结构存储系统,兼备数据库、缓存和消息中间件功能。它支持字符串、哈希、列表、集合、有序集合等数据结构,以及地理空间、基数统计和位图等特殊类型。Redis具备复制、LUA脚本、LRU事件、事务、持久化、哨兵和集群等高级特性,以实现高可用性。应用场景包括计数器、存储用户信息、消息队列、共同关注等。字符串最大容量为512M。
|
7月前
|
存储 NoSQL Java
Redis系列学习文章分享---第八篇(Redis快速入门之达人探店--发布探店笔记 + 查看探店笔记 + 点赞功能 + 点赞排行榜)
Redis系列学习文章分享---第八篇(Redis快速入门之达人探店--发布探店笔记 + 查看探店笔记 + 点赞功能 + 点赞排行榜)
46 0
|
8月前
|
存储 负载均衡 NoSQL
【Redis系列笔记】Redis集群
集群是一种在多个计算机或服务器之间分配和管理任务的方式。它们被广泛应用于大型计算任务、数据处理、网络服务和高性能计算等领域。在Redis中,主要有以下三种集群,分别是主从集群,哨兵集群,分片集群。
214 18
|
8月前
|
缓存 NoSQL Java
【Redis系列笔记】Redis入门
本文介绍了Redis常用命令,以及SpringBoot集成Spring Data Redis和Spring Cache。Spring Data Redis 提供了对 Redis 的操作方法,而 Spring Cache 则提供了基于注解的缓存功能,可以方便地将方法的返回值缓存到 Redis 中,以提高性能和减少对数据源的访问次数。这样的集成可以帮助开发者更便捷地利用 Redis 来管理应用程序的数据和缓存。
186 4