Redis学习笔记

什么是Redis

Redis是一个可基于内存亦可持久化的日志型、Key-Value的高性能nosql数据结构存储系统,可用作数据库、缓存、消息中间件。

安装Rides

1、使用宝塔安装程序
2、Linux命令行

  • 下载安装包 redis -5.0.8并上传到服务器

  • 解压Redis安装包

    tar -zxvf redis-5.0.8.tar.gz
    
  • redis需要c++环境支持,安装gcc环境

    yum install gcc-c++
    
  • 安装redis环境

    make
    
    make install
    
  • 进入redis环境的路径

    cd /usr/local/bin
    
  • 复制一份redis.conf到本目录,以后直接操作该配置文件

    cp /www/server/redis/redis.conf config
    
  • 修改配置文件redis.config: daemonize no >daemonize yes(宝塔不用改)

    vim config/redis.conf
    

启动Redis

redis-server config/redis.conf

连接Redis

redis-cli -p 6379
  • 输入ping如果输出PONG代表着测试成功

  • 查看Rides启动进程

    ps -ef|grep redis
    
  • 关闭Rides服务

    shutdown
    exit
    

Redis基础知识

  • redis默认有16个数据库,默认使用的是第0个数据库,在redis.conf文件中可查看:database 16

  • redis所有命令可以去Rides中文官网 查看

    • 切换数据库命令(切换到第二个数据库)

      127.0.0.1:6379> select 2
      OK
      127.0.0.1:6379[2]> 
      
    • 查看数据库大小

      127.0.0.1:6379> dbsize
      (integer) 5
      127.0.0.1:6379> 
      
    • 存值

      127.0.0.1:6379> set name yijin
      OK
      127.0.0.1:6379> 
      
    • 取值

      127.0.0.1:6379> get name
      "yijin"
      127.0.0.1:6379> 
      
    • 查看key的类型

      127.0.0.1:6379[1]> type name
      string
      
    • 设置值过期时间:EXPIRE key seconds

      设置key为name的值在10秒后过期

      127.0.0.1:6379[1]> expire name 10
      (integer) 1
      
    • 查看值过期时间:ttl key
      查看key为name的值在5秒后过期

      127.0.0.1:6379[1]> ttl name
      (integer) 5
      
    • 查看该数据库中是否有key为name的值(1:存在 0:不存在)

      127.0.0.1:6379[2]> EXISTS name
      (integer) 0
      127.0.0.1:6379[2]> 
      
    • 移除key为name的值:move key 索引(1:成功 0:失败)

      127.0.0.1:6379[2]> move name 1
      (integer) 1
      
  • 查看该数据库中所有的key

    127.0.0.1:6379> keys *
    		1) "name"
    		2) "mylist"
    		3) "key:__rand_int__"
    		4) "counter:__rand_int__"
    		5) "myset:__rand_int__"
    		127.0.0.1:6379> 
    
  • 清空该数据库

    127.0.0.1:6379[2]> flushdb
    OK
    127.0.0.1:6379[2]> 
    
  • 清空所有数据库

    127.0.0.1:6379[2]> FLUSHALL
    OK
    127.0.0.1:6379[2]> 
    

五大数据类型

string类,可用于记录某些频繁的值

