首页 > 数据库 >分布式锁-redis

分布式锁-redis

时间:2023-11-26 17:32:15浏览次数:27  
标签:poolConfig String int redis host null public 分布式

package redis.clients.jedis;

import java.net.URI;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.JedisURIHelper;
import redis.clients.util.Pool;

public class JedisPool extends Pool<Jedis> {
    public JedisPool() {
        this((String)"localhost", 6379);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host) {
        this(poolConfig, host, 6379, 2000, (String)null, 0, (String)null);
    }

    public JedisPool(String host, int port) {
        this(new GenericObjectPoolConfig(), host, port, 2000, (String)null, 0, (String)null);
    }

    public JedisPool(String host) {
        URI uri = URI.create(host);
        if (JedisURIHelper.isValid(uri)) {
            String h = uri.getHost();
            int port = uri.getPort();
            String password = JedisURIHelper.getPassword(uri);
            int database = JedisURIHelper.getDBIndex(uri);
            boolean ssl = uri.getScheme().equals("rediss");
            this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 2000, 2000, password, database, (String)null, ssl, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
        } else {
            this.internalPool = new GenericObjectPool(new JedisFactory(host, 6379, 2000, 2000, (String)null, 0, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
        }

    }

    public JedisPool(String host, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        URI uri = URI.create(host);
        if (JedisURIHelper.isValid(uri)) {
            String h = uri.getHost();
            int port = uri.getPort();
            String password = JedisURIHelper.getPassword(uri);
            int database = JedisURIHelper.getDBIndex(uri);
            boolean ssl = uri.getScheme().equals("rediss");
            this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 2000, 2000, password, database, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier), new GenericObjectPoolConfig());
        } else {
            this.internalPool = new GenericObjectPool(new JedisFactory(host, 6379, 2000, 2000, (String)null, 0, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null), new GenericObjectPoolConfig());
        }

    }

    public JedisPool(URI uri) {
        this(new GenericObjectPoolConfig(), (URI)uri, 2000);
    }

