单个Redis实例下的锁正确使用姿势

解锁redis锁的正确姿势 redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为。这个时候我们就要用到锁。锁的方式有好几种,php不能在内存中用锁,不能使用zookeeper加锁,使用数据库做锁又消耗比较大,这个时候我们一般会选用redis做锁机制。 setnx 锁在redis中最简单的数据结构就是string。最早的时候,上锁的操作一般使用setnx,这个命令是当:... 阅读详情

一、前言

一年前,写了一篇有瑕疵的博文 Redis分布式锁原理及实现 。这篇博文最后虽然给出了redis实现分布式锁的方式,但是在并发相当高的情况下,比如Requests per second: 1453.85 [#/sec] (mean)情况下,如果出现了一次锁超时,那么,之后的请求会有极大的概率一直持续处在被锁的状态,即出现死锁。
经过不断查资料以及实践检测,最终,得出了Redis使用单个实例下锁的正确实现。

二、原理

有效方式使用分布式锁所需的最低保证:

  • 安全属性:相互排斥。在任何给定时刻,只有一个客户端可以持有锁。
  • 活力属性A:无死锁。最终,即使锁定资源的客户端崩溃或被分区,也始终可以获取锁定。
  • 活力属性B:容错。只要大多数Redis节点启动,客户端就能够获取和释放锁。

由于介绍的是单实例下的Redis锁,所以 活力属性B 暂不考虑。

获得锁定

要获得锁定,可以采用以下方法:

 SET resource_name my_random_value NX PX 30000

该命令仅在密钥尚不存在时才设置密钥(NX选项),到期时间为30000毫秒(PX选项)。密钥设置为“我的随机值”值。此值必须在所有客户端和所有锁定请求中都是唯一的。

以安全的方式释放锁

使用一个告诉Redis的脚本:仅当密钥存在且存储在密钥上的值恰好是我期望的值时才删除密钥。这是通过以下Lua脚本完成的:

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

这一点很重要,以避免删除由另一个客户端创建的锁。仅使用DEL是不安全的,因为客户端可能会删除另一个客户端的锁定。

三、java 实现

老话说得好,Talk is cheap ,show me the code! 接下来看看其java实现。

导入依赖并配置基础信息

导入依赖:

		<!--  本项目是  springboot 2.0.4.RELEASE 下得实现 -->
     	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

配置基础信息:

spring:
  redis:
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器地址
    host: 127.0.0.1
    # Redis服务器连接端口
    port: 6379
    # Redis 密码
    password: require_pass
    jedis:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 100
        # 连接池中的最大空闲连接
        max-idle: 500
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 2000
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 10000
    # 连接超时时间(毫秒)
    timeout: 0

配置JedisPool

新建类RedisConfig如下:


import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;
    
    @Value("${spring.redis.password}")
    private String auth;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;

    @Bean
    public JedisPool redisPoolFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        if(auth ==null || auth.equals("")){
        	return new JedisPool(jedisPoolConfig, host, port, timeout);
        }else{
        	return new JedisPool(jedisPoolConfig, host, port, timeout,auth);
        }
    }

}

核心加锁和解锁方法

创建以下抽象RedisService :

import cc.mrbird.common.domain.RedisInfo;

import java.util.List;
import java.util.Map;
import java.util.Set;

public interface RedisService {


    /**
     *  setnx expire
     * @param key
     * @param value
     * @param nxxx setnx
     * @param expx expire
     * @param time
     * @return
     */
    String set(String key, String value, String nxxx, String expx, int time);

    /**
     * 执行redis脚本
     * @param script  脚本
     * @param keys 键值
     * @param args 参数
     * @return
     */
    Object eval(String script, List<String> keys, List<String> args);
}

具体实现如下:

@Service("redisService")
public class RedisServiceImpl implements RedisService {

    @Autowired
    JedisPool jedisPool;


    /**
     * 处理jedis请求
     *
     * @param f 处理逻辑,通过lambda行为参数化
     * @return 处理结果
     */
    private Object excuteByJedis(Function<Jedis, Object> f) {
        try (Jedis jedis = jedisPool.getResource()) {
            return f.apply(jedis);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    } 

    @Override
    public String set(String key, String value, String nxxx, String expx, int time) {
        return (String) this.excuteByJedis(j -> j.set(key, value, nxxx, expx, time));
    }

    @Override
    public Object eval(String script, List<String> keys, List<String> args) {
        return this.excuteByJedis(j -> j.eval(script, keys, args));
    }
}

有了以上准备,下面就可以创建一个工具类,专门用来处理Redis锁,如下:

@Component
@Slf4j
public class RedisLockUtils {

