• spring-redis使用


    导包 

    注入调用           opsForValue()     opsForList()

    redisTemplate   配置 ,为了   对key采用string序列化方式                 对value采用json序列化方式

    参数的配置

    # Redis 配置
    # Redis数据库索引(默认为0)
    spring.redis.database=0
    # Redis服务器地址
    spring.redis.host=192.168.10.128
    # Redis服务器连接端口
    spring.redis.port=6379
    # Redis服务器连接密码(默认为空)
    spring.redis.password=123qwe
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=8
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=8
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0
    # 连接超时时间(毫秒)
    spring.redis.timeout=0

    使用Redis做缓存

    使用Spring Cache注解 设置过期时间

     

    在service层加上cache注解

    @Cacheable  为存取缓存     @CachePut 为修改缓存      @CacheEvict 为删除缓存

     各个注解中的value参数是一个key的前缀

    对于key的生成规则用调用者本身对象的ID属性保证它的唯一性如下 注册进

    然后在需要cache的地方调用Redis  CRUD 方法

    1.为什么使用redis  性能 并发

    2.单线程的redis为什么这么快

    redis是单线程工作模型

    (一)纯内存操作
    (二)单线程操作,避免了频繁的上下文切换
    (三)采用了非阻塞I/O多路复用机制

    参照上图,简单来说,就是。我们的redis-client在操作的时候,会产生具有不同事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。

    3、redis的数据类型,以及每种数据类型的使用场景(五种)

    String    一些复杂的计数功能的缓存。

    hash     单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。

    list     做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。

    set   全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。
    另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能

    sorted set   set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外,参照另一篇《分布式之延时任务方案解析》,该文指出了sorted set可以用来做延时任务。最后一个应用就是可以做范围查找

    4、redis的过期策略以及内存淘汰机制

    redis采用的是定期删除+惰性删除策略。

    定期删除 默认100ms   惰性删除 在请求key的时候判断过期时间

    如果既没删掉,又没访问惰性删除,内存要爆掉了怎么办,只能采用内存淘汰机制

    在redis.conf中有一行配置
    # maxmemory-policy volatile-lru   在设置过期时间的键中移出最少使用的key  不推荐

    allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。

    5、redis和数据库双写一致性问题

    数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存

    采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。https://www.cnblogs.com/rjzheng/p/9041659.html

     

    6 如何解决redis的并发竞争key问题

    (1)如果对这个key操作,不要求顺序
    这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。
    (2)如果对这个key操作,要求顺序
    假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC.
    期望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。假设时间戳如下

    系统A key 1 {valueA  3:00}
    系统B key 1 {valueB  3:05}
    系统C key 1 {valueC  3:10}

    那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。

    其他方法,比如利用队列,将set方法变成串行访问也可以。总之,灵活变通。

    redis-cli 启动

    set name(key) "value"(value)
    get name
    1.key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且会降低查找的效率;
    2.key也不要太短,太短的话,key的可读性会降低;
    3.在一个项目中,key最好使用统一的命名模式,例如user:10000:passwd。
    incr name 给某个值加1 (INCR、INCRBY、DECR、DECRBY)全部具有原子操作不需担心事务
    2.存list
    lpush mylist "1"
    lpush(左插)rpush(右插)
    lrange mylist 0 1
    2.存set
    asdd myset "one"
    smembers myset 列出
    sismember myset "one" 判断是否存在
    sunion myset yourset 合并
    有序集合(zsets)
    zadd myzset 3 value 赋予他的序号为3
    3.存Hash
    HMSET user:001(key) username antirez password P1pp0 age 34 (value)
    HGETALL user:001
    HSET user:001 password 12345

    redis提供了两种持久化的方式分别是RDB(Redis DataBase)和AOF(Append Only File)

    RDB,简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上

    如果每5分钟都持久化一次,当redis故障时,仍然会有近5分钟的数据丢失


    AOF,则是换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了
    通过配置redis.conf中的appendonly yes就可以打开AOF功能
    默认的AOF持久化策略是每秒钟fsync(缓存中的指令记录到磁盘中)一次 之丢失1s
    直接执行BGREWRITEAOF命令,那么redis会生成一个全新的AOF文件

    关闭RDB和AOF方式 redis将变成一个纯内存数据库,就像memcache一样。


    1.MULTI用来组装一个事务;
    2.EXEC用来执行一个事务;
    3.DISCARD用来取消一个事务;
    4.WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行

    redis-check-aof工具来修复 不完整指令信息


    redis.conf配置
    include /other.conf 引入其他配置文件
    1.通用(general)
    2.快照(snapshotting)
    3.复制(replication)
    4.安全(security)
    5.限制(limits)
    6.追加模式(append only mode)
    7.LUA脚本(lua scripting)
    8.慢日志(slow log)
    9.事件通知(event notification)


    2快照
    save 60 10000 //表示每60秒至少有10000个key改变,就触发一次持久化
    不设置save或save "" 禁用RDB持久化

    当RDB持久化失败 —>拒绝写请求
    等待成功后,自动恢复
    stop-writes-on-bgsave-error yes 关闭强行接受

    rdbcompression yes 是否关闭压缩快照
    rdbchecksum yes 快照存储后是否关闭快照数据校验
    dbfilename dump.rdb 设置快照名称
    dir ./ 目录


    3.redis配置 – 复制

    slaveof <masterip> <masterport> 主从同步
    masterauth <master-password> 设置主的密码(主设置密码 requirepass设置)

    主从同步时 客户端 只读slave-read-only yes

    只读的从redis并不适合直接暴露给不可信的客户端 名字起得牛点,难以直接调用
    rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

    repl-backlog-size 1mb 设置同步队列长度 队列长度(backlog)是主redis中的一个缓冲区在与从redis断开连接期间,主redis会用这个缓冲区来缓存应该发给从redis的数据。这样的话,当从redis重新连接上之后,就不必重新全量同步数据,只需要同步这部分增量数据即可。

    repl-backlog-ttl 3600 设置等待时间,等不到我就清除了

    slave-priority 100 设置优先级 ,越小越高 如果主不工作了,谁来当主


    5.限制
    maxclients 10000
    maxmemory <bytes>
    达到内存上限后 移除规则可以通过maxmemory-policy来指定。
    移除规则
    1.volatile-lru:使用LRU算法移除过期集合中的key
    2.allkeys-lru:使用LRU算法移除key
    3.volatile-random:在过期集合中移除随机的key
    4.allkeys-random:移除随机的key
    5.volatile-ttl:移除那些TTL值最小的key,即那些最近才过期的key。
    6.noeviction:不进行移除。针对写操作,只是返回错误信息。


    6.追加模式
    appendonly no

    no-appendfsync-on-rewrite no


    Redis 和 Memcached 的区别
    http://www.importnew.com/26921.html

    使用redis
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    </dependency>
    <gson>
    spring.redis.database=0
    spring.redis.host=192.168.0.58
    spring.redis.port=6379
    spring.redis.password=
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=8
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=8
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0
    # 连接超时时间(毫秒)
    spring.redis.timeout=0


    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport{

    @Bean
    public KeyGenerator keyGenerator() {
    return new KeyGenerator() {
    @Override
    public Object generate(Object target, Method method, Object... params) {
    StringBuilder sb = new StringBuilder();
    sb.append(target.getClass().getName());
    sb.append(method.getName());
    for (Object obj : params) {
    sb.append(obj.toString());
    }
    return sb.toString();
    }
    };
    }
    @Bean
    public KeyGenerator objectId() {
    return new KeyGenerator(){
    @Override
    public Object generate(Object target, Method method, Object... params) {
    StringBuffer sb = new StringBuffer();
    sb.append(target.getClass().getName());
    try {
    sb.append(params[0].getClass().getMethod("getId", null)
    .invoke(params[0],null).toString());
    } catch (NoSuchMethodException no) {
    no.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }
    return sb.toString();
    }
    };
    }

    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    //设置缓存过期时间
    //rcm.setDefaultExpiration(60);//秒
    return rcm;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
    StringRedisTemplate template = new StringRedisTemplate(factory);
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    template.setValueSerializer(jackson2JsonRedisSerializer);
    template.afterPropertiesSet();
    return template;
    }

    }
    @Autowired
    private RedisTemplate redisTemplate;

    redisTemplate.opsForValue().set

    Gson gson = new Gson();
    gson.tojson
    user = gson.fromJson(userJson, User.class);

    spring.cache.type = redis 进行配置

    @Cacheble() @CachePut @CacheEvict 删除 @Caching

    @CacheEvict: 失效缓存

    @Cacheable: 插入缓存
    value: 缓存名称
    key: 缓存键,一般包含被缓存对象的主键,支持Spring EL表达式
    unless: 只有当查询结果不为空时,才放入缓存

    session 也可以放到redis中
    共享Session-spring-session-data-redis
    <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    @Configuration
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
    public class SessionConfig {
    }


    Redis常用命令
    1 连接操作命令

    quit:关闭连接(connection)
    auth:简单密码认证
    help cmd: 查看cmd帮助,例如:help quit
    2 持久化

    save:将数据同步保存到磁盘
    bgsave:将数据异步保存到磁盘
    lastsave:返回上次成功将数据保存到磁盘的Unix时戳
    shutdown:将数据同步保存到磁盘,然后关闭服务
    3 远程服务控制

    info:提供服务器的信息和统计
    monitor:实时转储收到的请求
    slaveof:改变复制策略设置
    config:在运行时配置Redis服务器
    4 对key操作的命令

    exists(key):确认一个key是否存在
    del(key):删除一个key
    type(key):返回值的类型
    keys(pattern):返回满足给定pattern的所有key
    randomkey:随机返回key空间的一个
    keyrename(oldname, newname):重命名key
    dbsize:返回当前数据库中key的数目
    expire:设定一个key的活动时间(s)
    ttl:获得一个key的活动时间
    select(index):按索引查询
    move(key, dbindex):移动当前数据库中的key到dbindex数据库
    flushdb:删除当前选择数据库中的所有key
    flushall:删除所有数据库中的所有key
    5 String

    set(key, value):给数据库中名称为key的string赋予值value
    get(key):返回数据库中名称为key的string的value
    getset(key, value):给名称为key的string赋予上一次的value
    mget(key1, key2,…, key N):返回库中多个string的value
    setnx(key, value):添加string,名称为key,值为value
    setex(key, time, value):向库中添加string,设定过期时间time
    mset(key N, value N):批量设置多个string的值
    msetnx(key N, value N):如果所有名称为key i的string都不存在
    incr(key):名称为key的string增1操作
    incrby(key, integer):名称为key的string增加integer
    decr(key):名称为key的string减1操作
    decrby(key, integer):名称为key的string减少integer
    append(key, value):名称为key的string的值附加value
    substr(key, start, end):返回名称为key的string的value的子串
    6 List

    rpush(key, value):在名称为key的list尾添加一个值为value的元素
    lpush(key, value):在名称为key的list头添加一个值为value的 元素
    llen(key):返回名称为key的list的长度
    lrange(key, start, end):返回名称为key的list中start至end之间的元素
    ltrim(key, start, end):截取名称为key的list
    lindex(key, index):返回名称为key的list中index位置的元素
    lset(key, index, value):给名称为key的list中index位置的元素赋值
    lrem(key, count, value):删除count个key的list中值为value的元素
    lpop(key):返回并删除名称为key的list中的首元素
    rpop(key):返回并删除名称为key的list中的尾元素
    blpop(key1, key2,… key N, timeout):lpop命令的block版本。
    brpop(key1, key2,… key N, timeout):rpop的block版本。
    rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
    7 Set

    sadd(key, member):向名称为key的set中添加元素member
    srem(key, member) :删除名称为key的set中的元素member
    spop(key) :随机返回并删除名称为key的set中一个元素
    smove(srckey, dstkey, member) :移到集合元素
    scard(key) :返回名称为key的set的基数
    sismember(key, member) :member是否是名称为key的set的元素
    sinter(key1, key2,…key N) :求交集
    sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合
    sunion(key1, (keys)) :求并集
    sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合
    sdiff(key1, (keys)) :求差集
    sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合
    smembers(key) :返回名称为key的set的所有元素
    srandmember(key) :随机返回名称为key的set的一个元素
    8 Hash

    hset(key, field, value):向名称为key的hash中添加元素field
    hget(key, field):返回名称为key的hash中field对应的value
    hmget(key, (fields)):返回名称为key的hash中field i对应的value
    hmset(key, (fields)):向名称为key的hash中添加元素field
    hincrby(key, field, integer):将名称为key的hash中field的value增加integer
    hexists(key, field):名称为key的hash中是否存在键为field的域
    hdel(key, field):删除名称为key的hash中键为field的域
    hlen(key):返回名称为key的hash中元素个数
    hkeys(key):返回名称为key的hash中所有键
    hvals(key):返回名称为key的hash中所有键对应的value
    hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

    具体察看

  • 相关阅读:
    Mvc自定义HtmlHelper
    Mvc动作过滤器
    UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
    移动UIButton
    UIControlEventTouchEnter
    objective 修改plist文件
    单例模式笔记
    IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解
    UINavgationController一些使用技巧
    cocos2d 学习笔记
  • 原文地址:https://www.cnblogs.com/mxz1994/p/8480376.html
Copyright © 2020-2023  润新知