    public JedisPool(URI uri, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(new GenericObjectPoolConfig(), uri, 2000, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(URI uri, int timeout) {
        this(new GenericObjectPoolConfig(), uri, timeout);
    }

    public JedisPool(URI uri, int timeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(new GenericObjectPoolConfig(), uri, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password) {
        this(poolConfig, host, port, timeout, password, 0, (String)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, boolean ssl) {
        this(poolConfig, host, port, timeout, password, 0, (String)null, ssl);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, host, port, timeout, password, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port) {
        this(poolConfig, host, port, 2000, (String)null, 0, (String)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, boolean ssl) {
        this(poolConfig, host, port, 2000, (String)null, 0, (String)null, ssl);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, host, port, 2000, (String)null, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout) {
        this(poolConfig, host, port, timeout, (String)null, 0, (String)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, boolean ssl) {
        this(poolConfig, host, port, timeout, (String)null, 0, (String)null, ssl);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, host, port, timeout, (String)null, 0, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database) {
        this(poolConfig, host, port, timeout, password, database, (String)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, boolean ssl) {
        this(poolConfig, host, port, timeout, password, database, (String)null, ssl);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, host, port, timeout, password, database, (String)null, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName) {
        this(poolConfig, host, port, timeout, timeout, password, database, clientName, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName, boolean ssl) {
        this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int timeout, String password, int database, String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, host, port, timeout, timeout, password, database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, String host, int port, int connectionTimeout, int soTimeout, String password, int database, String clientName, boolean ssl, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password, database, clientName, ssl, sslSocketFactory, sslParameters, hostnameVerifier));
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri) {
        this(poolConfig, (URI)uri, 2000);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, uri, 2000, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int timeout) {
        this(poolConfig, uri, timeout, timeout);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int timeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        this(poolConfig, uri, timeout, timeout, sslSocketFactory, sslParameters, hostnameVerifier);
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int connectionTimeout, int soTimeout) {
        super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, (String)null, false, (SSLSocketFactory)null, (SSLParameters)null, (HostnameVerifier)null));
    }

    public JedisPool(GenericObjectPoolConfig poolConfig, URI uri, int connectionTimeout, int soTimeout, SSLSocketFactory sslSocketFactory, SSLParameters sslParameters, HostnameVerifier hostnameVerifier) {
        super(poolConfig, new JedisFactory(uri, connectionTimeout, soTimeout, (String)null, uri.getScheme() != null && uri.getScheme().equals("rediss"), sslSocketFactory, sslParameters, hostnameVerifier));
    }

    public Jedis getResource() {
        Jedis jedis = (Jedis)super.getResource();
        jedis.setDataSource(this);
        return jedis;
    }

    /** @deprecated */
    @Deprecated
    public void returnBrokenResource(Jedis resource) {
        if (resource != null) {
            this.returnBrokenResourceObject(resource);
        }

    }

    /** @deprecated */
    @Deprecated
    public void returnResource(Jedis resource) {
        if (resource != null) {
            try {
                resource.resetState();
                this.returnResourceObject(resource);
            } catch (Exception var3) {
                this.returnBrokenResource(resource);
                throw new JedisException("Could not return the resource to the pool", var3);
            }
        }

    }
}

 

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisUtil {

    private JedisPool jedisPool;

    public void initPool(String host,int port ,int database){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(200);
        poolConfig.setMaxIdle(30);
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setMaxWaitMillis(10*1000);
        poolConfig.setTestOnBorrow(true);
        jedisPool=new JedisPool(poolConfig,host,port,20*1000);
    }

    public Jedis getJedis(){
        Jedis jedis = jedisPool.getResource();
        // 正确释放资源

        return jedis;
    }

}
public PmsSkuInfo getskuById(String skuId, String remoteAddr) {
        System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入商品详情页面");
        PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
        // 链接缓存
        Jedis jedis = redisUtil.getJedis();
        // 查询缓存
        String skuKey = "sku:" + skuId + ":info";
        String skuJson = jedis.get(skuKey);

        if (StringUtils.isNotBlank(skuJson)) {//if(skuJson!=null&&!skuJson.equals(""))
            System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入缓存");
            pmsSkuInfo = JSON.parseObject(skuJson, PmsSkuInfo.class);
        } else {
            System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"进入开始查询数据库");
            // 如果缓存中没有,查询mysql

            // 设置分布式锁
            String token = UUID.randomUUID().toString();
            String OK = jedis.set("sku:" + skuId + ":lock", token, "nx", "px", 10*1000);
            //拿到锁就查询
            if(StringUtils.isNotBlank(OK)&&OK.equals("OK")){
                System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"拿到锁");
                pmsSkuInfo = getItemInfoById(skuId);

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if (pmsSkuInfo != null) {

                    // mysql查询结果存入redis
                    jedis.set("sku:" + skuId + ":info", JSON.toJSONString(pmsSkuInfo));

                }else {
                    System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"查询null");
                    //数据库不存在就设置空/null给redis,防止数据库穿透
                    jedis.setex("sku:"+skuId+":info",60*3,JSON.toJSONString(""));

                }
                System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"释放锁");
                //释放锁  根据key匹配vulue,匹配上了就删除锁(防止误删其他线程的锁)

                  String lockToken = jedis.get("sku:" + skuId + ":lock");
//                if(StringUtils.isNotBlank(lockToken)&&lockToken.equals(token)){
//                    jedis.del("sku:" + skuId + ":lock");
//                }
                //对比防重删令牌 lua
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                  jedis.eval(script, Collections.singletonList(lockToken),
                        Collections.singletonList(token));



            }else {
                //没拿到锁就自旋
                System.out.println("ip为"+remoteAddr+"的帅哥美女"+Thread.currentThread().getName()+"开始自旋");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return getskuById(skuId, remoteAddr);
            }


        }
        jedis.close();
        return pmsSkuInfo;
    }

-----------------------------模板