    /**
     * 用来表示 setnx 的参数
     */
    private static final String SET_IF_NOT_EXIST = "NX";
    /**
     * EX = seconds(秒); PX = milliseconds(毫秒)
     */
    private static final String SET_WITH_EXPIRE_TIME = "EX";
    /**
     * 释放锁成功返回值
     */
    private static final Long RELEASE_SUCCESS = 1L;
    /**
     * 加锁成功返回值
     */
    private static final String LOCK_SUCCESS = "OK";
    /**
     * 超时时间 10s,单位是由 {@code SET_WITH_EXPIRE_TIME }
     */
    public static final int TIMEOUT = 10;

    /**
     * 常量前缀
     */
    private static final String REDIS_LOCK_KEY_PREFIX = "redis_lock_key_prefix";

    /**
     * 常量连接符
     */
    private static final String REDIS_LOCK_PLUS = "@";

    /**
     * 可用 key前缀
     */
    public static final String REDIS_LOCK_KEY = REDIS_LOCK_KEY_PREFIX + REDIS_LOCK_PLUS;

    @Autowired
    RedisService redisService;


    /**
     * 生成分布式锁密钥
     *
     * @param key
     * @return
     */
    public String generateLockKey(String key) {
        if (StringUtils.isBlank(key)) {
            return "";
        }
        return REDIS_LOCK_KEY + MD5Utils.encrypt(key);
    }


    /**
     * 尝试获取分布式锁
     *
     * @param lockKey    锁
     * @param requestId  请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功  true:成功获取锁;false:未获取锁资格
     */
    public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) {

        String result = redisService.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

    /**
     * 释放分布式锁
     *
     * @param lockKey   锁
     * @param requestId 请求标识
     * @return 是否释放成功  true:手动解锁成功;false:手动解锁失败
     */
    public boolean releaseDistributedLock(String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = redisService.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        log.info("解锁失败,解锁用户:{}, 锁值为:{}", requestId, lockKey);
        return false;
    }

}

到这,就可以愉快得撸代码了。

四、拓展

以上方法实现的redis锁,每次只有一个用户占用锁资源,这样会照成当一个用户A获取锁执行业务逻辑时,其他的用户都不能执行这块的业务逻辑,只有当A执行完成后,其他用户再次请求过来时,才有机会和获取到锁资格去执行相应的业务逻辑。

下面我有一个业务场景,比如发红包,如果用上面这样的锁机制,先点击“抢红包”按钮的用户,也不一定能比后点击“抢红包”按钮的用户先抢到红包。因为先点击的用户可能此时锁正被占用,而后点击的后点击的用户 可能这时候锁正好释放被他给碰上了。所以这样情况,以上的锁机制是不符合这个抢红包的逻辑的。

那么应该怎么办呢???其实也很简单。利用redis的单线程特性和其api中的 DECR 或是INCR可以实现。

下面来看一看基础 命令:

INCR key

简述:

  • 为键 key 储存的数字值加上一。

  • 如果键 key 不存在, 那么它的值会先被初始化为 0 , 然后再执行 INCR 命令。

  • 如果键 key 储存的值不能被解释为数字, 那么 INCR 命令将返回一个错误。

  • 本操作的值限制在 64 位(bit)有符号数字表示之内。

  • INCR 命令是一个针对字符串的操作。 因为 Redis 并没有专用的整数类型, 所以键 key 储存的值在执行 INCR 命令时会被解释为十进制 64 位有符号整数。

返回值: INCR 命令会返回键 key 在执行加一操作之后的值。

代码示例:

redis> SET page_view 20
OK

redis> INCR page_view
(integer) 21

redis> GET page_view    # 数字值在 Redis 中以字符串的形式保存
"21"

DECR key

简述:

  • 为键 key 储存的数字值减去一。

  • 如果键 key 不存在, 那么键 key 的值会先被初始化为 0 , 然后再执行 DECR 操作。

  • 如果键 key 储存的值不能被解释为数字, 那么 DECR 命令将返回一个错误。

  • 本操作的值限制在 64 位(bit)有符号数字表示之内。

返回值: DECR 命令会返回键 key 在执行减一操作之后的值。

代码示例:
对储存数字值的键 key 执行 DECR 命令:

redis> SET failure_times 10
OK

redis> DECR failure_times
(integer) 9

对不存在的键执行 DECR 命令:

redis> EXISTS count
(integer) 0

redis> DECR count
(integer) -1

测试

在上面的RedisServiceImpl 类中添加一个方法:

    public Long incr(String key) {
        return (Long)this.excuteByJedis(j -> j.incr(key));
    }

测试方法逻辑如下:

    public String testIncr() {
        long tmp = 0;
        if ((tmp = redisService.incr("numkey")) > 100) {  //100是红包数量,假定限制只能 发100个

            return "已经发完了!!!";
        }

        System.out.println("第" + tmp + “抢到红包的幸运儿!”) ;
        return "成功发出一个红包!";
    }

这样处理后,那么可以保证先点击的前一百个用户可以抢到红包,后面点击的用户则不会抢到红包了。

ps:你也可以使用 DECR 执行减法操作来计数,同时还可以利用set方法设置一个初值,并给定一个红包过期时间,留给读者发挥,这里就不赘述了。

参考文档:

告别手动标注!用ENVI Classic高效搞定高光谱图像语义分割标签(以农业/地物分类为例) 本文详细介绍了如何利用ENVI Classic实现高光谱图像的半自动化智能标注,特别针对农业和地物分类场景。通过光谱特征分析、智能标注技巧和MAT文件转换,显著提升标注效率和质量,助力AI模型训练。 阅读详情

相关推荐

Excel VBA+Adobe Acrobat Pro PDF发票识别全流程(附避坑指南)

本文详细介绍了如何利用Excel VBA与Adobe Acrobat Pro的API接口,构建一套企业级PDF发票智能识别与处理系统。内容涵盖从环境配置、核心文本提取原理、数据解析清洗到工程化脚本设计的全流程,并针对密码区干扰、不征税发票等常见问题提供避坑指南,旨在帮助财务人员和开发者实现高效、精准的财务数据处理自动化。

weixin_29207439的博客 347

redis加锁和解锁

本文章用于自己学习的操作 加锁 //调用加锁 boolean lock = redisService.getLock(resourceInfoId.toString(), String.valueOf(Thread.currentThread().getId())); if (lock == false) { return new FebsResponse().fail().message("当前资源正在审核中,请勿重复提交!"); }

w18973572056的博客 2639

Ubuntu下Vim创建属于自己的头部注释和代码模板

痛点 每次打开vim想写个C或者C++的程序都要把固定的模板敲一遍,是不是感觉非常的繁琐,能不能把Vim弄得像IDE那样新建一个文件直接生成对应的头部注释和代码模板,减少这些重复工作呢?下面我尽量详细的介绍实现的方法: 先看看新建文件后的效果 C语言格式效果 C++语言效果 方法: 使用命令 vi /etc/vim/vimrc 打开vimrc这个文件,然后复制以下代码至文件末尾的空白处即可! 修改vimrc文件里面的内容必须要用root管理员身份才能进行修改,修改时先切换至root身份即可。 "新建.

weixin_42137584的博客 1561

Redis分布式锁的手动实现

redis分布式锁的手动实现

于琦海 1697

睿尔曼超轻量仿人机械臂--机械臂接口介绍

本文介绍了睿尔曼超轻量仿人机械臂的控制器接口及末端接口。

realman_Rop的博客 3437

电路设计仿真软件:Mentor Graphics_(1).MentorGraphics电路设计仿真软件概述

菜单栏:包含文件、编辑、视图、工具等菜单。工具栏:提供常用的工具按钮,如打开、保存、仿真等。原理图编辑区:用于绘制电路原理图。元件库:包含各种电路元件,支持拖拽操作。属性面板:显示选中元件的属性,可以进行参数设置。仿真控制区:用于设置仿真参数和控制仿真过程。输出窗口:显示仿真结果和日志信息。打开模型编辑器:点击“工具”菜单,选择“模型编辑器”。选择模型类型:在模型编辑器中选择模型类型,如SPICE模型。输入模型参数:根据需要输入模型的参数,如电阻值、电容值等。保存模型。

kkchenjj的博客 1924

redis代码封装,及分布式锁实现

package com.smallrig.srm.redis; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; /** * @version 1.0.0 * @aurhor chencl * @date 2020/4/28 0028 * @描述: redis缓存服务端接口 */ public interface RedisService { void .

qq_42093488的博客 481

uniapp [全端兼容] - 详细实现人脸识别和活体检测功能,实时监测人脸是否进入区域及动作是否正确播报,免费自动提示引导动作及语音,提供提供实名认证、身份证识别、人脸信息采集、刷脸扫脸认证示例代码

uniapp,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,人脸识别,扫脸认证,人脸认证,活体认证,身份认证,uni-app人脸识别详细教程,如何在app端实现免费人脸识别教程,如何在小程序端做,最好用的插件,安卓ios百度人脸识别、活体检测、人脸采集APP,H5人脸识别带前后摄像头,适合新手看的人脸识别功能教程,详细示例代码源码,有没有免费的,接入百度,阿里云人脸识别,百度,api,活体检测,数据采集,动作提示指引,语音提示指引,报错,无法核验一直出错,根本用

🏆 前端领域优质创作者 1万+

redis实现分布式锁

redis实现分布式锁

落叶 555

Android功耗系列专题分析之四:待机概率性功耗高的失效分析

本文分析了Android设备待机功耗异常高的问题。通过日志发现系统休眠失败,原因是PowerManagerService.Display唤醒锁未被释放。进一步排查发现,指纹解锁功能在灭屏时未正确释放屏幕锁定,导致DisplayReady状态异常。解决方案是将指纹功能的背光控制与DisplayReady状态控制分离,使用两个变量独立管理。经验表明,快速定位问题比解决问题更重要,修改原生流程时需谨慎评估风险。

451

FPGA&ASIC笔面试题(四):编写Verilog代码描述跨时钟域信号传输,快时钟域到慢时钟域(补充)

      跨时钟域处理从快时钟域到慢时钟域,如果是下面第一个图,cklb则可以采样到signal_a_in,但是如果只有单脉冲,如第二个图,则不能确保采样掉signal_a_in。这个时候用两级触发器同步是没有用的。 代码如下: //Synchronous module Sync_Pulse( input clka, input clkb, input rst_n, input pulse_ina, output pulse_outb, ou

千歌叹尽执夏的博客 2510

Redis的正确使用姿势

前言 说到分布式缓存,可能大多数人脑海浮现的就是redis了,为什么redis能够在竞争激烈的缓存大战中脱颖而出呢?原因无非有一下几点:性能好,丰富的特性跟数据结构,api操作简单。但是用的人多了,就会出现很多不规范或者疏忽的地方,严重的时候甚至会导致生产事故,所以我们有必要来聊聊在Redis使用过程中的一些“正确姿势“。 切忌裸奔 大家别笑... 很多初学者或者没经验的开发...

深夜里的程序猿 3万+

通过WorkVisual连接KUKA机器人的具体方法

通过WorkVisual连接KUKA机器人的具体方法

Robot_PLC_HMI_Automation 6843

使用redis锁的正确姿势

redis锁的使用方式一般有三种,INCR,SETNX,SET。 1.INCR INCR命令会将key的值加一,如果key值不存在,则key值会被初始化为0,然后执行INCR操作。 127.0.0.1:6379> GET LOCK_1234 (nil) 127.0.0.1:6379> INCR LOCK_1234 (integer) 1 127.0.0.1:6379> GET LOCK_1234 "1" 利用INCR命令,结合程序构建锁,具体使用逻辑如下: 1)创建程序中需要加

xiaohei_xiaobai的博客 924

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Redis分布式锁的正确使用姿势

分布式锁在日常开发中,用处非常的多。包括但不限于抢红包,秒杀,支付下单,幂等,等等场景。分布式锁的实现方式有多种,包括redis实现,mysql实现,zookeeper实现等等。而其中redis非常适合作为分布式锁使用,并且在各个公司都大规模的使用。本文将由浅入深的探究Redis分布式锁的实现,最终实现一个可工业使用的Redis分布式锁。欢迎大家一步一步跟读,一起学习一起进步。分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。

javallllllllllll的博客 1631

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

掌握Redis分布式锁的正确姿势

前言 在Java中,我们对于锁会比较熟悉,常用的有 synchronized、Lock锁,在java并发编程中,我们通过锁,来实现当多个线程竞争同一个共享资源或者变量而造成的数据不一致的问题,但是JVM锁只能针对于单个应用服务,随着我们业务的发展需要,单体单机部署的系统早已演化成分布式系统,由于分布式系统的多线程、多进程而且分布在不同的机器上,这个时候JVM锁的并发控制就没有效果了,为了解决跨JVM锁并且能够控制共享资源的访问,于是有了分布式锁的诞生。 为什么JVM锁在分布式下不可以呢? 我们通过代码来.

牧小农 4024

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

单个Redis实例下的锁的使用

一、前言 一年前,写了一篇有瑕疵的博文 Redis分布式锁原理及实现 。这篇博文最后虽然给出了redis实现分布式锁的方式,但是在并发相当高的情况下,比如Requests per second: 1453.85 [#/sec] (mean)情况下,如果出现了一次锁超时,那么,之后的请求会有极大的概率一直持续处在被锁的状态,即出现死锁。 经过不断查资料以及实践检测,最终,得出了Redis使用单个实例...

Feng_dian的博客 569

Redis锁的使用姿势

考虑到redis主从同步集群中,如果从master获取到锁之后,就故障换成了从节点,那么就会导致锁失效,因此提出了RedLock的分布式锁算法。该算法依赖于这样的假设:虽然进程之间没有同步时钟,但每个进程中的本地时间几乎以相同的速率更新,与锁的自动释放时间相比,误差很小。在上述锁中,存在一个问题——如果A获取了锁,但是由于执行时间过长,导致B也获取到过期后的锁,此时并会同时存在多方获取锁。以下是删除特定value的锁的lua脚本,这样就可以防止删除不属于自己的锁。在锁竞争比较激烈情况下,性能损耗较大。

iUcool的博客 513

photozoompro 8 解锁代码_解锁redis锁的正确姿势

redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为。这个时候我们就要用到锁。锁的方式有好几种,php不能在内存中用锁,不能使用zookeeper加锁,使用数据库做锁又消耗比较大,这个时候我们一般会选用redis做锁机制。setnx锁在redis中最简单的数据结构就是string。最早的时候,上锁的操作一般使用setnx,这个命令是当:lock...

weixin_39944515的博客 1万+

redis 6.X 正确使用姿势

标题redis 1 官网 https://redis.io/ http://www.redis.cn/ http://doc.redisfans.com/ 2 配置文件 6.0.8版本 安装后需要修改配置文件 1 修改daemonize 改为 daemonize yes 2 修改protected-mode yes 改为 protected-mode no 3 注释掉 #bin 127.0.0.1 3 redis单线程&多线程问题 redis 是单线程还是多线程 - redis的版本有很多3.

weixin_39304711的博客 1218

解锁 redis 锁的正确姿势

redis 是 php 的好朋友,在 php 写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为。这个时候我们就要用到锁。锁的方式有好几种,php 不能在内存中用锁,不能使用 zookeeper 加锁,使用数据库做锁又消耗比较大,这个时候我们一般会选用 redis 做锁机制。 setnx 锁在 redis 中最简单的数据结构就是 string。最早的时候,上...

weixin_30855099的博客 275

Spring Boot 中 Redis 分布式锁的正确使用姿势,我后悔没早知道

分布式锁是微服务架构中的必备技能,用错了轻则数据重复,重则资金损失。用成熟的框架:别自己造轮子,Redisson 已经处理了大部分边界情况注意锁的粒度:key 设计要足够细,避免影响并发性能做好失败降级:获取不到锁时要有兜底方案,别把所有请求都堵死希望这篇文章能帮你们少踩坑。相关推荐Redisson 官方文档Redis 分布式锁详解。

聚焦学生开发者需求,分享课设毕设项目实战经验、系统开发技巧、数据库设计规范及文档排版实用方法。 1146

解锁 Redis 锁的正确姿势

这里的token是一个随机数,当lock的时候,往redis的my:lock中存的是这个token,unlock的时候,先get一下lock中的token,如果和我要删除的token是一致的,说明这个锁是之前我set的,否则的话,说明这个锁已经过期,是别人set的,我就不应该对它进行任何操作。比如,这个锁我上了10s,但是我处理的时间比10s更长,到了10s,这个锁自动过期了,被别人取走了,并且对它重新上锁了。获取锁的机制是对了,但是删除锁的机制直接使用del是不对的。因为有可能导致误删别人的锁的情况。

minihuabei的博客 330

Redis实现分布式锁的正确姿势

一、前言   在我们日常工作中,除了Spring和Mybatis外,用到最多无外乎分布式缓存框架——Redis。但是很多工作很多年的朋友对Redis还处于一个最基础的使用和认识。所以我就像把自己对分布式缓存的一些理解和应用整理一个系列,希望可以帮助到大家加深对Redis的理解。本系列的文章思路先从Redis的应用开始。再解析Redis的内部实现原理。最后以经常会问到Redist相关的面试题为结尾...

南风不竞的专栏 201
上一篇: oracle使用日常总结
下一篇: redis 任何命令都执行不了,抛错 NOAUTH Authentication required
She_lock
博客等级 码龄12年 157粉丝 134原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值