redis常用命令和Spring data redis

redis是一个非关系型数据库,可基于内存亦可持久化的日志型、Key-Value数据库。这里需要解释redis, jedis和spring data redis是什么关系。

Redis 
redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写。企业开发通常采用Redis来实现缓存。同类的产品还有memcache 、memcached 、MongoDB等。

Jedis 
Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis。

Spring-data-redis 
Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。

redis数据操作

转自:https://blog.csdn.net/she_lock/article/details/80621156


Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 
1、String(字符串) 
一个key对应一个value。一个键最大能存储512MB。string类型是二进制安全的。

192.168.56.101:6>SET name "hello"   //存值
OK

192.168.56.101:6>GET name       //取值
hello

2、Hash(哈希) 
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。每个 hash 可以存储 232 - 1 键值对(40多亿)。

192.168.56.101:6>HMSET user name "张三" age 18    //存多个值   HMSET KEY_NAME FIELD1 VALUE1 ...FIELDN VALUEN 存单个值用 HSET KEY_NAME FIELD VALUE 
OK

192.168.56.101:6>HGET user age  //取值  HGET KEY_NAME FIELD_NAME 
18

192.168.56.101:6>HGET user name
张三

192.168.56.101:6>HGETALL user   //所有的字段和值  HGETALL KEY_NAME 
1) name
2) 张三
3) age
4) 18
5) sex
6) 男

192.168.56.101:6>HKEYS user  //获取key  HKEYS key 
1) name
2) age
3) sex

192.168.56.101:6>HLEN user  //获取哈希表中字段的数量


3

3、List(列表) 
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

192.168.56.101:6>lpush users admin //在users List中插入admin
1

192.168.56.101:6>lpush users guest
2

192.168.56.101:6>lpush users zhangsan
3

192.168.56.101:6>lrange users 0 10  //在users list中取出index为0到10的数据,超出的不显示
1) zhangsan
2) guest
3) admin
192.168.56.101:6>lrange users 
ERR wrong number of arguments for 'lrange' command

192.168.56.101:6>lrange users 0 3
1) zhangsan
2) guest
3) admin

4、Set(集合) 
Redis的Set是string类型的无序集合。值不重复。

sadd 添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。语法如下;

sadd key member

样例:

192.168.56.101:6>sadd tecq redis    //存值
1

192.168.56.101:6>sadd tecq redis    //插入重复的值,会不成功,返回0
0

192.168.56.101:6>sadd tecq moongodb
1

192.168.56.101:6>sadd tecq rabbitmq
1

192.168.56.101:6>smembers tecq  //取值
1) rabbitmq
2) moongodb
3) redis

5、zset(sorted set:有序集合) 
Redis zset 和 set 一样也是string类型元素的集合。且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

zadd命令添加元素到集合,元素在集合中存在则更新对应score,其语法如下:

zadd key score member 

样例:

192.168.56.101:6>zadd nosql 0 redis
1

192.168.56.101:6>zadd nosql 20 moongodb
1

192.168.56.101:6>zadd nosql 0 jedis
1

192.168.56.101:6>zadd nosql 2 neo4j
1

192.168.56.101:6>ZRANGEBYSCORE nosql 0 5  //按照 score 从小到大
1) jedis
2) redis
3) neo4j
192.168.56.101:6>ZRANGEBYSCORE nosql 0 0
1) jedis
2) redis
192.168.56.101:6>ZRANGEBYSCORE nosql 0 20
1) jedis
2) redis
3) neo4j
4) moongodb

key 相关
1、EXISTS KEY_NAME 检查给定 key 是否存在。若 key 存在返回 1 ,否则返回 0 。


192.168.56.101:6>exists tecp
0

192.168.56.101:6>exists tecq
1

2、DEL KEY_NAME 删除key。被删除 key 的数量。

192.168.56.101:6>del name
1

3、Expire KEY_NAME TIME_IN_SECONDS 设置 key 的过期时间,单位为 s(秒)。key 过期后将不再可用。设置成功返回 1 。 当 key 不存在或者不能为 key 设置过期时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的过期时间)返回 0 。

192.168.56.101:6>set name zhangsan 
OK

192.168.56.101:6>expire name 30
1

4、 TTL KEY_NAME 以秒为单位返回 key 的剩余过期时间。

192.168.56.101:6>set name zhangsan 
OK

192.168.56.101:6>expire name 60
1

192.168.56.101:6>ttl name    //已经过了6s
54

 

spring data redis

转自:https://blog.csdn.net/weixin_42430194/article/details/80834733#23-%E5%90%8E%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0%E5%B1%82%E4%B8%AD%E7%BC%93%E5%AD%98%E7%9A%84%E5%AE%9E%E7%8E%B0

项目常见问题思考 
项目首页每天有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪。那如何解决呢?我们通常的做法有两种:一种是数据缓存、一种是网页静态化。我们今天讨论第一种解决方案。

spring-data-redis针对jedis提供了如下功能: 
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口 
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作

