幸いですlog

redis简单尝试

redis简单尝试

description
redis基本类型、集群
Created
Jun 3, 2022 09:56 AM
Updated
Last updated June 4, 2022

数据类型

命令不区分大小写,而key是区分大小写的
  • string 字符
    • 最常用
      • set key value
      • get value
    • 如何同时获取多个键值
      • mset key value[key value ...]
      • mget key[key...]
    • 数值增减
      • 递增数字 incr key
      • 增加指定的整数 incrby key increment
      • 递减数值 decr key
      • 减少指定的整数 decrby key decrement
    • 获取字符串的长度 strlen key
    • 分布式锁
      • setnx key value
      • set key value[EX seconds] [Px milliseconds] [NX|XX]
      • Ex:key 在多少秒后过期
      • PX:key在多少毫秒后过期
      • NX:当Key不存在的时候,才创建key,效果等同于setnx
      • XX:当key存在的时候,覆盖key
    • 应用场景
      • 商品编号,订单编号采用incr 命令生产
      • 是否喜欢的文章
  • list 列表
    • 向列表左边添加元素 lpush key value[value...]
    • 向列表右边添加元素 rpush key value[value...]
    • 查看列表 lrange key start stop
    • 获取列表中元素的个数 llen key
    • 应用场景 微信文章订阅公众号
  • hash 散列
    • 对应Map<String,Map<Object,Object>>
    • 一次设置一个字段值 hset key field value
    • 一次获取一个字段值 hget key field
    • 一次设置多个字段值 hset key field value[field value ..]
    • 一次获取多个字段值 hget key field[fiela ..]
    • 获取所有字段值 hgetall key
    • 获取某个key内的全部数量 hlen
    • 删除一个key hdel
    • 应用场景购物车简单版
  • set 集合
    • 添加元素 sadd key member[member...]
    • 删除元素 srem key member[member...]
    • 获取集合中的所有元素 smembers key
    • 判断元素是否在集合中 sismember key member
    • 获取集合中的元素个数 scard key
    • 从集合中随机弹出一个元素,元素不删除 srandmember key[数字]
    • 从集合中随机弹出一个元素,出一个删一个 spop key[数字]
    • 集合运算
      • 差集 A-B sdiff key [key ...]
      • 交集 A∩B sinter key[key...]
      • 并集 A∪B sunion key [key...]
    • 应用场景
      • 抽奖小程序
      • 朋友圈点赞
      • 微博好友关注社交关系
        • 共同关注的人 交集
        • 我关注的人别人也关注了他。
      • qq内推可能认识的人 差集
  • zset(sorted set) 有序集合
    • 向有序集合中加入一个元素和该元素的分数
    • 添加元素 zadd key score member[score member...]
    • 按照元素分数从小到大顺序返回索引从start到stop之间的所有元素 zrange key start stop[withscore]
    • 获取元素的分数 zscore key member
    • 删除元素 zrem key member[member ...]
    • 获取指定分数范围的元素 zrangebyscoer key min max [withscore]
    • 添加某个元素的分数 zincrby key increment member
    • 获取集合中元素的数量 zcard key
    • 获得指定分数范围内的元素个数 zcount key min max
    • 按照排名范围删除元素 zremrangebyrank key start stop
    • 获取元素的排名
      • 从小到大 zrank key member
      • 从大到小 zrever key member
    • 应用场景
      • 根据商品销售对商品进行排序显示
      • 抖音热搜
  • bitmap 位图
  • HyperLogLog 统计
  • GEO 地理空间
  • Stream

分布锁

知道分布式锁嘛?有那些实现方案?

分布式微服务架构,拆分后各个微服务为了避免冲突和数据故障而加入的一种锁,分布式锁
解决方案
1、mysql
2、zookeeper
3、redis
redis---redlock===>redisson lock/unlock

服务加锁

单机版加锁

sychronized或者lock
设置超时时间的或用lock.trylock(1L,TimeUnit.单位)

Nginx负载均衡

/usr/local/nginx/conf nginx.conf
设置负载均衡
/usr/loacl/nginx/sbin/nginx -c/usr/loacl/nginx/conf/nginx.conf
./nginx -c/usr/local/nginx/conf/nginx.conf
  • 启动 /usr/local/nginx/sbin
  • 关闭 /usr/local/nginx/sbin ./nginx -s stop
  • 重启 ./nginx -s reload

分布式锁