1. String

  • 批量设置值:mset(如果数据库有相同的键则会设置失败)

    127.0.0.1:6379[2]> mset name "yijin" age 10 sex "nv"
    OK
    127.0.0.1:6379[2]> keys *
    1) "sex"
    2) "age"
    3) "name"
    
  • 批量获取值:mget

    127.0.0.1:6379[2]> mget name age sex
    1) "yijin"
    2) "10"
    3) "nv"
    
  • 追加字符串:append key “vaule”,如果key不存在则新建一个值

    127.0.0.1:6379[1]> append name "hello"
    (integer) 10
    
  • 获取字符串长度

    127.0.0.1:6379[1]> strlen name
    (integer) 10
    
  • 值+1(i++)

    127.0.0.1:6379[1]> incr age
    (integer) 1
    
    
  • 值-1(i–)

    127.0.0.1:6379[1]> decr age
    (integer) 0
    
    
  • 值+n: incrby age n

    127.0.0.1:6379[1]> incrby age 10
    (integer) 10
    
    
  • 值 - n: decrby age n

    127.0.0.1:6379[1]> decrby age 5
    (integer) 5
    
    
  • 字符串范围: getrange

    127.0.0.1:6379[2]> getrange name 1 3
    "iji"
    
  • 修改字符串范围: setrange

    127.0.0.1:6379[2]> setrange name 3 1
    (integer) 5
    
  • 设置一个值并设置过期时间: setex

    127.0.0.1:6379[2]> setex key1 10 "hello"
    OK
    127.0.0.1:6379[2]> get key1
    "hello"
    127.0.0.1:6379[2]> ttl key1
    (integer) -2
    127.0.0.1:6379[2]> get key1
    (nil)
    
  • 不存在则设置值: setnx(在分布式锁经常使用)

    127.0.0.1:6379[2]> keys *
    1) "age"
    2) "name"
    127.0.0.1:6379[2]> setnx name "hekk"
    (integer) 0
    
  • getset组合命令(如果没有值则返回nil再设置值,如果存在则获得值再赋予新的值)

    127.0.0.1:6379[2]> getset name "yijing"
    "yijin"
    127.0.0.1:6379[2]> get name
    "yijing"
    

2. List

基本的数据类型,list其实是一个链表结构
如果key不存在,创建一个list,存在则添加一个元素
能同时在左右两端同时操作元素,既可以作为队列,又可以作为栈
所有的list命令都为l开头
  • 放入:LPUSH (将一个或多个值放入列表的左边) RPUSH(将一个或多个值放入列表右边)

    127.0.0.1:6379[2]> LPUSH list1 one two three
    (integer) 3
    127.0.0.1:6379[2]> rpush list1 four five
    (integer) 5
    127.0.0.1:6379[2]> lrange list1 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "four"
    5) "five"
    
  • 移除:LPOP (移除左边的一个值) RPOP(移除右边的一个值)

    127.0.0.1:6379[2]> lrange list1 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "four"
    5) "five"
    127.0.0.1:6379[2]> lpop list1
    "three"
    127.0.0.1:6379[2]> rpop list1
    "five"
    
  • 获取:LRANGE(通过具体区间获取值,如果想获取所有可用0 -1)

    127.0.0.1:6379[2]> LRANGE list1 0 1
    1) "three"
    2) "two"
    
    
  • 获取list下标的值:lindex

    127.0.0.1:6379[2]> lindex list1 1
    "one"	
    
  • 获取list长度:llen

    127.0.0.1:6379[2]> llen list1
    (integer) 3
    
  • 移除list中的元素:lrem(指定个数)

    127.0.0.1:6379[2]> lrem list1 1 one
    (integer) 1
    
  • 把一个list中最后一个元素移动到另一个list中:rpoplpush

    127.0.0.1:6379[2]> lrange list1 0 -1
    1) "two"
    2) "four"
    127.0.0.1:6379[2]> rpoplpush list1 list2
    1)"four"
    127.0.0.1:6379[2]> lrange list2 0 -1
    1) "four"
    
  • 修改该下标的值:lset(没有下标则报错)

    127.0.0.1:6379[2]> lset list2 0 fours
    OK
    127.0.0.1:6379[2]> lrange list2 0 -1
    1) "fours"
    
  • 插入值:linsert(before|after)

    127.0.0.1:6379[2]> lrange list2 0 -1
    1) "five"
    2) "fours"
    127.0.0.1:6379[2]> linsert list2 after fours three
    (integer) 3
    127.0.0.1:6379[2]> lrange list2 0 -1
    1) "five"
    2) "fours"
    3) "three"
    

3. Set