public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
        String cates = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
        if (StringUtils.isNotBlank(cates)){
            return JSON.parseArray(cates,CategoryVO.class);
        }
         //开始分布式锁
        List<CategoryVO> categoryVOS =null;
        //唯一标识  防止等会误删锁
        String uuid= UUID.randomUUID().toString();
        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 3, TimeUnit.MINUTES);
        if (ifAbsent){
            //查询数据库
            categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
            //存入redis   没有判空,防止缓存穿透(存空值)                                                 设置随机过期时间,防止缓存雪崩
            redisTemplate.opsForValue().set(KEY_PREFIX + parentCid,JSON.toJSONString(categoryVOS),5+new Random().nextInt(5), TimeUnit.DAYS);
            //释放锁 del
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            //获取唯一标识
            String lock = redisTemplate.opsForValue().get("lock");
            //执行删除
            this.redisTemplate.execute(new DefaultRedisScript<>(script), Arrays.asList(lock), Arrays.asList(uuid));
        }else {
            // 每隔1秒钟回调一次,再次尝试获取锁
            try {
                Thread.sleep(500);
                return queryCategoryByPidCategoryVO(parentCid);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return categoryVOS;
    }

 ----------------------------------------------redisson推荐-----------------------

public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
    //判断缓存是否存在
    String cates = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
    if (StringUtils.isNotBlank(cates)){
        return JSON.parseArray(cates,CategoryVO.class);
    }
     //开始分布式锁
    RLock lock = redissonClient.getLock("lock" + parentCid);//只锁当前进入的parentCid
    lock.lock();
    //判断缓存是否存在
    String cates02 = redisTemplate.opsForValue().get(KEY_PREFIX + parentCid);
    if (StringUtils.isNotBlank(cates02)){
        lock.unlock();//释放锁
        return JSON.parseArray(cates02,CategoryVO.class);
    }
        //查询数据库
        List<CategoryVO> categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
        //存入redis   没有判空,防止缓存穿透(存空值)                                                 设置随机过期时间,防止缓存雪崩
        redisTemplate.opsForValue().set(KEY_PREFIX + parentCid,JSON.toJSONString(categoryVOS),5+new Random().nextInt(5), TimeUnit.DAYS);
    lock.unlock();//释放锁

    return categoryVOS;
}

 --------------------------抽取    注解+Aop-----------------------------------------------------------------