1、
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value); if(!flag){    //抢锁失败 }
2、如果异常的话,可能无法释放锁,必须要在代码层面finally释放锁
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value); if(!flag){    //抢锁失败 } }finally{    stringRedisTemplate.delete(REDIS_LOCK) }
3、宕机了怎么解决,机器挂了代码走不到finally key没有办法删除
需要加入一个过期时间
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value); stringRedisTemplate.expire(REDIS_LOCK,10L,TimeUnit.SECONDS);//10秒过期 if(!flag){    //抢锁失败 } }finally{    stringRedisTemplate.delete(REDIS_LOCK) }
4、原子性怎么保证?
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value,10L,TimUnit.SECONDS); if(!flag){    //抢锁失败 } }finally{    stringRedisTemplate.delete(REDIS_LOCK) }
5、锁时间过期,误删其他的锁
notion image
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value,10L,TimUnit.SECONDS); if(!flag){    //抢锁失败 } }finally{    //加判断 是不是自己的锁    if(stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){        stringRedisTemplate.delete(REDIS_LOCK) } }
6、判断和delete不是原子性的,会造成误解锁
  • lua脚本解决
if redis.call("get",KEYS[1]==ARGV[1]) then    return redis.call("del",KEYS[1]) else    return 0; end
  • redis的事务
    • MULTI 标记事务块的开始
    • EXEC 事务中执行所有先前放入队列的命令,然后恢复正常的链接状态
    • DISCARD 所有先前在一个事务中放入队列的命令,然后恢复正常的链接状态
    • wacth 某个事务需要按条件执行时,就要使用这个命令将给定的建设为监控的状态 wacth key
    • unwacth 清空监控的建
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value,10L,TimUnit.SECONDS); if(!flag){    //抢锁失败 } }finally{  while(true){    stringRedisTemplate.watch(REDIS_LOCK);//标记为监听状态    //加判断 是不是自己的锁    if(stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){        stringRedisTemplate.setEnableTransactionSupport(true);//支持事务        stringRedisTemplate.muti();        stringRedisTemplate.delete(REDIS_LOCK);        List<Object> list=stringRedisTemplate.exec();//返回队列        if(list!=null){            continue;       } }    stringRedisTemplate.unwatch();//清楚监控    break; } }
7、redis池
String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); try{ Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK,value,10L,TimUnit.SECONDS); if(!flag){    //抢锁失败 } }finally{    Jedis jedis=RedisUtils.getJedis();    String script="if redis.call('get',KEYS[1])==ARGV[1]"        +"then"+        "return redis.call('del',KEYS[1])"+        "else"+        "return 0;"+"end"     try{         Object 0=jedis.eval(script,Collections.singletonList(REDIS_LOCK),Collections.singletonList(value));         if("1".equals(o.toString()){             //成功         }else{             //失败         }     }finally{         if(null!=jedis){             jedis.close();         }     } }
9、确保Redislock过期时间大于业务执行时间的问题
redis分布锁如何续期? 缓存续命机制
特性:AP
C:Consistency(强一致性)
A:Availability(可用性)
P:Partition tolerance(分区容错性)
AP:redis异步复制造成锁丢失
比如主节点没来得及把刚刚的set进来这条数据给从节点,就挂了
zookeperCP

Redisson

//配置 @Bean public Redisson redisson(){ Config config=new Config();    config,useSingleServer().setAddress("redis://192.168.111.147:6379").setDatabase(0);    return (Redission)Redisson.create(config); }
//分布式锁调优 private Redisson redisson; .... String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); RLock lock=redisson.getLock(REDIS_LOCK); lock.lock(); try{ //逻辑 if(!flag){    //抢锁失败 } }finally{    lock.unlock(); }
问题,不要直接写unlock(); //数据量过大时,会报解锁的线程不是要解锁的线程
//分布式锁调优 private Redisson redisson; .... String value=UUID.randomUUID().toString()+Thread.currentThread().getName(); RLock lock=redisson.getLock(REDIS_LOCK); lock.lock(); try{ //逻辑 if(!flag){    //抢锁失败 } }finally{    if(lock.isLocked()){//是加锁状态        if(lock.isHeldByCurrentThread){//是本线程持有             lock.unlock(); }   } }

redis缓存过期淘汰策略

  • Redis内存满了怎么办
    • 会报oom
  • 默认内存多少?在哪里查看? 怎么设置 怎么查看内存情况?
    • reids.config maxmemory参数 如果不设置 64不限制大小,32位3个G
      一般设置位最大内存的四分之三
      1、通过文件配置 2、命令配置 config set maxmemory 单位
      info memory
  • redis的淘汰策略 8个
    • 1、默认打满报错
    • 删除策略
      • 定时删除(对cpu不好,对内存好) 惰性删除(对内存不好,对cpu好),
        定期删除(每个一段时间执行一次,限制删除的时长和频率)
        notion image
设置 config set maxmemory-policy 策略

LRU算法 最近最少使用,常用搞得页面置换算法

redis,缓存
读+写两个操作。
命中
哈希链表

曾经也有 个和你一样的人来过这里。

「姿や形は問題ではなく、「魂」が問題です。」

Vercel Logo

「健全なる魂は健全なる精神と健全なる肉体に宿る。」

「あなたの魂、受け取りました。」

VercelVercel

Clover © 2022 幸いです 全著作権所有.