无序不重复集合,所有命令都由S开头

  • 添加元素:sadd , 查看set中的元素:smembers,查看set大小:scard

    127.0.0.1:6379[2]> sadd set1 hello
    (integer) 1
    127.0.0.1:6379[2]> smembers set1
    1) "hello"
    127.0.0.1:6379[2]> scard set1
    (integer) 3
    
  • 判断集合中是否存在该元素:sismember

    127.0.0.1:6379[2]> sismember set1 hello
    (integer) 1
    
  • 移除集合中的元素: srem

    127.0.0.1:6379[2]> srem set1 hello
    (integer) 1
    
  • 移动一个元素到另一个集合中

    127.0.0.1:6379[2]> smove set1 set2 two
    (integer) 1
    127.0.0.1:6379[2]> smembers set2
    1) "two"
    
  • 随机获取集合中指定个数元素:srandmember

    127.0.0.1:6379[2]> srandmember set1 2
    1) "two"
    2) "three"
    
  • 随机删除指定个数元素:spop

    127.0.0.1:6379[2]> spop set1 
    "one"
    127.0.0.1:6379[2]> smembers set1
    1) "three"
    2) "two"
    
  • 获取另一个集合中不同的元素:sdiff (差集)

    127.0.0.1:6379[2]> sdiff set1 set2
    1) "one"
    2) "three"
    
  • 获取两个集合中相同的元素:sinter (交集)

    127.0.0.1:6379[2]> sinter set1 set2
    1) "two"
    
  • 获取两个集合中所有元素:sunion (并集)

    127.0.0.1:6379[2]> sunion set1 set2
    1) "one"
    2) "three"
    3) "two"
    

4. Hash

哈希,key-map,一般用于存储对象,命令以h开头

  • 设置hash值:hset ,设置多个hash值:hmset

    127.0.0.1:6379[2]> hset map1 name yijin
    (integer) 1
    127.0.0.1:6379[2]> hmset map1 age 16 sex man
    OK
    
  • 获取hash值:hget,获取多个值:hmget

    127.0.0.1:6379[2]> hget map1 name
    "yijin"
    127.0.0.1:6379[2]> hmget map1 name age
    1) "yijin"
    2) "16"
    
  • 获取hash中所有的键值:hgetall

    127.0.0.1:6379[2]> hgetall map1
    1) "name"
    2) "yijin"
    3) "age"
    4) "16"
    5) "sex"
    6) "man"
    
  • 获取hash中所有的键:hkeys , 获取hash中所有的值:hvals

    127.0.0.1:6379[2]> hkeys map1
    1) "name"
    2) "age"
    127.0.0.1:6379[2]> hvals map1
    1) "yijin"
    2) "16"
    
  • 删除hash中的值:hdel

    127.0.0.1:6379[2]> hdel map1 sex
    (integer) 1
    
  • 获取hash的大小:hlen

    127.0.0.1:6379[2]> hlen map1
    (integer) 2
    
  • 判断hash中是否拥有该值

    127.0.0.1:6379[2]> hexists map1 name
    (integer) 1
    

5. Zset

有序集合,在set的基础上增加一个值

  • 设置值:zadd

    127.0.0.1:6379[2]> zadd zset1 1 one 2 two
    (integer) 2
    
  • 获取值:zrange,降序:zrevrange

    127.0.0.1:6379[2]> zrange zset1 0 -1
    1) "one"
    2) "two"
    127.0.0.1:6379> zrevrange zset1 0 -1 withscores
    1) "two"
    2) "2"
    3) "one"
    4) "1"
    
  • 获取区间内的值:zrangebyscore(-inf:-无穷,+inf:+无穷)

    127.0.0.1:6379> zrangebyscore zset1 -inf +inf
    1) "one"
    2) "two"
    127.0.0.1:6379> zrangebyscore zset1 -inf +inf withscores
    1) "one"
    2) "1"
    3) "two"
    4) "2"
    
  • 移除元素:zrem

    127.0.0.1:6379> ZREM zset1 one
    (integer) 1
    
  • 获取有序集合大小:zcard

    127.0.0.1:6379> ZCARD zset1
    (integer) 1
    
  • 获取指定区间的总数:zcount

    127.0.0.1:6379> ZCOUNT zset1 0 2
    (integer) 1
    