Spring Data Redis入门小Demo
1 准备工作
(1)构建Maven工程 SpringDataRedisDemo 
(2)引入Spring相关依赖、引入JUnit依赖 (内容参加其它工程)
 

    <!-- 集中定义依赖版本号 -->
    <properties>
        <junit.version>4.12</junit.version>
        <spring.version>4.2.4.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
        </dependency>
    </dependencies>

(3)引入Jedis和SpringDataRedis依赖

<!-- 缓存 -->
<dependency> 
          <groupId>redis.clients</groupId> 
          <artifactId>jedis</artifactId> 
          <version>2.8.1</version> 
</dependency> 
<dependency> 
          <groupId>org.springframework.data</groupId> 
          <artifactId>spring-data-redis</artifactId> 
          <version>1.7.2.RELEASE</version> 
</dependency>   

(4)在src/main/resources下创建properties文件夹,建立redis-config.properties

        # 主机
        redis.host=127.0.0.1 
        # 端口号
        redis.port=6379 
        # 密码 一般不需要
        redis.pass= 
        redis.database=0 
        redis.maxIdle=300 
        redis.maxWait=3000 
        redis.testOnBorrow=true 

(5)在src/main/resources下创建spring文件夹 ,创建applicationContext-redis.xml

  <?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:mvc="http://www.springframework.org/schema/mvc" 
  xmlns:cache="http://www.springframework.org/schema/cache"
  xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans.xsd   
            http://www.springframework.org/schema/context   
            http://www.springframework.org/schema/context/spring-context.xsd   
            http://www.springframework.org/schema/mvc   
            http://www.springframework.org/schema/mvc/spring-mvc.xsd 
            http://www.springframework.org/schema/cache  
            http://www.springframework.org/schema/cache/spring-cache.xsd">  

   <context:property-placeholder location="classpath*:properties/*.properties" />   

   <!-- redis 相关配置 --> 
   <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
     <property name="maxIdle" value="${redis.maxIdle}" />   
     <property name="maxWaitMillis" value="${redis.maxWait}" />  
     <property name="testOnBorrow" value="${redis.testOnBorrow}" />  
   </bean>  

   <bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
       p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>  

   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
        <property name="connectionFactory" ref="JedisConnectionFactory" />  
   </bean>  

</beans>  
  • maxIdle :最大空闲数
  • maxWaitMillis:连接时的最大等待毫秒数
  • testOnBorrow:在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的;

2 值类型操作

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestValue {

    //泛型可以不指定
    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Test
    public void setValue(){
        //存值
        redisTemplate.boundValueOps("name").set("张三");
    }

    @Test
    public void getValue(){
        String name = redisTemplate.boundValueOps("name").get();
        //如果没有 name 则会返回 null
        System.out.println(name);
    }

    @Test
    public void deleteValue(){
        //移除值
        redisTemplate.delete("name");
    }

}

3 Set类型操作

/**
 * 特点: 无序,不可重复
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestSet {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void setValue(){
        redisTemplate.boundSetOps("nameset").add("曹操");
        redisTemplate.boundSetOps("nameset").add("刘备");
        redisTemplate.boundSetOps("nameset").add("关羽");
    }

    @Test
    public void getValue(){
        //如果没有 nameset 返回  []
        Set<String> members = redisTemplate.boundSetOps("nameset").members();
        // 没有循序,和存入的循序无关
        // [关羽, 刘备, 曹操] 
        System.out.println(members);
    }

    @Test
    public void removeValue(){
        //移除一个
        redisTemplate.boundSetOps("nameset").remove("刘备");

        //全部移除
        redisTemplate.delete("nameset");

    }
}

4 List类型操作

/**
 * 特点: 有序, 可重复
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestList {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 右压栈: 后添加的元素排在后面
     *              先进先出
     */
    @Test
    public void setValueRight(){
        redisTemplate.boundListOps("name").rightPush("张三");
        redisTemplate.boundListOps("name").rightPush("李四");
        redisTemplate.boundListOps("name").rightPush("王五");
        redisTemplate.boundListOps("name").rightPush("赵六");
    }


    /**
     * 右压栈的输入
     */
    @Test
    public void getValue(){
        // [张三, 李四, 王五,赵六]
        List<String> name = redisTemplate.boundListOps("name").range(0, 10);
        System.out.println(name);

    }

    /**
     * 左压栈: 先进后出
     */
    @Test
    public void setValueLeft(){
        redisTemplate.boundListOps("nameLeft").leftPush("关羽");
        redisTemplate.boundListOps("nameLeft").leftPush("张飞");
        redisTemplate.boundListOps("nameLeft").leftPush("诸葛亮");
        redisTemplate.boundListOps("nameLeft").leftPush("刘备");
    }

    /**
     * 左压栈的输入
     */
    @Test
    public void getValueLeft(){
        // [刘备, 诸葛亮, 张飞, 关羽]
        List<String> name = redisTemplate.boundListOps("nameLeft").range(0, 10);
        System.out.println(name);
    }

    /**
     * 按索引位置查询元素
     */
    @Test
    public void searchByIndex(){
        // 关羽
        String index = redisTemplate.boundListOps("nameLeft").index(3);
        System.out.println(index);
        //集合元素个数
        Long size = redisTemplate.boundListOps("nameLeft").size();
        System.out.println(size);
    }

    /**
     * 移除
     */
    @Test
    public void removeByIndex(){
        // 移除元素的个数   移除元素的name
        redisTemplate.boundListOps("nameLeft").remove(1, "诸葛亮");
        redisTemplate.delete("nameLeft");//移除所有值
    }
}

