• [交流吐槽] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [技术干货] 解决Redis启动警告问题
    如果启动前不对linux内核做任何更改,那么redis启动会报出警告,共三个:如下图所示第一个警告:The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.意思是:TCP  backlog设置值,511没有成功,因为 /proc/sys/net/core/somaxconn这个设置的是更小的128.临时解决方法:(即下次启动还需要修改此值)echo 511 > /proc/sys/net/core/somaxconn永久解决方法:(即以后启动还需要修改此值)将其写入/etc/rc.local文件中。baklog参数实际控制的是已经3次握手成功的还在accept queue的大小。参考linux里的backlog详解 第二个警告:overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to/etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.意思是:overcommit_memory参数设置为0!在内存不足的情况下,后台程序save可能失败。建议在文件 /etc/sysctl.conf 中将overcommit_memory修改为1。临时解决方法:echo "vm.overcommit_memory=1" > /etc/sysctl.conf永久解决方法:将其写入/etc/sysctl.conf文件中。参考:有关linux下redis overcommit_memory的问题 第三个警告:you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix thisissue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain thesetting after a reboot. Redis must be restarted after THP is disabled.意思是:你使用的是透明大页,可能导致redis延迟和内存使用问题。执行 echo never > /sys/kernel/mm/transparent_hugepage/enabled 修复该问题。临时解决方法:echo never > /sys/kernel/mm/transparent_hugepage/enabled。永久解决方法:将其写入/etc/rc.local文件中。参考透明大页介绍 。到此这篇关于解决Redis启动警告问题的文章就介绍到这了转载自https://www.jb51.net/article/238574.htm
  • [交流吐槽] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [技术干货] Redis基础知识
    1.Redis的诞生1.1 磁盘和内存数据存储分为两个位置,一个是磁盘,另一个是内存。1.1.1 磁盘的优势是成本价格便宜,缺点是寻址速度是ms(毫秒级)补充:磁盘由一圈圈磁道组成,而磁道又由很多扇区组成,读取扇区中的数据时,最少是读取4k的数据,如果小于4k还是会读取4k的信息。1.1.2 内存的优势是寻址速度是ns(纳秒级,相当于磁盘的十万倍),缺点是成本价格很昂贵1.2 为什么使用Redis1.2.1 数据量变大的影响因为内存相对磁盘很小,所以数据基本都是存储在磁盘中,而其中的索引是将B-Tree之类的树中的枝干存储在内存类(因为内存寻址比磁盘快十万倍,所以查找会变快),当表的字段变多的时候或数据量变大,增删改速速会变慢,但是查询速度在查询量很小时还是会很快,但是高并发查询时会被磁盘的带宽影响速度变的很慢。1.2.2 Redis缓存的诞生在硬盘的各种缺点和内存的成本之间,都会大大影响我们日常的使用,因此Redis这类缓存技术就诞生了,他会将一部分资源放进内存中。Redis是一个高性能(读写非常快,读可以达到每秒十万次,写可以达到每秒8万次)的key-value数据库,并且提供string 字符串(可以为整形、浮点型和字符串,统称为元素)、list 列表(实现队列,元素不唯一,先入先出原则)、set 集合(各不相同的元素)、hash散列值(hash的key必须是唯一的)、sort set 有序集合五种数据结构的存储。2.Linux安装2.1 yum install wget此例为空服务器上,首先安装wget2.2 cd 进入根目录或者任意目录2.3 mkdir redisTest 创建文件夹存放redis压缩包2.4 cd redisTest 进入到redisTest文件夹目录下2.5 wget http://download.redis.io/releases/redis-xxx.tar.gz 下载对应的版本的redis压缩包2.6 tar xf redis.xxx.tar.gz 解压缩redis压缩包到当前目录下2.7 cd redis中src查看README.md文档,里面会有安装的说明等2.8 make 进行编译安装2.8.1 如果安装失败,检查原因,比如没有gcc就需要安装gcc,执行指令是 yum install gcc         如果安装失败,会有些安装失败的文件,需要通过指令make disclean进行清除,然后再进行make编译安装指令。2.9 cd 进入src目录下,如果看到redis-server等绿色的可执行文件则为安装成功2.10 cd..会到安装目录下2.11 make install PREFIX=/opt/test(任意目录),将可执行文件安装到指定目录,用于之后的开机自启动和多个redis的配置2.12 vim /etc/profile 进入profile文件夹下进行环境变量的配置        export REDIS_HOME=/opt/test(上面存放的任意目录)        export PATH=$PATH:$REDIS_HOME/bin       source /etc/profile 重新加载配置文件2.13 cd utils 进行多个redis的配置2.14 ./install_server.sh 可以执行一次或者多次爬坑1 参考1如果出现下面提示,需要将_pid_1_exe方法整个屏蔽掉再执行./install_server.sh就可以完成设置了Welcome to the redis service installer This script will help you easily set up a running redis server This systems seems to use systemd. Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!2.1.4.1 一个物理机中可以有多个redis实例(进程),通过port端口号进行区分;2.1.4.2 可执行程序只有一份存在上面的自己放的任意目录,但是内存中可以有多个实例,只需要执行install_server,sh脚本进行指定port端口号、各自的配置文件、持久化目录。2.1.4.3 启动/停止命令是通过指令 service redis_6379 start/stop/stauts进行执行,redis_6379这类的是在/etc/init.d/xxx,是通过上面脚本配置的端口号自动生成的。再通过脚本设置另外一个6380端口的redis实例,通过ps -fe | grep redis查看已经启动redis进程,此时就可以看到6379和6380两个redis实例已经启动了。
  • [交流分享] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [知识分享] 延迟任务场景,该如何提高吞吐量和时效性
    >摘要:随着业务需求的发展和功能的复杂度提升,往往反馈到研发设计和实现,就不那么简单了,怎么办呢?本文分享自华为云社区《[给面试加点硬菜:延迟任务场景,该如何提高吞吐量和时效性!](https://bbs.huaweicloud.com/blogs/330938?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=other&utm_content=content)》,作者: 小傅哥。 # 一、延迟任务场景 什么是延迟任务? 当我们的实际业务需求场景中,有一些活动开始前的状态变更、订单结算后的T+1对账、贷款单息费的产生,都是需要使用到延迟任务来进行触达。实际的操作一般会有 Quartz、Schedule 来对你的库表数据进行定时扫描和处理,当条件满足后做数据状态的变更或者产生新的数据插入到表中。 这样一个简单的需求就是延迟任务最初需求,如果需求前期内容较少、使用方不多,可能在实际开发中就只是一个单台机器直接对着表一顿轮训就完事了。但随着业务需求的发展和功能的复杂度提升,往往反馈到研发设计和实现,就不那么简单了,比如:你需要保障尽可能低延迟完成较大规模的数据量扫描处理,否则就像贷款单息费的产生,已经到了第二天用户还没看到自己的息费信息或者是还款后的重新对账,可能就这个时候就要产生客诉了。 那么,类似这样的场景该如何设计呢? # 二、延迟任务设计 通常的任务中心处理流程主要,主要是由定时任务扫描任务库表,把即将达到超时时间的任务信息扫描到处理队列(内存/MQ消息),再由业务系统进行处理任务,处理完成后更新库表中的任务状态。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20222/18/1645170130720538620.png) 问题: 1. 海量数据规模较大的任务列表数据,在分库分表下该需要快速扫描。 2. 任务扫描服务与业务逻辑处理,耦合在一起,不具有通用性和复用性。 3. 细分任务体系有些是需要低延迟处理的,不能等待过长时间。 ## 1. 任务表方式 除了一些较小的状态变更场景,例如在各自业务的库表中,就包含了一个状态字段,这个字段一方面有程序逻辑处理变更的状态,也有到达指定到期时间后由任务服务自动变更处理的操作,一般这类功能,直接设计到自己的库表中即可。 那么还有一些较大也较为频繁使用的场景,如果都是在每个系统的各自所需的N多个表中,都添加这样的字段进行维护,就显得非常冗余了,也不那么易于维护。所以针对这样的场景就很适合做一个通用的任务延时系统,各业务系统把需要被延时执行的动作提交到延时系统中,再有延时系统在指定时间下进行回调,回调的动作可以是接口或者MQ消息进行触达。例如可以设计这样一个任务调度表: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20222/18/1645170151504483645.png) 1. 抽取的任务调度表,主要是拿到什么任务,在什么时间发起动作,具体的动作处理仍交给业务工程处理。 2. 大批量的各自业务的任务进行集中处理,则需要设计一个分库分表,满足于后续业务体量的增长。 3. 门牌号设计,针对一张表的扫描,如果数据量较大,又不希望只是一个任务扫描一个表,可以多个任务扫描一个表,加到扫描的体量。这个时候就需要一个门牌号来隔离不同任务扫描的范围,避免扫描出重复的任务数据。 ## 2. 低延迟方式 低延迟处理方案,是在任务表方式的基础上,新增加的时间把控处理。它可以把即将到期的前一段时间的任务,放置到 Redis 集群队里中,在消费的时候再从队列中 pop 出来,这样可以更快的接近任务的处理时效,避免因为扫库间隔较大延迟任务执行。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20222/18/1645170177118647251.png) - 在接收业务系统提交进来的延迟任务时,按照执行时间的长短放置到任务库或者也同步到 Redis 集群中,一些执行时间较晚的任务则可以先放到任务库,再通过扫描的方式添加到超时任务执行队列中。 - 那么关于这块的设计核心在于 Redis 队列的使用,以及为了保证消费的可靠性需要引入二阶段消费、注册 ZK 注册中心至少保证一次消费的处理。本文重点主要放在 Redis 队列的设计,其他更多的逻辑处理,可以按照业务需求进行扩展和完善 # Redis 消费队列 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20222/18/1645170202285744313.png) - 按照消息体计算对应数据所属的槽位 index = CRC32 & 7 - StoreQueue 采用 Slot 按照 SlotKey = #{topic}_#{index} 和 Sorted Set 的数据结构按执行任务分数排序,存放任务执行信息。定时消息将时间戳作为分数,消费时每次弹出分数小于当前时间戳的一个消息 - 为了保障每条消息至少可消费一次,消费者不是直接 pop 有序集合中的元素,而是将元素从 StoreQueue 移动到 PrepareQueue 并返回消息给消费者。消费成功后再从 PrepareQueue 从删除,如果消费失败则从PreapreQueue 重新移动到 StoreQueue,这样二阶段消费的方式进行处理。 ## 简单案例 @Test public void test_delay_queue() throws InterruptedException { RBlockingQueue blockingQueue = redissonClient.getBlockingQueue("TASK"); RDelayedQueue delayedQueue = redissonClient.getDelayedQueue(blockingQueue); new Thread(() -> { try { while (true){ Object take = blockingQueue.take(); System.out.println(take); Thread.sleep(10); } } catch (InterruptedException e) { e.printStackTrace(); } }).start(); int i = 0; while (true){ delayedQueue.offerAsync("测试" + ++i, 100L, TimeUnit.MILLISECONDS); Thread.sleep(1000L); } } ## 测试数据 2022-02-13 WARN 204760 --- [ Finalizer] i.l.c.resource.DefaultClientResources : io.lettuce.core.resource.DefaultClientResources was not shut down properly, shutdown() was not called before it's garbage-collected. Call shutdown() or shutdown(long,long,TimeUnit) 测试1 测试2 测试3 测试4 测试5 Process finished with exit code -1 - 源码:GitHub - fuzhengwei/TimeOutCenter: TimeOutCenter - 描述:使用 redisson 中的 DelayedQueue 作为消息队列,写入后等待消费时间进行 POP 消费。 # 三、总结 - 调度任务的使用在实际的场景中非常频繁,例如我们经常使用 xxl-job,也有一些大厂自研的分布式任务调度组件,这些可能原本都是很小很简单的功能,但经过抽象、整合、提炼,变成了一个个核心通用的中间件服务。 - 当我们在考虑使用任务调度的时候,无论哪种方式的设计和实现,都需要考虑这个功能使用时候的以为迭代和维护性,如果仅仅是一个非常小的场景,又没多少人使用的话,那么在自己机器上折腾就可以。过渡的设计和使用有时候也会把研发资源代入泥潭 - 其实各项技术的知识点,都像是一个个工具,刀枪棍棒斧钺钩,那能怎么结合各自的特点,把这些兵器用起来,才是一个程序员不断成长的过程。
  • [交流分享] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [交流分享] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [java] 不会用SpringBoot连接Redis,那就赶紧看这篇
    摘要:如何通过springboot来集成操作Redis。本文分享自华为云社区《SpringBoot连接Redis操作教程》,作者: 灰小猿。今天来和大家分享一个如何通过springboot来集成操作Redis。一、SpringBoot连接Redisspringboot连接Redis时需要在pom文件中导入所需的jar包依赖,依赖如下: <!-- 加入jedis依赖 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> (1)使用Jedis类直接连接Redis服务器在springboot环境下连接redis的方法有很多,首先最简单的就是直接通过jedis类来连接,jedis类就相当于是redis的客户端表示。连接方法如下: /** * redis连接测试01 */ @Test public void redisTest01() { //连接本地的 Redis 服务 Jedis jedis = new Jedis("localhost"); // 如果 Redis 服务设置了密码,需要用下面这行代码输入密码 // jedis.auth("123456"); System.out.println("连接成功"); //查看服务是否运行 System.out.println("服务正在运行: "+jedis.ping()); }运行后结果:通过这种方式进行连接时,springboot会自动的去本地寻找redis服务器进行连接,如果没有找到那么就会报错,如果你去阅读jedis的底层源码,你会发现Jedis类有多种构造方法,常用的几个是使用默认地址和端口//不传值,那么使用默认的127.0.0.1地址,6379端口就访问 public Jedis()使用指定地址和默认端口//只传入目的地址,那么使用指定的地址和默认的端口号去访问 public Jedis(String host)使用指定地址和端口//传入目的地址和端口号,那么使用指定的地址和端口号去访问 public Jedis(String host, int port)(2)通过配置文件进行连接在springboot中,当然是可以通过配置文件的形式来设置各种连接参数了,Redis也是一样的,在yml文件中进行如下配置:注意:这是没有使用连接池的,如果使用连接池,需要在下边增加配置,关于使用连接池的可以继续往下看。##redis配置信息 spring: redis: database: 0 #redis数据库索引,默认为0 host: 127.0.0.1 #redis服务器地址 port: 6379 #redis服务器连接端口 password: #redis服务器连接密码,默认为null timeout: 5000 #redis连接超时时间通过配置文件来进行配置之后,我们就可以使用springboot中的一个工具类来操作Redis的操作了,springboot会自动读取配置文件中的配置信息,然后通过该配置信息去连接Redis服务器,springboot中提供操作Redis的工具类有两个,分别是:StringRedisTemplate和RedisTemplate,StringRedisTemplate和RedisTemplate的区别如下在进行序列化时,RedisTemplate使用的是 JdkSerializationRedisSerializer,而StringRedisTemplate使用的是StringRedisSerializerStringRedisTemplate继承了RedisTemplate<String,String>,而RedisTemplate 定义为 RedisTemplate<K, V>,所有StringRedisTemplate就限定了K,V为String类型的相同处体现在他们对Redis的操作上,RedisTemplate和StringRedisSerializer都定义了五种对Redis的操作,分别对应这Redis中的五种数据类型。redisTemplate.opsForValue();  //操作字符串 redisTemplate.opsForHash();   //操作hash redisTemplate.opsForList();   //操作list redisTemplate.opsForSet();   //操作set redisTemplate.opsForZSet();   //操作有序set那么在使用的时候,这两个类应该如何选择呢?如果你的redis数据库里面本来存的是字符串数据,或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,》但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。接下来我以StringRedisSerializer为例子,来给大家演示一下使用StringRedisSerializer操作Redis的方法, /** * springboot主从连接测试, * 使用springRedisTemplate操作 */ @Test public void redisTest06() { // 操作字符型 stringRedisTemplate.opsForValue().set("test06","Test06"); System.out.println(stringRedisTemplate.opsForValue().get("test06")); // 设置key的过期时间,30秒 stringRedisTemplate.expire("test06", 30 * 1000, TimeUnit.MILLISECONDS); // 根据key获取过期时间 Long test06ExpireTime = stringRedisTemplate.getExpire("test06"); System.out.println("根据key获取过期时间:" + test06ExpireTime); // 根据key获取过期时间,并且换算成指定单位 Long test06ExpireTimeToUnit = stringRedisTemplate.getExpire("test06", TimeUnit.SECONDS); System.out.println("根据key获取过期时间,并且换算成指定单位:" + test06ExpireTimeToUnit); // 检查key是否存在,返回布尔类型 Boolean test06IsExist = stringRedisTemplate.hasKey("test06"); System.out.println("检查key是否存在,返回布尔类型:" + test06IsExist); }在上面的操作中,有一点关于获取和设置key过期时间的操作,当时在操作的时候对其进行了一下探究,在这里分享给大家stringRedisTemplate中获取过期时间的getExpire()方法的说明如果最开始没有设置过期时间,那么就返回-1,数据在没有达到Redis数据最大限额的情况下会一直存在.如果设置了过期时间,但是数据还未过期,就返回剩余时间,如果到了过期时间,那么数据会被删除如果数据被删除或者不存在,那么就返回-2.
  • [技术行业前沿] 【数据库系列】华为云GuassDB(for Redis)发布全新版本推出:Lua脚本和SSL连接加密
    >摘要:9月8日,华为云GuassDB(for Redis)正式推出全新版本。新版本内核带来性能提升、无损升级、慢日志统计等多维度产品体验,同时推出Lua脚本和SSL连接加密两大重要功能,让业务设计更加灵活,公网访问更安全。本文分享自华为云社区《[华为云GuassDB(for Redis)发布全新版本,两大核心特性正式亮相](https://bbs.huaweicloud.com/forum/thread-153489-1-1.html?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=database&utm_content=content)》,作者:GaussDB 数据库。 9月8日,华为云GuassDB(for Redis)正式推出全新版本。新版本内核带来性能提升、无损升级、慢日志统计等多维度产品体验,同时推出Lua脚本和SSL连接加密两大重要功能,让业务设计更加灵活,公网访问更安全。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/150733eft0q09uz0z39cwo.png) GaussDB(for Redis)是华为云推出的企业级分布式KV数据库,它完全兼容Redis协议,提供丰富的数据类型,同时基于云原生存储计算分离架构,在成本、可靠性等方面为企业带来全新价值,此番推出的两大功能特性更是为企业业务发展带来全新体验。 # Lua脚本功能:业务设计更灵活 GaussDB(for Redis)推出的Lua脚本功能,支持用户预设逻辑,组合执行多条命令,让业务设计更加灵活。使用方法上,GaussDB(for Redis)的Lua脚本功能与开源Redis保持完全兼容。用户可以将一组命令编入Lua脚本,交给GaussDB(for Redis)执行,从而实现原子操作的效果。 相比开源Redis Cluster,GaussDB(for Redis)的Lua脚本功能更为优秀: - **脚本执行不易引发请求阻塞**:这是由于GaussDB(for Redis)实例内部有着更细粒度的数据分片,同时每个分片都有多线程执行命令的能力。 - **消除“脚本复制”的副作用**:开源Redis主从脚本复制让时间模块、随机命令等功能受限,GaussDB(for Redis)内核采用全新实现,并无此类限制,业务设计更轻松。 - **强一致保障**:在高并发场景,GaussDB(for Redis)提供数据强一致保障,业务多点访问不会发生脏读。 根据以往经验,Lua脚本在一些业务场景起着关键作用,例如:**订单系统**要求用户余额不出现负数,库存系统要避免商品超卖……它们都需要使用Lua脚本来确保“查询+扣减”的原子性语义。GaussDB(for Redis)将Lua脚本与强一致特性结合,给业务设计带来极大灵活性。 # SSL连接加密功能:公网访问更安全 GaussDB(for Redis)提供的SSL连接加密功能,支持客户端使用SSL协议连接数据库,提升公网访问安全性。用户只需从华为云控制台下载证书,并使用支持SSL协议的客户端(例如Redis-cli 6.0),即可与实例建立安全可靠连接。 通过控制台,用户还可以随时开启或禁用SSL连接模式。当连接模式发生切换,旧连接会被断开以确保实例网络安全。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/150931mx4htvon8rx6y4ii.png) 相比开源Redis 6.0 SSL,GaussDB(for Redis)保持兼容并带来以下优势: - **性能更好**:开启SSL后的性能损失更小,约15%;而开源Redis损失更多。 - **多线程完美兼容**:开启SSL不影响多线程并发能力,而开源Redis的SSL与多线程存在二选一冲突。 在一些场景中,业务有从公网甚至海外访问数据库的需求。此时,对于核心数据存储,全链路的安全保障尤为重要,新版GaussDB(for Redis)能够极大提升公网访问安全性。 # GuassDB(for Redis)核心价值 作为云原生KV数据库,GaussDB(for Redis)有着全面领先于开源Redis的能力: - **成本降低75%以上**:全量数据落盘,容量利用率高 - **高稳定性**:即使N-1节点故障,全量数据依旧可用 - **高可靠性**:数据三副本冗余存储,无丢失风险 - **强一致性**:强一致性保障,多点访问无脏读问题 - **强抗写能力**:全部节点可写,多线程设计 - **强扩展能力**:节点分钟级、容量秒级扩容 目前GaussDB(for Redis)已经凭借出色的产品实力在游戏系统、电商平台、推荐系统、社交媒体、物联网等众多企业级应用场景中发挥巨大作用。新推出的Lua脚本和SSL连接加密两大功能特性,更是为企业数字化转型注入了全新动力。想体验更多产品能力,[欢迎前往华为云官网](https://www.huaweicloud.com/product/gaussdbforredis.html)。
  • [技术原理] 华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的应用
    一、背景       即时通讯(Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频。微信、QQ等IM类产品在这个高度信息化的互联网时代已成为生活必备品,IM系统中最核心的部分是消息系统,消息系统中最核心的功能是消息的同步、存储和检索。消息同步:将消息完整的、快速的从发送方发送至接收方。消息同步系统最重要的衡量指标是消息传递的实时性、完整性、顺序性以及支撑的消息规模。消息存储:即消息的持久化,传统消息系统通常支持消息在接收端的本地存储,数据基本不具备可靠性。现代消息系统支持消息在云端存储,从而实现消息异地查询:账号可在任意客户端登陆查看所有历史消息。消息检索:消息一般是文本,所以支持全文检索也是必备的能力之一。传统消息系统通常来说基于本地存储的消息数据来构建索引,支持消息的本地检索。而现代消息系统支持消息的在线存储以及存储过程中构建索引,提供全面的消息检索功能。二、IM系统架构设计       上图为IM系统的应用场景,可用于聊天,游戏、智能客服等诸多行业。不同行业对IM系统的成本、性能、可靠性、时延等指标的需求是不同的,架构设计需要进行平衡。接下来将介绍IM系统架构设计所涉及到的一些基本概念。2.1 传统架构 vs 现代架构 传统架构先同步后存储。在线消息同步和离线消息缓存。服务端不会对消息进行持久化,无法支持消息异地查询。现代架构先存储后同步。划分消息存储库与消息同步库。消息存储库用于全量保存所有会话消息,主要用于支持消息异地查询。消息同步库,主要用于接收方的多端同步。提供消息全文检索能力。2.2 读扩散vs 写扩散        《2020微信数据报告》指出,截至2020年9月,微信月活跃用户数为10.825亿,日消息发送次数450亿次,日音视频呼叫成功次数4.1亿次。面临这么多的消息,如何保证消息传递的可靠性、一致性并且有效的降低服务器或者客户端的压力是十分具有技术挑战的。其中,采用何种读写模型对IM系统至关重要,这里介绍两种模型:读扩散和写扩散。        如上图所示,用户B与每个聊天的人(A1,A2,A3)都有一个信箱(一种数据结构的抽象,用于存储消息),B在查看聊天信息时需读取所有有新消息的信箱。IM系统里的读扩散通常是每两个相关联的人就有一个信箱。读扩散的优点:写操作(发消息)轻量,不管是单聊还是群聊,只需要往相应的信箱写一次即可。每一个信箱天然就是两个人的聊天记录,可以方便查看和搜索聊天记录。读扩散的缺点:读操作(读消息)很重,存在读放大效应。如上图,在写扩散中,用户(B1,B2,B3)都只从自己的信箱里读取消息,但写(发消息)的时候,对于单聊跟群聊处理如下:单聊:往自己的信箱跟对方的信箱都写一份消息;同时,如果需要查看两个人的聊天历史记录的话还需要再写一份。群聊:发信息时需要针对所有群成员的信箱都写一份消息。群聊使用的是写扩散模型,而写扩散很消耗资源,因此微信群有人数上限(目前是500)。写扩散优点:读操作很轻量,只需要读取自己的邮箱。可以很方便实现消息的多终端同步。写扩散缺点:写操作很重,尤其是对于群聊来说。2.3 推模式 vs 拉模式 vs 推拉结合模式       在IM系统中,消息的获取通常有三种模式:推模式(Push):新消息到达时由服务器主动推送给所有客户端;需要客户端和服务器建立长连接,实时性很高,对客户端来说只需要接收处理消息即可;缺点是服务端不知道客户端处理消息的能力,可能会导致数据积压。拉模式(Pull):由前端主动发起拉取消息的请求,为了保证消息的实时性,一般采用推模式,拉模式一般用于获取历史消息;因客户端拉取新消息的时间间隔不好预设,太短可能会导致大量的连接拉取不到数据,太长导致数据接收不及时。推拉结合模式:兼顾push和pull两种模式的优点。新消息来临时服务器会先推送一个新消息到达的通知给前端,前端接收到通知后就向服务器拉取消息。三、IM技术挑战       上图为IM系统的总体架构图,Client双方通信会经过Server转发来完成消息传递。其核心为消息存储库和消息同步库。这两种库对存储层的性能有极高的要求。支撑海量数据存储:对于消息存储库来说,如果需要消息永久存储,则随着时间的积累,数据规模会越来越大,需存储库支持容量无限扩展以应对日益增长的消息数据。低存储成本:消息数据具有明显的冷热特征,大部分查询集中在热数据,冷数据需要一个低成本的存储方式,否则随着时间的积累,数据量不断膨胀,存储成本会不断上升。数据生命周期管理:不管是对于消息数据的存储还是同步,数据都需要定义生命周期。存储库是用于在线存储消息数据本身,通常需要设定一个较长周期的保存时间。而同步库  是用于写扩散模式的在线或离线推送,通常设定一个较短的保存时间。极高的写入吞吐:绝大部分IM类场景,通常是采用写扩散模型,写扩散要求底层存储具备极高的写入吞吐能力,从而应对消息洪峰。低延迟的读:消息系统通常应用于在线场景,具备较高的实时性,读取延迟应尽可能低。四、高斯Redis在IM场景中的优势       IM系统的核心是存储层,其性能差异将直接影响IM系统的用户体验。目前存储层可选择的数据库产品有很多,如HBase、开源Redis等等。选择何种数据库,需根据业务规模、成本、性能等指标来进行综合选择。这里介绍一种NoSQL数据库:高斯Redis,在性能和规模上,可以满足IM系统对存储层的严格要求:海量数据存储、低存储成本、生命周期管理、写入吞吐大、读取时延低。4.1高斯Redis简介       高斯Redis是华为云数据库团队自主研发且兼容Redis5.0协议的云原生数据库,采用计算存储分离架构。存储侧使用自研的存储系统,容量无限扩展、强一致、高可靠。计算侧基于 LSM 存储引擎实现,通过将大量的随机写转换为顺序写,从而极大的提升了数据写入性能,同时也通过读缓存、bloom filter 等极大优化了读取性能。下图是高斯Redis在IM场景的优势介绍。4.2基于高斯Redis的IM应用案例:       下图是基于高斯Redis的IM系统模型图,这里我们使用stream作为基本数据结构。Redis stream不仅可以作为消息存储容器,还实现了生产者、消费者等基本模型,具有IM系统的基本功能,如消息订阅,分发、增加消费者等,用户可基于高斯Redis快速构建一套IM系统。创建一个群聊时,在Redis中对应地为该群聊创建一个stream队列。在发送消息时,每个用户都将消息按照时间顺序添加到stream队列中,保证了消息的有序性。stream是一个持久化的队列,可保证信息不丢失。五、总结       高斯Redis通过一系列技术创新实现了读写性能水平扩展,秒级扩容,低成本以及自动备份等功能, 可作为IM系统的存储层,其优异的读写性能和高级特性将会极大助力IM应用.同时,高斯Redis在开源Redis的基础之上,较好平衡了性能和成本,能够广泛应用在智慧医疗、流量削峰、计数器等领域。六、结束本文作者:华为云高斯Redis团队。杭州西安深圳简历投递:yuwenlong4@huawei.com更多技术文章,关注高斯Redis官方博客:https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813七、参考资料1. 《GaussDB(for Redis)官方主页》https://www.huaweicloud.com/product/gaussdbforredis.html2. 《华为云GaussDB(for Redis)与自建开源Redis的成本对比》https://www.modb.pro/db/427393. 《华为云PB级数据库GaussDB(for Redis)揭秘第一期:Redis与存算分离》https://bbs.huaweicloud.com/blogs/2385844. 《华为云PB级数据库GaussDB(for Redis)揭秘第三期:一场由fork引发的超时,让我们重新探讨了Redis的抖动问题》https://bbs.huaweicloud.com/blogs/2456515. 《现代 IM 系统中的消息系统架构—架构篇》https://www.infoq.cn/article/ypb3y2lv-dsftrr5cguv
  • [干货汇总] 【数据库系列】Redis:我是如何与客户端进行通信的
    >摘要:我是一个Redis服务,最引以为傲的就是我的速度,我的 QPS 能达到10万级别。本文分享自华为云社区《[Redis:我是如何与客户端进行通信的](https://bbs.huaweicloud.com/blogs/327076?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=other&utm_content=content)》,作者: 码农参上 。 江湖上说,**天下武功,无坚不摧,唯快不破**,这句话简直是为我量身定制。 我是一个Redis服务,最引以为傲的就是我的速度,我的 QPS 能达到10万级别。 在我的手下有数不清的小弟,他们会时不时到我这来存放或者取走一些数据,我管他们叫做客户端,还给他们起了英文名叫 Redis-client。 有时候一个小弟会来的非常频繁,有时候一堆小弟会同时过来,但是,即使再多的小弟我也能管理的井井有条。 有一天,小弟们问我。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141039pz3mvfc4sb87xrnc.png) 想当年,为了不让小弟们拖垮我傲人的速度,在设计和他们的通信协议时,我绞尽脑汁,制定了下面的三条原则: - 实现简单 - 针对计算机来说,解析速度快 - 针对人类来说,可读性强 为什么这么设计呢?先来看看一条指令发出的过程,首先在客户端需要对指令操作进行封装,使用网络进行传输,最后在服务端进行相应的解析、执行。 这一过程如果设计成一种非常复杂的协议,那么封装、解析、传输的过程都将非常耗时,无疑会降低我的速度。什么,你问我为什么要遵循最后一条规则?算是对于程序员们的馈赠吧,我真是太善良了。 我把创造出来的这种协议称为 RESP (REdis Serialization Protocol)协议,它工作在 TCP 协议的上层,作为我和客户端之间进行通讯的标准形式。 说到这,我已经有点迫不及待想让你们看看我设计出来的杰作了,但我好歹也是个大哥,得摆点架子,不能我主动拿来给你们看。 所以我建议你直接使用客户端发出一条向服务器的命令,然后取出这条命令对应的报文来直观的看一下。话虽如此,不过我已经被封装的很严实了,正常情况下你是看不到我内部进行通讯的具体报文的,所以,你可以伪装成一个Redis的服务端,来截获小弟们发给我的消息。 实现起来也很简单,我和小弟之间是基于 Socket 进行通讯,所以在本地先启动一个ServerSocket,用来监听Redis服务的6379端口: public static void server() throws IOException { ServerSocket serverSocket = new ServerSocket(6379); Socket socket = serverSocket.accept(); byte[] bytes = new byte[1024]; InputStream input = socket.getInputStream(); while(input.read(bytes)!=0){ System.out.println(new String(bytes)); } } 然后启动redis-cli客户端,发送一条命令: `set key1 value1` 这时,伪装的服务端就会收到报文了,在控制台打印了: *3 $3 set $4 key1 $6 value1 看到这里,隐隐约约看到了刚才输入的几个关键字,但是还有一些其他的字符,要怎么解释呢,是时候让我对协议报文中的格式进行一下揭秘了。 我对小弟们说了,对大哥说话的时候得按规矩来,这样吧,你们在请求的时候要遵循下面的规则: *参数数量> CRLF $参数1的字节长度> CRLF 参数1的数据> CRLF $参数2的字节长度> CRLF 参数2的数据> CRLF ... $参数N的字节长度> CRLF 参数N的数据> CRLF 首先解释一下每行末尾的CRLF,转换成程序语言就是\r\n,也就是回车加换行。看到这里,你也就能够明白为什么控制台打印出的指令是竖向排列了吧。 在命令的解析过程中,set、key1、value1会被认为是3个参数,因此参数数量为3,对应第一行的*3。 第一个参数set,长度为3对应$3;第二个参数key1,长度为4对应$4;第三个参数value1,长度为6对应$6。在每个参数长度的下一行对应真正的参数数据。 看到这,一条指令被转换为协议报文的过程是不是就很好理解了? ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141211zluap44sycjewcat.png) 当小弟对我发送完请求后,作为大哥,我就要对小弟的请求进行**指令回复**了,而且我得根据回复内容进行一下分类,要不然小弟该搞不清我的指示了。 # 简单字符串 简单字符串回复只有一行回复,回复的内容以+作为开头,不允许换行,并以\r\n结束。有很多指令在执行成功后只会回复一个OK,使用的就是这种格式,能够有效的将传输、解析的开销降到最低。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141245fnobz8tgddkw3ohn.png) # 错误回复 在RESP协议中,错误回复可以当做简单字符串回复的变种形式,它们之间的格式也非常类似,区别只有第一个字符是以-作为开头,错误回复的内容通常是错误类型及对错误描述的字符串。 错误回复出现在一些异常的场景,例如当发送了错误的指令、操作数的数量不对时,都会进行错误回复。在客户端收到错误回复后,会将它与简单字符串回复进行区分,视为异常。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141301jwtvcrxu1jd634ps.png) # 整数回复 整数回复的应用也非常广泛,它以:作为开头,以\r\n结束,用于返回一个整数。例如当执行incr后返回自增后的值,执行llen返回数组的长度,或者使用exists命令返回的0或1作为判断一个key是否存在的依据,这些都使用了整数回复。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141316xwqdxzbnl7perc7p.png) # 批量回复 批量回复,就是多行字符串的回复。它以$作为开头,后面是发送的字节长度,然后是\r\n,然后发送实际的数据,最终以\r\n结束。如果要回复的数据不存在,那么回复长度为-1。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141338i4s88bx9hmlgwzlb.png) # 多条批量回复 当服务端要返回多个值时,例如返回一些元素的集合时,就会使用多条批量回复。它以*作为开头,后面是返回元素的个数,之后再跟随多个上面讲到过的批量回复。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202201/28/141401s6ytlhpsn5vaeemv.png) 到这里,基本上我和小弟之间的通讯协议就介绍完了。刚才你尝试了伪装成一个服务端,这会再来试一试直接写一个客户端来直接和我进行交互吧。 private static void client() throws IOException { String CRLF="\r\n"; Socket socket=new Socket("localhost", 6379); try (OutputStream out = socket.getOutputStream()) { StringBuffer sb=new StringBuffer(); sb.append("*3").append(CRLF) .append("$3").append(CRLF).append("set").append(CRLF) .append("$4").append(CRLF).append("key1").append(CRLF) .append("$6").append(CRLF).append("value1").append(CRLF); out.write(sb.toString().getBytes()); out.flush(); try (InputStream inputStream = socket.getInputStream()) { byte[] buff = new byte[1024]; int len = inputStream.read(buff); if (len > 0) { String ret = new String(buff, 0, len); System.out.println("Recv:" + ret); } } } } 运行上面的代码,控制台输出: `Recv:+OK` 上面模仿了客户端发出set命令的过程,并收到了回复。依此类推,你也可以自己封装其他的命令,来实现一个自己的Redis客户端来和我进行通信。
  • [交流吐槽] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
  • [技术干货] 利用Nginx+ Flask +MySQL+ Redis,部署一个从Docker到Docker-Compose的应用
    应用概述:把一个Flask项目的MySQL数据库、Redis数据库、Flask应用、Nginx服务分别装到四个容器中,然后用Docker-Compose命令同时启动与关闭。   Flask 技术   Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。另外,Flask还有很强的定制性,用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。 Flask是基于Python开发的框架,类似的框架还有Django、Tornado等,相比于另外两个框架Flask因为灵活、轻便且高效的特点被业界认可,同时拥有基于Werkzeug、Jinja2等一些开源库,拥有内置服务器和单元测试,适配RESTful,支持安全的cookies。并且Flask中拥有灵活的Jinja2模板引擎,提高了前端代码的复用率。这样可以提高开发效率和有利于后期开发与维护。   Redis技术   Redis是一个开源(BSD 许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过 Redis Sentinel提供高可用,通过 Redis Cluster 提供自动分区。Redis是一个高性能的key-value 数据库。Redis的出现,很大程度补偿了memcached 这类 key/value 存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了 Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。   MySQL技术   MySQL 是一款安全、跨平台、高效的,并与PHP、Java等主流编程语言紧密结合的数据库系统。目前 MySQL被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,使得很多公司都采用 My SQL 数据库以降低成本。MySQL 数据库可以称得上是目前运行速度最快的SQL语言数据库之一。 除了具有许多其他数据库所不具备的功能外,MySQL 数据库还是一种完全免费的产品,用户可以直接通过网络下载MySQL数据库,而不必支付任何费用。   Nginx技术    Nginx (engine x) 是一个高性能的 HTTP和反向代理服务。Nginx是一个很强大的高性能 Web和反向代理服务,它具有很多非常优越的特性,时常用于服务端的反向代理和负载均衡。它的内存占用少,启动极快,高并发能力强。在连接高并发的情况下,Nginx是 Apache 服务不错的替代品。   步骤概述   一、安装DockerDocker 运行在 CentOS7 上,要求系统为64位、系统内核版本为 3.10 以上。通过 uname -r 命令查看当前的内核版本。二、只用Docker部署首先先把MySQL和Redis数据库跑起来部署Flask应用部署Nginx注意区分:Docker镜像是一个模版,Docker容器是一个实例,它可以被启动与关闭。三、Docker-Compose部署Docker-Compose可以很方便地通过一个文件构建多个镜像、启动多个容器。    智能云网   智能云网社区是华为专为开发者打造的“学习、开发、验证、交流”一站式支持与服务平台,该平台涵盖多领域知识。目前承载了云园区网络,云广域网络,数通网络开放可编程,超融合数据中心网络,数通网络设备开放社区共五个场景。为了响应广大开发者需求,还提供了开发者交流、API 体验中心、多媒体课件、SDK工具包、开发者工具以及远程实验室共六大工具,让开发者轻松开发。欢迎各位前来体验。>>戳我了解更多<<
  • [交流分享] 关于幂等性的学习笔记
    最基础的概念,什么是幂等性?幂等性:提交多次的情况下,结果都一样。比如数据库查询,可称为天然幂等性,即查询多次结果都一样,无需人为去做幂等性操作。但是update table set value=value+1 where id=1,每次执行的结构都会发生变化,不是幂等。inter into table(id,name)values(1,‘name’),如id不是主键或者没有唯一索引,重复操作上面的业务,会插入多条数据,不具备幂等性;所以我们在什么情景下需要确保幂等性呢?用户多次点击保存按钮用户保存成功后,返回上一页再次保存微服务相互调用,由于网络原因,导致请求失败解决方案一、token机制:1、根据业务场景,判断哪些业务存在幂等性问题,在执行业务之前先获取token,将token缓存止redis中2、调用业务接口时,将token携带过去,一般放在请求头,作为Auth认证3、服务器判断token是否存在于redis中,存在表示第一次请求,然后删除token,继续执行业务4、如果不存在,则表示反复操作,不执行业务逻辑,直接返回重复标志!结束风险性:业务执行前删除还是后删除token?如果是执行后删除,在业务执行中,未删除token,用户又点了请求进来,那么则无法保障幂等性。如果是执行前删除,在分布式下,用户快速请求2次,这时2个请求同时到redis去获取token,对比成功,同时删除,同时执行业务,那么也无法保障幂等性。so:使用执行前删除,在分布式情况下,获取,对比,删除必须确保原子性,所以要加分布式锁。二、加锁1、数据库锁select * from table where … for update2、业务层面加分布式锁将获取、对比、删除作为一个原子性的操作加锁,处理完成后释放锁,确保串行操作。三、约束数据库唯一约束:通过主键、唯一索引,确保无法重复新增同一笔数据,这就能确保幂等性
总条数:310 到第
上滑加载中