栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Redis简述

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Redis简述

Redis(Remote Dictionary Server )即远程字典服务,是 C 语言开发的一个开源的key/value存储系统(官网:http://redis.io),是一个分布式缓存数据库。

官方只提供Linux版本,windows公司提供了Windows版的(Redis的次版本号(第一个小数点后的数字为偶数的版本是稳定版本,奇数为非稳定版本)

Redis作为一种key/value结构的数据存储系统,为了便于对数据进行进行管理,提供了多种数据类型,Reids中基础数据结构包含字符串、散列,列表,集合,有序集合

优势: 并发处理能力非常好 , 更好的保证数据的可靠性, 有丰富的数据类型

Bootnb 相关:https://www.runoob.com/redis/redis-tutorial.html
Redis 官网:https://redis.io/
源码地址:https://github.com/redis/redis
Redis 在线测试:http://try.redis.io/
Redis 命令参考:http://doc.redisfans.com/

Redis数据存于磁盘中,采用TCP协议进行通讯

双写: 数据同时存入分布式缓存和数据库中

下载安装于linux操作系统中的docker容器中

基础常用命令

启动及关闭redis服务

docker ps #查看进程
docker stop 618 #关闭进程
docker start redis #启动redis进程
ps -ef | grep redis # 查看正在运行的进程过滤redis进程
docker exec -it redis01 bash #redis01 为容器名 进入redis容器
redis-cli #登陆本地redis服务
或者
redis-cli -p 6379
或者
redis-cli -p 6379 -a  password #-a后面为password,此操作需要开启redis.conf文件中的 requirepass选项
redis-cli  -h ip  -p 6379  -a  password #登录远端redis服务
info #查看当前redis节点的详细配置信息
shutdown #保护模式关闭redis服务
exit #关闭redis服务
select 1 #单机模式Redis默认支持16个数据库,下标是0-15
flushdb #清除当前数据库数据
flushall #清除所有数据库数据

set key1 100 #存入数据
type key1 #查看数据类型

①set key2 100 EX 5 #设置数据存储的有效时长 EX秒 PX毫秒
②set key3 100 
 expire key3 5 #数据保留5秒
ttl key3 #查看数据有效时长

keys * #查看当前数据库的所有key
get key1 #查询key1的数据
常见数据类型 String数据类型

存储的值可以是字符串,其最大字符串长度支持到512M
于此类型,可以实现博客的字数统计,将日志不断追加到指定key,实现一个分布式自增id,实现一个博客的的点赞操作等

set num 1 #如果值存在则覆盖
setnx num 9 #判断是否存在num,存在就不存入数据,不存在则存入数据

incr num #2 数据在内存中递增,数据库自增是在数据库程序中 订单分布式id
incr num #3 如果num不存在,则自动会创建,如果存在自动+1
incrby num 2 #每次递增2
decr num #递减
decrby num 3 #每次递减3

del key1 key2 #删除

append test "abc" #向尾部追加值。如果键不存在则创建该键

strlen test #字符串长度,返回数据的长度,如果键不存在则返回0。注意,如果键值为空串,返回也是0

mset a 1 b 2 c 3 #同时设置/获取多个键值
mget a b c

exists a b #判断某个值是否存在,0为不存在
Hash数据类型

Redis散列类型相当于Java中的HashMap,实现原理跟HashMap一致,一般用于存储对象信息,存储了字段(field)和字段值的映射,K V中V又是KV结构

hset user username chenchen
hset user password 123
hset user username chenchen password 123
hsetnx user password 456

hget user username
hgetall user 
hmget user username password
hvals user #chenchen 123
hkeys user #username password

hincrby article total -1		#没有hdecrby自减命令

hexists user username 

hdel user username # 操作的是小key
del user #操作的是大key
List数据类型

Redis的list类型相当于java中的LinkedList,其原理就就是一个双向链表。支持正向、反向查找和遍历等操作,插入删除速度比较快。经常用于实现热销榜,最新评论等的设计。K V 中的V为很多个有序可重复的V

lpush list1 a b c c d
rpop list1 5 #a b c c d
llen list1 #0

lpush list1 a b c c d
lpop list1 5 #d c c b a

lpush list1 a b c #最先进去的是最后的
linsert list1 before a  f
rpop list1 4 #a f b c

lpush list1 a b c #c的下标是0
lset list1 0 g
rpop list1 3 #a b g

lpush num1 a b c
lrem num1 1 a
lrange num1 0 -1 #c b
ltrim num1 0 0
lindex  num 0

lpush g1 a b
lpush g2 g f
rpoplpush g2 g1 
rpop g1 3 #a b g

lpush num1 a b c
brpop num1 20 #a 当元素移除完后,线程会指定阻塞时间20秒
brpop num1 20 #b
brpop num1 20 #c
Set数据类型

Redis的Set类似Java中的HashSet,是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。K V 中的V为很多个无序不可重复的V

sadd set1 a a b b c c c d d 
smembers set1 #d b a c
spop set1 1 #c
spop set1 2 #a b

sadd set1 a a b b c c c d d 
scard set1 #4
sadd set2 7 8 9
smove set1 set2 c
spop set2 #7 c 8 9
sunion set1 set2
Zset数据类型

zet是Redis提供的一个非常特别的数据结构,常用作排行榜等功能,以用户d为value,关注时间或者分数作为score进行排序。K score1 user1 score2 user2  

Java中操作redis

Redis 是一种C/S 架构的分布式缓存数据库,它有自带的命令行客户端,也有对应的Java或其它语言客户端,可以在这些客户端中通过一些API对redis进行读写操作。

创建父工程,pom文件添加编译配置


        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    8
                    8
                
            
        
    
Jedis的基本应用

Jedis是Java中操作redis的一个客户端,类似通过jdbc访问mysql数据库.

创建redis-jedis 工程添加如下依赖


       
           redis.clients
           jedis
           3.5.2
       
       
           junit
           junit
           4.12
           test
       
       
       
           com.google.code.gson
           gson
           2.8.6
       

在Jedis工程中的src/test/java目录创建单元测类

public class JedisTests {
    
    @Test
    public void testHashOper01(){
        //1.建立连接(TCP)
        Jedis jedis=new Jedis(
                "192.168.126.128", 6379);
        //2.添加数据
        Map map1=new HashMap<>();
        map1.put("id", "201");
        map1.put("title", "redis6.2.5");
        jedis.hset("blog:201", map1);//不存在则直接添加
        jedis.hset("blog:201", "title", "redis6.2.6");
        //3.读取数据
        map1=jedis.hgetAll("blog:201");
        System.out.println(map1);
        //4.释放资源
        jedis.close();
    }
    
    @Test
    public void testStringOper02() {
        //1.建立连接
        Jedis jedis=new Jedis(
                "192.168.126.128", 6379);
        //2.将一个map对象转换为json字符串,然后写入到redis并给定有效期
        Map map1=new HashMap<>();
        map1.put("id", "101");
        map1.put("title", "redis6.2.5");
        Gson gson=new Gson();
        String jsonStr1=gson.toJson(map1);
        System.out.println(jsonStr1);
        jedis.set("blog:101", jsonStr1);
        jedis.expire("blog:101", 20);
        //3.从redis将json字符串读出,并转换为map然后输出.
        String jsonStr2 = jedis.get("blog:101");
        Map map2=gson.fromJson(jsonStr2,Map.class);
        System.out.println(map2);
        //4.释放资源
        jedis.close();
    }
    
    @Test
    public void testStringOper01(){
      //1.建立连接
        Jedis jedis=new Jedis(
                "192.168.126.128", 6379);
      //2.添加数据(Create)
        jedis.set("id", "100");
        Long setnx = jedis.setnx("lock", "AAA");
        jedis.set("logs", "abc");
        //3.获取数据(Retrieve)
        String id = jedis.get("id");
        System.out.println("update.before.id="+id);
      //4.修改数据(Update)
        jedis.incr("id");
        id = jedis.get("id");
        System.out.println("update.after.id="+id);

        jedis.expire("lock", 10);
        jedis.append("logs","EF");

      //5.删除数据(Delete)
        jedis.del("id");
        id = jedis.get("id");
        System.out.println("delete.after.id="+id);
      //6.释放资源
        jedis.close();

    }

    @Test
    public void testGetConnection(){
        //1.建立连接
        //假如无法建立连接,要从如下几个方面进行分析
        //1)ip
        //2)port
        //3)防火墙
        //4)redis服务是否启动ok
        Jedis jedis=new Jedis(
                "192.168.126.128", 6379);
        //jedis.auth("123456");
        //2.执行ping操作
        String result = jedis.ping();
        System.out.println(result);
    }
}
连接池JedisPool连接池
public class JedisPoolTests {
    
    @Test
    public void testJedisPool(){
        //1.创建池对象
        //GenericObjectPoolConfig poolConfig=
                //new GenericObjectPoolConfig();
        JedisPoolConfig poolConfig=//这个类型是上面类型的子类类型.
                new JedisPoolConfig();
        poolConfig.setMaxTotal(128);//最大连接数
        poolConfig.setMaxIdle(8);//最大空闲连接数
        JedisPool jedisPool=
                //new JedisPool("192.168.126.128", 6379);
                new JedisPool(poolConfig,
                        "192.168.126.128", 6379);
        //2.获取连接
        Jedis resource = jedisPool.getResource();
        //3.读写数据
        resource.set("id", "100");
        String id = resource.get("id");
        System.out.println(id);
        //4.释放资源
        resource.close();
        jedisPool.close();//以后这个池是关服务的时候关.
    }
}

提取连接池配置到配置类中,需要时直接通过方法获取即可

public class JedisDataSource {


   //初始化池对象并获取连接 (何时需要何时创建池对象~懒加载)
    private static volatile JedisPool jedisPool;
    
    public static  Jedis getConnection(){ //JedisDataSource.class
        if(jedisPool==null) {
            synchronized (JedisDataSource.class) {
                if (jedisPool == null) {
                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    poolConfig.setMaxTotal(128);//最大连接数
                    poolConfig.setMaxIdle(8);//最大空闲连接数
                    jedisPool = new JedisPool(poolConfig, "192.168.126.128", 6379);
                    //1.对象创建的过程?
                    //1)分配内存
                    //2)初始化属性
                    //3)执行构造方法
                    //4)将JedisPool对象赋值给jedisPool变量
                }
            }
        }
        return jedisPool.getResource();
    }

    public static void close(){
        jedisPool.close();
    }
}

可以参考HikariDataSource类中连接池的创建,以上代码还是存在线程不停切换的问题,需要将成员变量赋值给局部变量,再进行判断,可以减少线程之间切换的问题; 还可以进一步优化,将连接池的配置参数提取到pom配置文件中

RedisTemplate基本应用(lettuceAPI)

创建子工程redis-template,添加添加依赖


        
            
                org.springframework.boot
                spring-boot-dependencies
                2.3.2.RELEASE
                pom
                import
            
        
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        


        
            mysql
            mysql-connector-java
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.2
        

        
        
            org.apache.commons
            commons-pool2
        

    
spring:
  redis:
    host: 192.168.126.129  #写自己的ip
    port: 6379

创建启动类测试连接是否成功

package com.jt.redis;
@SpringBootTest
public class RedisTemplateTests {
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    
    @Test
    void testGetConnection(){
        RedisConnection connection =
            redisTemplate.getConnectionFactory()
                         .getConnection();
        String result = connection.ping();
        System.out.println(result);
    }

    @Test
    void testStringOper01(){
       //1.获取字符串操作对象(ValueOperations)
        ValueOperations vo = redisTemplate.opsForValue();
        //2.操作redis数据
        vo.set("x", 100);
        Object x = vo.get("x");
        System.out.println(x);
        //vo.increment("x");//不可以
        Long y = vo.increment("y");
        y=vo.increment("y");
        //Object y = vo.get("y");//不可以
        System.out.println(y);
        //存储key/value,设置key的有效期
        vo.set("z", "100", Duration.ofSeconds(10));
    }
    
    @Test
    void testStringOper02(){
        //1.获取字符串操作对象(ValueOperations)
        ValueOperations vo = redisTemplate.opsForValue();
        //2.按默认序列化方式存储数据
        String token= UUID.randomUUID().toString();
        vo.set(token,"admin");
        //3.指定序列方式进行数据存储
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(RedisSerializer.string());
        vo.set(token,"Mike");
        //4.更新数据(假如有对应的key则直接进行覆盖)
        vo.set(token, "Jack");
        Object value = vo.get(token);
        System.out.println(value);
        //5.删除数据(存数据时给定有效期-生产环境必须设置)
        vo.set("permissions", "sys:res:update",Duration.ofSeconds(5));
    }
    
    @Test
    void testHashOper01(){
        //1.获取Hash操作对象(ValueOperations)
        HashOperations ho = redisTemplate.opsForHash();
        //2.以hash类型存储数据
        ho.put("blog","id",100);
        ho.put("blog", "title", "redis....");
        //3.获取数据
        Object id = ho.get("blog", "id");
        Object title = ho.get("blog", "title");
        System.out.println("id="+id+";title="+title);
        Map blog = ho.entries("blog");//取key对应的所有值。
        System.out.println(blog);
    }
  
   
    @Test
    void testHashOper02() throws JsonProcessingException {
        //1.获取数据操作对象(ValueOperations,HashOperations)
        ValueOperations vo = redisTemplate.opsForValue();
        HashOperations ho = redisTemplate.opsForHash();
        //2.基于ValueOperations存取Blog对象
        Blog blog=new Blog();
        blog.setId(100L);
        blog.setTitle("redis ...");
        vo.set("blog-jack", blog);//序列化
        Object o = vo.get("blog-jack");//反序列化
        System.out.println(o);
        //3.基于HashOperations存取Blog对象
        ObjectMapper objectMapper=new ObjectMapper();//jackson
        String jsonStr=objectMapper.writeValueAsString(blog);
        Map map = objectMapper.readValue(jsonStr, Map.class);
        ho.putAll("blog-mike", map);
        ho.put("blog-mike","id","200");
        map=ho.entries("blog-mike");
        System.out.println(map);
    }

    @Test
    void testListOper(){
      //向list集合放数据
        ListOperations listOperations = redisTemplate.opsForList();
        listOperations.leftPush("lstKey1", "100"); //lpush
        listOperations.leftPushAll("lstKey1", "200","300");
        listOperations.leftPush("lstKey1", "100", "105");
        listOperations.rightPush("lstKey1", "700");
        Object value= listOperations.range("lstKey1", 0, -1);
        System.out.println(value);
      //从list集合取数据
        Object v1=listOperations.leftPop("lstKey1");//lpop
        System.out.println("left.pop.0="+v1);
        value= listOperations.range("lstKey1", 0, -1);
        System.out.println(value);
    }

    @Test
    void testSetOper(){
        SetOperations setOperations=redisTemplate.opsForSet();
        setOperations.add("setKey1", "A","B","C","C");
        Object members=setOperations.members("setKey1");
        System.out.println("setKeys="+members);
        //........
    }

   @Test
    void testFlushdb(){
        redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
               //redisConnection.flushDb();
                redisConnection.flushAll();
                return "flush ok";
            }
        });
    }
     @Test
    void testGetConnection(){
        RedisConnection connection =
                stringRedisTemplate.getConnectionFactory()
                        .getConnection();
        String ping = connection.ping();
        System.out.println(ping);
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/888009.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号