Redis

Redis 是一个基于 内存 的 key-value 结构数据库。

  • 基于内存存储,读写性能高 (mysql是存储在磁盘上)
  • 适合存储热点数据(热点商品、咨询、新闻)
  • 应用在微博、推特、阿里巴巴、百度、美团、搜狐等

Redis是一个开源的内存中的数据结构存储系统,可以用作:数据库、缓存和消息中间件。

NoSQL = Not Only Sql, 泛指非关系型数据库,一类数据库,不是特指某一种数据库

关系型数据库RDBMS:MySQL、Oracle、DB2、SQLServer

非关系型数据库NoSQL:Redis、Mongo DB、MemCached

Redis应用场景:缓存热点数据、任务队列、消息队列、分布式锁(解决并发式操作问题)

Redis安装:

Redis_第1张图片

 Linux安装Redis:

Redis_第2张图片

  1. 压缩包上传
  2. 解压:tar -axvf redis-4.0.0.tar.gz -C /usr/local
  3. 进入相应目录:cd /usr/local
  4. 安装Redis的依赖环境gcc,命令:yum install gcc-c++
  5. 进入/usr/local/redis-4.0.0,进行编译,命令:make
  6. 进入redis的src目录进行安装,命令:make install

Windows安装Redis:

直接解压即可使用,解压后目录结构如下:

Redis_第3张图片

Linux服务启动与停止:

Linux中Redis服务启动,可以进入src目录,然后使用redis-server,默认端口号为6379

复制一个标签窗口,cd /usr/local/redis-4.0.0/src

Redis_第4张图片

redis-cli :默认连接本地redis服务

keys * 连接服务

Redis_第5张图片

Ctrl + C 停止Redis服务

修改redis的配置:vi redis.conf

输入/ 搜索dae, 找到daemonize 改no 为 yes :wq 退出

设置为后台运行:src/redis-server ./redis.conf

Windows服务启动与停止:

Redis_第6张图片

redis 服务默认没有开启密码校验,在redis-4.0.0文件夹下:

1. 从 redis.conf 中 找requirepass,将其注释去掉,并设置一个密码 123456

2. ps -ef | grep redis 将进程杀掉kill -9 xxxxx

3. 然后重新启动:src/redis-server ./redis.conf

4. src/redis-cli -h localhost -p 6379 (p后面是端口号)

5. keys * 会报错 然后输入 auth + 密码 或者第4步骤后边跟上 -a password

修改配置文件,使得redis可以被远程连接

Redis_第7张图片

按住shift点右键,将命令行窗口打开:

Redis_第8张图片

在powershell中输入 .\redis-cli.exe -h 192.168.153.128 -p 6379 -a 123456

如果显示 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。

firewall-cmd --zone=public --add-port=6379/tcp --permanent

systemctl restart firewalld

Redis_第9张图片

Redis数据类型:

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5中常用的数据类型:

  • 字符串String
  • 哈希hash:适合存储对象
  • 列表list:按照插入顺序排序,可以有重复元素 做任务队列
  • 集合set:无序集合,没有重复元素
  • 有序集合sorted set:有序集合,没有重复元素

Redis常用命令:

Redis 字符串(String)_redis教程

先打开redis-server.ext,再打开redis-cli.exe,然后在redis-cli.ext中运行以下语句:

  • 字符串String:set命令设置的value,都会转成字符串存储

set key value

设置指定key的值

get key

获取指定key的值

setex key seconds value

设置指定key的值,并将通过key获取对应的value值的过期时间设为seconds秒,例如手机验证码

setnx key value

只有在key不存在时设置key的值(即一次赋值之后再也不能再赋值),例如分布式锁

  • 哈希hash:是一个string类型的field和value的映射表,hash特别适合用于存储对象,常用命令:

Redis_第10张图片

hset key field value

将hash表key中的字段field的值设为value

hget key field

获取存储在哈希表中指定字段的值

hdel key field

删除存储在哈希表中的指定字段,可以删除多个字段

hkeys key

获取哈希表中所有字段

hvals key

获取哈希表中所有值

hgetall key

获取在哈希表中指定key的所有字段和值

  • 列表list:是简单的字符串列表,按照插入顺序排序,常用命令