三种特殊数据类型

1、geospatial 地理位置

底层由zset实现,具体使用规则:https://www.redis.net.cn/order/3685.html

  • 添加数据:geoadd,查询城市位置: http://www.jsons.cn/lngcode注:两极无法添加,一般由程序直接导入,参数:key 值(纬度,经度,地名)

    127.0.0.1:6379[2]> geoadd china:city 116.40 39.90 beijin
    (integer) 1
    
  • 查找数据:geopos

    127.0.0.1:6379[2]> GEOPOS china:city beijin
    1) 1) "116.39999896287918091"
       2) "39.90000009167092543"
    
  • 查询两个地理位置的距离:geodist

    127.0.0.1:6379[2]> geodist china:city changshaa shanghai km
    "886.7051"
    127.0.0.1:6379[2]> geodist china:city shanghai beijin km
    "1067.3077"
    
  • 查询该坐标半径以内中所有元素

    127.0.0.1:6379[2]> georadius china:city 110 30 1000 km
    1) "changshaa"
    127.0.0.1:6379[2]> georadius china:city 110 30 1000 km  withcoord
    1) 1) "changshaa"
    2) 1) "112.98227995634078979"
    2) "28.19409000030395163"
    127.0.0.1:6379[2]> georadius china:city 110 30 10000 km  withcoord count 1
    1) 1) "changshaa"
    2) 1) "112.98227995634078979"
    2) "28.19409000030395163"
    
  • 查询该元素半径以内中所有元素:georadisbymember

    127.0.0.1:6379[2]> GEORADIUSBYMEMBER china:city shanghai 5000 km 
    1) "changshaa"
    2) "shanghai"
    3) "beijin"
    
  • 查询一个或多个元素的hash值:geohash

    127.0.0.1:6379[2]> GEOHASH china:city shanghai changshaa beijin
    1) "wtw3sjt9vg0"
    2) "wt026ux4mz0"
    3) "wx4fbxxfke0"
    

2、hyperloglog基数统计

redis2.8.9版本更新了hyperloglog数据结构,能作为网页的UV(同一账号多次访问只能算作一次访问),优点:存储2^64个不同元素只消耗12kb内存,能节省内存空间,缺点:不精确,会有一定的误差,0.81%错误率

  • 添加元素:pfadd

    127.0.0.1:6379[2]> pfadd demo1 a b b c c d d
    (integer) 1
    
  • 查询基数估算值:pfcount

    127.0.0.1:6379[2]> PFCOUNT demo1 
    (integer) 4
    
  • 将多个hyperloglog合成一个(并集+去从):pfmerge

    127.0.0.1:6379[2]> PFMERGE demo3 demo1 demo2
    OK
    127.0.0.1:6379[2]> keys *
    1) "demo3"
    2) "demo2"
    3) "demo1"
    127.0.0.1:6379[2]> PFCOUNT demo3
    (integer) 5
    

3、bigmaps位图运算

统计用户活跃度,签到,打卡功能,bigmaps位图是直接操作二进制

  • 设置值:setbit

    127.0.0.1:6379[2]> setbit bit1 1 1
    (integer) 0
    127.0.0.1:6379[2]> setbit bit1 2 1
    (integer) 0
    127.0.0.1:6379[2]> setbit bit1 3 0
    (integer) 0
    
  • 获取值:getbit

    127.0.0.1:6379[2]> getbit bit1 2
    (integer) 1
    127.0.0.1:6379[2]> getbit bit1 3
    (integer) 0
    
  • 统计总数:bitcount

    127.0.0.1:6379[2]> BITCOUNT bit1
    (integer) 2
    

事务

