redis

redis学习

redis通用命令:
	help :获取帮助信息
	help @group:获取复杂数据结构的操作命令
	help exists:查看exists用法
	
	key的层级名称:
		便于区分同类型不同意义的字段
		key:  项目名:业务名:类型:id  value:json字符串

redis六种基本数据结构

  1. ​ String

    set:添加或者修改已经存在的string类型的键值对
    get:根据key获取string类型的value
    mset:批量添加多个string类型的键值对
    mget:根据多个key获取多个string类型的value
    incr:让一个value为整型的key自增1
    incrby:让一个value整型的key自增并指定步长
    incrbyfloat:让一个浮点类型的数字自增并指定步长
    setnx:添加一个string类型的键值对,前提是这个key不存在,否则不执行
    setex:添加一个string类型的键值对,并指定有效期
    
  2. hash

hset key field value:添加或者修改hash类型key的field的值
hget key field:获取一个hash类型key的field的值
hmset:批量添加多个hash类型key的field的值
hmget:批量获取多个hash类型key的field的值
hgetall:获取一个hash类型的key中的所有field和value
hkeys:获取一个hash类型的key中的所有field
hvals:获取一个hash类型中key中所有的value
hincrby:让一个hash类型key的字段值自增并指定步长
hsetnx:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行
  1. list

    朋友圈点赞列表或者评论列表
    lpush key element:向列表左侧插入一个或多个元素
    lpop key:移除或返回列表左侧的第一个元素
    lrange key star end:返回一段角标范围内的所有元素
    Rpush key element:向列表右侧插入一个或多个元素
    rpop key:移除并返回列表右侧的第一个元素
    Blpop和brpop:与lpop和rpop类似,只不过在没有元素时等待指定时间,而不是直接返回nil
    
  2. set

    集合操作:共同好友共同关注
    sadd key member:向set中添加一个元素
    srem key member:移除set中的指定元素
    scard key:返回set中的元素的个数
    sismember key member:判断一个元素是否存在set中
    smembers:获取set中的所有元素
    sinter key1 key2:求key1与key2的交集
    sdiff key1 key2:求key1与key2的差集
    sunion key1 key2:求key1与key2的并集
    
  3. sortedset

    zadd key score member:添加一个或多个元素到sorted set,如果已经存在则更新score值
    zrem key member:删除sortedset中的一个指定元素
    zscore key member:获取sortedset中的指定元素的score值
    zrank key member:获取sortedset中指定元素的排名
    zcard key:获取sortedset中元素的个数
    zcount key min max:统计score值在给定范围内的所有元素的个数
    zincrby key increment member:让sortedset中指定元素自增,步长为指定的increment值
    zrange key min max:按照score排序后,获取指定排名范围内的元素
    zdiff zinter zunion:差集,交集,并集
    

    redis的java客户端

    jedis:已redis命令作为方法名,学习成本低。但是jedis实例是线程不安全的,多线程环境下需要基于连接池来使用
    lettuce:lettuce是基于netty实现的,支持同步,异步和响应式编程方式,并且是线程安全的,支持redis的哨兵模式,集群模式和管道模式
    redisson:redisson是一个基于redis实现的分布式,可伸缩的java数据结构集合,包含了map,queue,lock,semaphore,atomiclong等强大功能
    
    redisTemplate:引入spring-boot-starter-data-reids依赖 commons-pool2连接池依赖
    				编写yml配置文件
    redisTemplate:序列化默认jdk序列化可读性差,内存占用大,必须改变序列化方式自定义序列化配置文件
    				反序列化:将json字符串转化为java对象,默认的会带有@class StringRedisTemplate类,它的key和value的序列化方式默认是string方式。省去了我们自定义RedisTemplate的过程
    
缓存:
	缓存穿透:客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库
	缓存雪崩:同一时段内大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库,带来巨大压力
			解决方案:1.给不同的key的ttl添加随机值 2.利用redis集群提高服务的可用性 
					3.给缓存业务添加降级限流策略  4.给业务添加多级缓存
	缓存击穿:热点key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效,无数的请求访问会在瞬间给数据库带来巨大冲击
			解决方案:加互斥锁,逻辑过期

基于redis的分布式锁

不同业务有不同的锁
trylock(time){
	
}

unlock(){
	String script = "if(redis.call('get',KEY[1])==ARGV[1] then return redis.call('del',KEY[1]) end return 0)";//解决释放锁原子性一致问题
}
@RestController
public class DlockController {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @RequestMapping("/lock/{order}/{username}") 
    public String update(@PathVariable ("order") String order,@PathVariable("username") String username){
        //标识线程,防止误删
        String uuid = UUID.randomUUID().toString();
        //锁的key,多个进程访问共享资源要竞争同一把锁标识,即形成互斥
        String lockKey = "lock:"+order;  //order表示对某类业务加锁
        lock(uuid,lockKey,username);
        return "";
    }

    private void lock(String uuid,String lockKey,String username) {
        //lua脚本 解锁原子性
        String script = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        //获取锁
        Boolean nativeLock = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, uuid, 2000,TimeUnit.SECONDS);
        System.out.println(username+"加锁状态:"+nativeLock);
        if(nativeLock){
            //加锁成功
            try{
                //作业业务相关
                System.out.println(username+"正在修改数据");
                TimeUnit.SECONDS.sleep(10L);
            }catch (Exception e){

            }finally {
                //解锁
                Long result = stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(lockKey), uuid);
                System.out.println(username+"解锁状态:"+result);
            }
        }else{
            //自旋操作
            try{
                System.out.println("加锁失败,休眠5秒...");
                TimeUnit.MILLISECONDS.sleep(5000);
            }catch (InterruptedException e){

            }
            lock(uuid,lockKey,username);
        }

    }

}
synchronized:
	本地锁只能锁当前进程,只要是同一把锁,就能锁住需要这个锁的所有进程
	1.synchronized(this):springboot所有的组件在容器中都是单例的,每个this代表当前容器的实例。而在分布式情况下一个服务可能部署在多个容器上,所以会有多个容器的实例即this.
本地缓存
缓存使用:
	1.那些数据适合放入缓存
		即时性,数据一致性要求不高的
		访问量大且更新频率不高的数据
分布式缓存:
	分布式缓存:通过缓存的中间件集中配置缓存,避免了调用了不同的服务器而导致数据不一致
	本地缓存:在多个本地缓存的数据不能保证数据的一致性问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值