5 Hash类型操作

/**
 * 存取有序,不可重复
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestHash {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 存值
     */
    @Test
    public void setValue(){
        redisTemplate.boundHashOps("hash").put("a", "唐僧");
        redisTemplate.boundHashOps("hash").put("b", "八戒");
        redisTemplate.boundHashOps("hash").put("c", "沙和尚");
        redisTemplate.boundHashOps("hash").put("d", "孙悟空");
    }

    /**
     * 获取所有的key
     */
    @Test
    public void getAllKey(){
        //获取所有的key : [a, b, c, d]
        Set<Object> key = redisTemplate.boundHashOps("hash").keys();
        System.out.println(key);
    }

    /**
     * 获取所有的值
     */
    @Test
    public void getAllValue(){
        //获取所有的值
        List<Object> values = redisTemplate.boundHashOps("hash").values();
        System.out.println(values); //[唐僧, 八戒, 沙和尚, 孙悟空]

        //根据key取值
        String str = (String)redisTemplate.boundHashOps("hash").get("c");
        System.out.println(str); // 沙和尚
    }

    /**
     * 移除某个小key的值
     */
    @Test
    public void removeKey(){
        redisTemplate.boundHashOps("hash").delete("c");
    }
}

 

在项目中的应用
1 需求分析
项目中首页的广告每次都是从数据库读取, 这样当网站访问量达到高峰时段,对数据库压力很大,并且影响执行效率。我们需要将这部分广告数据缓存起来。

2 读取缓存
2.1 公共组件层
因为缓存对于我们整个的系统来说是通用功能。广告需要用,其它数据可能也会用到,所以我们将配置放在公共组件层中较为合理。

(1. 引入依赖 
(2. 创建配置文件

2.2 后端服务实现层中添加对公共组件层的依赖
2.3 后端服务实现层中缓存的实现
 

思路: 在查询数据时,我们要先从缓存中查询数据,如果缓存中没有再从数据库中查询,
      将从数据库中查询出来的数据存入缓存中.
    @Autowired
    private RedisTemplate redisTemplate;

        @Override
        public List<TbContent> findByCategoryId(Long categoryId) {

            //从缓存中查询数据
            List<TbContent> list = (List<TbContent>) redisTemplate.boundHashOps("content").get(categoryId);

            if(list == null){
                System.out.println("从数据库中查询数据并放入缓存");
                TbContentExample example = new TbContentExample();
                Criteria criteria = example.createCriteria();
                criteria.andCategoryIdEqualTo(categoryId);//指定分类ID
                criteria.andStatusEqualTo("1");//指定条件有效的
                example.setOrderByClause("sort_order");//排序
                list = contentMapper.selectByExample(example);
                redisTemplate.boundHashOps("content").put(categoryId, list);//放入缓存
            }else{
                System.out.println("从缓存中查询");
            }
            return list;
        }

2.4 细节

问题: 当我们数据库中的数据发生改变时,从缓存中查询出的数据并没有改变.
解决: 当广告数据发生变更时,需要将缓存数据清除,这样再次查询才能获取最新的数据
我们看一下那些操作使数据库中的数据发生改变:
    (1 增加
         再增加之前我们要清除缓存,然后再增加,这样会重新在数据库中查询一次,那么数据库的
         改变就会同步到缓存中
         contentMapper.insert(content);
         redisTemplate.boundHashOps("content").delete(content.getCategoryId());

    (2 删除
        for(Long id:ids){
        //清除缓存  先清除在删除
        Long categoryId = contentMapper.selectByPrimaryKey(id).getCategoryId();
        redisTemplate.boundHashOps("content").delete(categoryId);

        contentMapper.deleteByPrimaryKey(id);
        }   

    (3 修改
        注意`:  用户可能会修改广告的分类,这样需要把原分类的缓存和新分类的缓存都清除掉。
    @Override
    public void update(TbContent content){
        //查询修改前的分类Id
        Long categoryId = contentMapper.selectByPrimaryKey(content.getId()).getCategoryId();
        redisTemplate.boundHashOps("content").delete(categoryId);


        contentMapper.updateByPrimaryKey(content);
        //如果分类ID发生了修改,清除修改后的分类ID的缓存
        if(categoryId.longValue()!=content.getCategoryId().longValue()){
            redisTemplate.boundHashOps("content").delete(content.getCategoryId());
    }   

}

 spring data redis设置过期时间:

redisTemplate.expire(key, timeout, TimeUnit);

其中timeUnit参数是时间单位选择:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值