Redis事务本质:一组事务的集合!一个事务中的所有命令都会被序列化,在事务的执行过程中,会按照顺序执行。会按照一次性、顺序性、排他性去执行列的命令
Redis事务没有隔离级别的概念!
所有命令在事务中,并没有直接执行,只有发起了执行命令才会执行!
Redis只有单条命令保持原子性,但事务是不保持原子性的!
Redis事务

  • 开启事务(multi)————命令入队————执行事务(exec)

    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> set demo1 one
    QUEUED
    127.0.0.1:6379[2]> set demo2 two
    QUEUED
    127.0.0.1:6379[2]> get demo1
    QUEUED
    127.0.0.1:6379[2]> get demo2
    QUEUED
    127.0.0.1:6379[2]> exec
    1) OK
    2) OK
    3) "one"
    4) "two"
    
  • 取消事务:discard

    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> set demo3 three
    QUEUED
    127.0.0.1:6379[2]> set demo4 four
    QUEUED
    127.0.0.1:6379[2]> DISCARD
    OK
    
  • 事务中的异常:1、编译异常 :事务中命令有错,整个事务都会取消

    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> set demo1 one
    QUEUED
    127.0.0.1:6379[2]> getset demo1
    (error) ERR wrong number of arguments for 'getset' command
    127.0.0.1:6379[2]> set demo2 two
    QUEUED
    127.0.0.1:6379[2]> exec
    (error) EXECABORT Transaction discarded because of previous errors
    
  • 事务中的异常:2、运行异常 :事务队列中存在语法性错误,只影响错误的那个队列,其他命令正常运行

    127.0.0.1:6379[2]> lpush list one two three
    (integer) 3
    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> get list
    QUEUED
    127.0.0.1:6379[2]> set demo3 hello
    QUEUED
    127.0.0.1:6379[2]> get demo3
    QUEUED
    127.0.0.1:6379[2]> exec
    1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    2) OK
    3) "hello"
    
  • 监控(watch):测试多线程操作值时,watch可当做redis乐观锁操作
    悲观锁:思想很悲观,不管任何操作都会上锁
    乐观锁:思想很乐观,更新数据时去判断是否有人修改过这个数据,获取version,更新的时候比较version
    正常情况:

    127.0.0.1:6379[2]> set money 100
    OK
    127.0.0.1:6379[2]> set personl 0
    OK
    127.0.0.1:6379[2]> watch money
    OK
    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> DECRBY money 10
    QUEUED
    127.0.0.1:6379[2]> incrby personl 10
    QUEUED
    127.0.0.1:6379[2]> exec
    1) (integer) 90
    2) (integer) 10
    

    失败情况:当线程a修改加锁的数据的时候,线程b更新了该数据,这时线程a提交事务时则会失败,事务失败则需要手动解除锁 unwatch:解除锁

    127.0.0.1:6379[2]> set money 100
    OK
    127.0.0.1:6379[2]> watch money
    OK
    127.0.0.1:6379[2]> multi
    OK
    127.0.0.1:6379[2]> decrby money 50
    QUEUED
    127.0.0.1:6379[2]> exec
    (nil)
    

    该线程在线程a操作money但未提交时修改了money,导致线程a后面提交为nil

    127.0.0.1:6379[2]> incrby money 1000
    (integer) 1100
    

Jedis

官方推荐的Java连接开发工具,是一个Java操作Redis的中间件
步骤:

1、导入依赖
<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
 </dependencies>
2、编码测试(输出PONG代表成功),Redis数据类型操作命令都能Jedis实例中找到对应方法!
public class RedisTest {
    public static void main(String[] args) {
        Jedis jedis=new Jedis("云服务器IP",6379);
        System.out.println(jedis.ping());
    }
}

SpringBoot整合Redis

1、导入依赖

<dependency>   
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> 
</dependency>

2、配置连接

spring.redis.host=127.0.0.1 
spring.redis.port=6379

3、测试

@SpringBootTest 
class Redis02SpringbootApplicationTests {
    @Autowired    
    private RedisTemplate redisTemplate;
    @Test    
    void contextLoads() {
        redisTemplate.opsForValue().set("name","yijin"); 
        System.out.println(redisTemplate.opsForValue().get("name"));
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值