import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonCache {

    //相互等价 value=prefix
    @AliasFor("prefix")
    String value() default "";

    // 缓存中key的前缀
    @AliasFor("value")
    String prefix() default "";

    // 过期时间 单位:分
    int timeout() default 5;

    // 随机时间 单位:分
    int random() default 5;
}
import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.index.annotation.RedissonCache;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class RedissonAop {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 1.返回值object
     * 2.参数proceedingJoinPoint
     * 3.抛出异常Throwable
     * 4.proceedingJoinPoint.proceed(args)执行业务方法
     */
    @Around("@annotation(com.atguigu.gmall.index.annotation.RedissonCache)")
    public Object cacheAroundAdvice(ProceedingJoinPoint point) throws Throwable {

        Object result =null;

        // 获取连接点签名
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        // 获取连接点的RedissonCache注解信息
        RedissonCache annotation = methodSignature.getMethod().getAnnotation(RedissonCache.class);
        // 获取缓存的前缀
        String prefix = annotation.prefix();
        //获取目标方法的参数列表
        Object[] args = point.getArgs();
        // 组装成key
        String key = prefix + Arrays.asList(args).toString();
        // 1. 查询缓存
        result = this.cacheHit(methodSignature, key);
        if (result!=null){
            return result;
        }
        // 初始化分布式锁
        RLock lock = redissonClient.getLock("lock" + Arrays.asList(args).toString());
        lock.lock(); // 防止缓存穿透 加锁
        // 再次检查内存是否有,因为高并发下,可能在加锁这段时间内,已有其他线程放入缓存
        result= this.cacheHit(methodSignature, key);
        if (result != null) {
            lock.unlock();
            return result;
        }
        // 2. 执行查询的业务逻辑从数据库查询
         result = point.proceed(point.getArgs());
        // 并把结果放入缓存
        int timeout = annotation.timeout();
        int random = annotation.random();
        this.redisTemplate.opsForValue().set(key, JSON.toJSONString(result),timeout+(int)(Math.random()*random), TimeUnit.MINUTES);

        // 释放锁
        lock.unlock();

        return result;

    }
    /**
     * 查询缓存的方法
     *
     * @param signature
     * @param key
     * @return
     */
    private Object cacheHit(MethodSignature signature, String key) {
        // 1. 查询缓存
        String cache = this.redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(cache)) {
            // 有,则反序列化,直接返回
            Class returnType = signature.getReturnType(); // 获取方法返回类型
            // 不能使用parseArray<cache, T>,因为不知道List<T>中的泛型
            return JSON.parseObject(cache, returnType);
        }
        return null;
    }


}
@RedissonCache(prefix = "index:cates",timeout = 6,random = 10)
 public List<CategoryVO> queryCategoryByPidCategoryVO(Long parentCid) {
        //判断缓存是否存在

         //开始分布式锁

        //判断缓存是否存在

            //查询数据库
            List<CategoryVO> categoryVOS = pmsClient.queryCategoryByPidCategoryVO(parentCid).getData();
            //存入redis   没有判空,防止缓存穿透(存空值)                                                 设置随机过期时间,防止缓存雪崩

        return categoryVOS;
    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参考:https://github.com/redisson/redisson/wiki

标签:poolConfig,String,int,redis,host,null,public,分布式
From: https://blog.51cto.com/u_16253752/8571489

相关文章

  • redis基础命令复习(Sring,Hash,List,Set,SortedSet)
    1,Redis数据结构:  https://redis.io/commands  2,Redis命令---Redis通用命令(常见的有,keys,del,exists,expire,ttl)2.1,keys:查看符合模板的所有key,不建议在生产环境设备上使用 打开redis:win+R,输入cmd,打开命令提示符后,输入redis-server;  再另外打开一个命令提示......
  • node连接redis基础用法
     //*************redis基础用法**********************///1.导入redis,最好是下载3版本constredis=require('redis')//2.创建客户端constcli=redis.createClient({host:'localhost',port:6379})/***3.设置数据库*参1:k值*参2:v值*参3:'ex'|&#......
  • 关于点赞业务对MySQL和Redis和MongoDB的思考
    点赞​ 在我个人理解中,点赞业务比较频繁,很多人业务可能都会有这个,比如:博客,视频,文章,动态,评论等,但是不应该是核心业务,不应该大量地请求MySQL数据库,给数据库造成大量的资源消耗,MySQL的数据库是非常宝贵的.以某音为例,当我去搜索的时候,全抖音比较高的点赞数目应该是在1......
  • 01Redis的安装与配置(新手必备)
    第2章Redis的安装与配置 2.1Redis的安装2.1.1克隆并配置主机Redis在Linux上进行安装,首先有配置Linux操作系统2.1.2安装前的准备工作(1)安装gcc由于Redis是由C/C++语言编写的,而从官网下载的Redis安装包是需要编译后才可安装的,所以对其进行编译就必须要使......
  • Redis持久化
    Redis持久化RDB持久化实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为RDB文件(dump.rdb),其中,RDB就是RedisDataBase的缩写。在指定的时间间......
  • redis
        无序集合:set                          有序集合:set ......
  • 写写Redis十大类型bitmap的常用命令
    其实这些命令官方上都有,而且可读性很强,还有汉化组翻译的http://redis.cn/commands.html,不过光是练习还是容易忘,写一写博客记录一下bitmap位图,是由0和1状态表现的二进制bit数组,bitmap是由string作为底层数据结构,本质就是一个数组应用场景:用户签到,视频是否播放,是否登录过,钉钉打卡......
  • 谨防利用Redis未授权访问漏洞入侵服务器
    说明:Redis是一个开源的,由C语言编写的高性能NoSQL数据库,因其高性能、可扩展、兼容性强,被各大小互联网公司或个人作为内存型存储组件使用。但是其中有小部分公司或个人开发者,为了方便调试或忽略了安全风险,没有设置密码并直接对外开放了6379端口,那么这就是一个危险的行为。漏洞成......
  • 写写Redis十大类型zset的常用命令
    其实这些命令官方上都有,而且可读性很强,还有汉化组翻译的http://redis.cn/commands.html,不过光是练习还是容易忘,写一写博客记录一下从zset类型开始写||zset类型适合做排行榜,score排行后显示member应用场景:商品销售的排序zaddkeyscoremember[keymember]//这里和sadd不同的......
  • 科普:多领域分布式协同仿真
    分布式协同仿真是一种在分布式计算环境中进行协同工作的仿真方法。使用该方法进行协同仿真时,仿真任务将被分发到多个计算节点上,并且这些节点可以同时工作以模拟完整的系统行为。分布式协同仿真已被广泛应用于工程、科学和军事领域,以便更好地模拟和理解大规模和复杂系统的行为。分......