lpush key value1 [value2]

将一个或多个值插入到列表头部

lrange key start stop

获取列表指定范围内的元素,stop:-1 表示到最后

drop key

移除并获取列表最后一个元素

llen key

获取列表长度

brpop key1 [key2] timeout

移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。实现任务队列

  • 集合set:是string类型的无序集合,集合成员是唯一的,意味着集合后总不能和出现重复的数据,常用命令:

sadd key member1 [member2]

向集合添加一个或多个成员

smembers key

返回集合中的所有成员

scard key

获取集合的成员数

sinter key1 [key2]

返回给定所有集合的交集

sunion key1 [key2]

返回所有给定集合的并集

sdiff key1 [key2]

返回给定所有集合的差集

srem key member1 [member2]

移除集合中一个或多个成员

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

Redis_第11张图片

zadd key score1 member1 [score2 member2]

向有序集合添加一个或多个成员,或者更新已经存在成员的分数

zrange key start stop [withscores]

通过索引区间返回有序集合中指定区间内的成员

zincrby key increment member

有序集合中对指定成员的分数加上增量increment

zrem key member [member ... ]

移除有序集合中的一个或多个成员

  • 通用命令:

keys pattern

查找所有符合给定模式(pattern)的key,pattern多为*

exists key

检查给定key是否存在,存在返回1,不存在返回0

type key

返回key所存储的值的类型,以上5种Redis数据类型中的一种

ttl key

返回给定key的剩余生存时间(TTL,time to live),以秒为单位

del key

该命令用于在key存在时删除key

在java中操作redis:

Redis的java客户端很多:Jedis、Lettuce、Redisson

Spring对Redis客户端进行了整合,提供了Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即pring-boot-starter-data-redis

Jedis的maven坐标:


    redis.clients
    jedis
    3.2.0

使用Jedis操作Redis的步骤:① 获取连接 ② 执行操作 ③ 关闭连接

@Test
public void testRedis(){
    //  ① 获取连接
    Jedis jedis = new Jedis("localhost", 6379);   //类似于jdbc的connection
    //  ② 执行操作
    jedis.set("username", "xiaoming");   //和redis的命令一样
    //  ③ 关闭连接
    jedis.close();
}

打开两个exe服务,运行以上test,在服务中执行get username,即可获得属性值“xiaoming"

@Test
public void testRedis(){
    Jedis jedis = new Jedis("localhost", 6379);   //类似于jdbc的connection
    jedis.set("username", "xiaoming");   //和redis的命令一样
    String value = jedis.get("username");
    System.out.println(value);
    jedis.hset("China", "province", "hebei");
    String hget = jedis.hget("China", "province");
    System.out.println(hget);
    Set keys = jedis.keys("*");    //等价于keys *
    for (String key : keys) {
        System.out.println(key);
    }
    jedis.close();
}

Spring Data Redis

在springboot项目中,可以使用spring data redis来简化redis操作,maven坐标:


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

spring data redis中提供了一个高度封装的类:RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

ValueOperations

简单K-V操作

SetOperations

set类型数据操作

ZSetOperations

zset类型数据操作

HashOperations

针对map类型的数据操作

ListOperations

针对list类型的数据操作

application.properties配置文件中配置

spring.application.name=jedis
spring.redis.host=localhost           //IP
spring.redis.port=6379                //端口号
#spring.redis.password=123456          //密码
spring.redis.database=0                //0号数据库  在redis-cli.exe中切换数据库:select 2  切换到2号数据库
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=1ms
spring.redis.jedis.pool.max-idle=4
spring.redis.jedis.pool.min-idle=0

Redis_第12张图片

Redis_第13张图片

测试类中:

@SpringBootTest
//@RunWith(SpringRunner.class)
public class JedisApplicationTests {
    @Resource
    private RedisTemplate redisTemplate;

    @Test
    public void testString(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("city123", "shanghai");
    }
}

得到的结果:

Redis_第14张图片

得到的是序列化的结果,要将前缀需要去掉,需要写一个配置类:

@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}

数据类型操作:

//    操作String类型的数据
    @Test
    public void testString(){
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("city555", "shanghai");
        String city555 = (String) valueOperations.get("city555");     //获取值
        System.out.println(city555);
        redisTemplate.opsForValue().set("key111", "value111", 10, TimeUnit.SECONDS);    //设置过期时间
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city555", "南京");    //key不存在时给key设置值
        System.out.println(aBoolean);
    }
//    操作hash类型的数据
    @Test
    public void hashTest(){
        HashOperations hashOperations = redisTemplate.opsForHash();
//        存值
        hashOperations.put("002", "name", "xiaoming");
        hashOperations.put("002", "age", "23");
        hashOperations.put("002", "addr", "shanghai");
//        取值
        String name = (String) hashOperations.get("002", "name");
        String age = (String) hashOperations.get("002", "age");
        String addr = (String) hashOperations.get("002", "addr");
        System.out.println(name + " " + age + " " + addr);
//        获得hash结构中的所有字段
        Set keys = hashOperations.keys("002");
        for (Object key : keys) {
            System.out.println(key);
        }
//        获得hash结构中的所有value值
        List values = hashOperations.values("002");
        for (Object value : values) {
            System.out.println(value);
        }
    }
//    操作list类型的数据
    @Test
    public void listTest(){
        ListOperations listOperations = redisTemplate.opsForList();
        listOperations.leftPush("mylist", "a");
        listOperations.leftPushAll("mylist", "a", "b", "c", "d");   //先进后遍历
        List mylist = listOperations.range("mylist", 0, -1);
        for (String o : mylist) {
            System.out.println(o);
        }
        System.out.println("================================================");
//        出队列
        Long len = listOperations.size("mylist");
        int length = len.intValue();
        for (int i = 0; i < length; i++) {
            String element = (String) listOperations.leftPop("mylist");  //leftPop:从右往左;rightPop:从左往右
            System.out.println(element);
        }

    }
//    操作set类型的数据
    @Test
    public void testSet(){
        SetOperations setOperations = redisTemplate.opsForSet();
//        存值
        setOperations.add("myset", "1", "a", "a", "d");
//        取值
        Set myset = setOperations.members("myset");
        for (String o : myset) {
            System.out.println(o);
        }
//        删除值
        setOperations.remove("myset", "a", "b");
        System.out.println("================");
//        取值
        Set myset1 = setOperations.members("myset");
        for (String s : myset1) {
            System.out.println(s);
        }
    }
//    操作ZSet
    @Test
    public void testZSet(){
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//        存值
        zSetOperations.add("myZset", "a", 10.0);
        zSetOperations.add("myZset", "b", 6.0);
        zSetOperations.add("myZset", "c", 1.0);
        zSetOperations.add("myZset", "d", 5.0);
        zSetOperations.add("myZset", "b", 2.0);   //重复的value,分数会替换之前设置的分数
        zSetOperations.add("myZset", "a", 3.0);
//      取值
        Set myZset = zSetOperations.range("myZset", 0, -1);
        for (String s : myZset) {
            System.out.println(s);
        }
        System.out.println("=========================");
//        修改分数
        zSetOperations.incrementScore("myZset", "b", 10);
        //      取值
        myZset = zSetOperations.range("myZset", 0, -1);
        for (String s : myZset) {
            System.out.println(s);
        }
        System.out.println("+++++++++++++++++++++++++++++");
//        删除
        zSetOperations.remove("myZset", "a", "b");
        //      取值
        myZset = zSetOperations.range("myZset", 0, -1);
        for (String s : myZset) {
            System.out.println(s);
        }
    }

通用操作:针对不同的数据类型都可以操作:

    @Test
    public void testCommon(){
//        获取Redis中所有的key
        Set keys = redisTemplate.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }
        System.out.println("=======================");
//        判断某个key是否存在
        Boolean isExist = redisTemplate.hasKey("wlp666");
        System.out.println(isExist);
        System.out.println("------------------------------");
//        删除指定key
        redisTemplate.delete("username");
        System.out.println("++++++++++++++++++++++++");
//        获取指定key对应的value的数据类型
        DataType myset = redisTemplate.type("myset");
        System.out.println(myset.code());
    }

你可能感兴趣的:(redis,数据库,缓存)