Redis(二)

基础知识

基础使用(默认是0号数据库—共有16个数据库)

127.0.0.1:6379> select 3 //切换数据库
127.0.0.1:6379> DBSIZE //查看库的大小
127.0.0.1:6379> set name zzh //存储Key值
127.0.0.1:6379> get name //得到Value值
127.0.0.1:6379> keys * //查询所有的key值
127.0.0.1:6379> flushdb //清空当前库的数据
127.0.0.1:6379> flushall //清空全部数据库的数据

Redis是单线程

1. Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽。
2. Redis为什么单线程还那么快:
误区1:高性能的服务器一定是多线程的
误区2:多线程一定比单线程效率高
3. 核心:Redis是将所有的数据放在内存中的,所以使用单线程去操作效率就是最高的,多线程(CPU会进行上下文的切换),对于内存系统来说,没有上下文的切换效率就是最高的,多次读写都是在CPU上的,在内存的情况下,这就是最佳的方案。

数据类型

五大数据类型
Redis是一个开源 ( BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。它支持多种类型的数据结构,如字符串( string),散列( hashe),列表(list),集合(set),有序集合(Zset)与范围查询,bitmaps,hyperloglogs和地理空间( geospatial)索引半径查询。Redis 内置了复制( replication) , LUA脚本( Lua,scripting ),LRU驱动事件( LRU eviction) , 事务( transactions )和不同级别的磁盘持久化( persistence),并通过Redis哨兵( Sentinel )和自动分区( Cluster )提供高可用性( high availbility)。

String(字符串)

127.0.0.1:6379> append name xyf       //字符串追加 (如果name不存在就相当于创建一个key)
127.0.0.1:6379> strlen name           //获取字符串长度
127.0.0.1:6379> incr views            //自增+1
127.0.0.1:6379> decr views            //自减-1
127.0.0.1:6379> incrby views 10       //自增+10
127.0.0.1:6379> decrby views 10       //自减-10
127.0.0.1:6379> getrange name 0 3     //截取字符串0到3的范围数据
127.0.0.1:6379> getrange name 0 -1    //获取全部的字符串
127.0.0.1:6379> setrange name 0 hh    //0表示从指定位置替换,hh表示替换内容
127.0.0.1:6379> setex name 30 "hello" //设置name的值 30秒过期
127.0.0.1:6379> setnx mykey "redis"   //如果mykey 不存在创建 mykey ;如果存在就 创建失败
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 //批量创建多个key
127.0.0.1:6379> mget k1 k2 k3         //同时获取多个值
127.0.0.1:6379> msetnx k1 v1 k2 v2    //原子性一个失败全部失败
//对象
set user:1 {name:zhangsan,age:3} //设置一个user:1 对象值为json字符来保存一个对象!
//这里的key是一个巧妙的设计: user:{id}:{filed} ,如此设计在Redis中是完全0K了!
127.0.0.1:6379> mset user:1:name zhangsan  user:1:age 2
127.0.0.1:6379> mget user:1:name  user:1:age
getset 先get后set ---组合命令
127.0.0.1:6379> getset db redis    //如果不存在值则返回nil,但是redis会添加
127.0.0.1:6379> getset db mongodb  //如果存在值则获取原先值,但是mongodb会替换

String类似的使用场景: value除了是我们的字符串还可以是数字

1. 计数器;
2. 统计多单位的数量;
3. 粉丝数
4. 对象缓存存储!

List(集合中允许存在重复)

127.0.0.1:6379> lpush list one  //将一个值或多个值插入列表的头部
127.0.0.1:6379> rpush list two  //将一个值或多个值插入列表的尾部
127.0.0.1:6379> lrange list 0 -1  //查询list的所有值---通过区间
127.0.0.1:6379> lpop list       //移除列表的第一个数据
127.0.0.1:6379> rpop list       //移除列表的最后一个数据
127.0.0.1:6379> lindex list 0   //移除列表的某个下标的值
127.0.0.1:6379> llen list       //返回list的长度
移除值
127.0.0.1:6379> lrem list 1 value //移除list中指定个数的value
127.0.0.1:6379> ltrim list 1 2    //截取指定list中1-2区间---list集合只剩下这截取的数据
rpoplpush ---组合命令 //移除列表的最后一个元素,将他移动到新的列表中
127.0.0.1:6379> rpush mylist "hello"
127.0.0.1:6379> rpush mylist "hello1"
127.0.0.1:6379> rpush mylist "hello2"
127.0.0.1:6379> rpoplpush mylist myotherlist //移除列表的最后一个元素,将他移动到新的列表中!

lset  //将列表中指定下标的值替换为另外一个值,更新操作
127.0.0.1:6379> EXISTS list  // 判断这个列表是否存在
127.0.0.1:6379> lpush list valuel
127.0.0.1:6379> lset list 0 item  //如果存在,更新当前下标的值
127.0.0.1:6379> lset list 1 item   //如果不存在,则会报错!

linsert //将某个具体的value插入到列把你中某个元素的前面或者后面!
127.0.0.1:6379> Rpush mylist "hello"
127.0.0.1:6379> Rpush mylist "world"
127.0.0.1:6379> LINSERT mylist before "world" "other"
127.0.0.1:6379> LINSERT mylist after "world"  "new"

实际上是一个链表, before Node after ,left , right都可以插入值

1. 如果key不存在,创建新的链表;
2. 如果key存在,新增内容;
3. 如果移除了所有值,空链表,也代表不存在!;
4. 在两边插入或者改动值,效率最高。

Set(集合中不允许存在重复) 共同关注—交集

127.0.0.1:6379> sadd myset "hello"   //set集合中添加值
127.0.0.1:6379> sadd myset "world"
127.0.0.1:6379> smembers myset   //查看set集合的所有值
127.0.0.1:6379> sismember myset hello  //判断set集合中是否存在该值
127.0.0.1:6379> scard myset   //查看set集合中的个数
127.0.0.1:6379> srem myset hello  //移除set集合中的指定元素
127.0.0.1:6379> srandmember myset  //随机抽取一个元素
127.0.0.1:6379> srandmember myset 个数  //随机抽取指定个数的元素
127.0.0.1:6379> spop myset //随机删除set集合中的元素
127.0.0.1:6379> smove myset //将一个指定的值移到另一个集合
127.0.0.1:6379> sadd key1 a
127.0.0.1:6379> sadd key1 b
127.0.0.1:6379> sadd key1 c
127.0.0.1:6379> sadd key2 a
127.0.0.1:6379> sadd key2 b
127.0.0.1:6379> sadd key2 d
127.0.0.1:6379> sdiff key1 key2  //差集---key1和key2多了一个c,以第一个为基准来判断 
127.0.0.1:6379> sinter key1 key2 //交集
127.0.0.1:6379> sunion key1 key2 //并集

Hash(哈希—值变成了一个map)

127.0.0.1:6379> hset myhash field1 zzh // set一个具体的 key -value
127.0.0.1:6379> hget myhash field1     // get一个字段值
127.0.0.1:6379> hmset myhash field1 hello field2 world // set多个 key -value
127.0.0.1:6379> hmget myhash field1 field2    // get多个字段值
127.0.0.1:6379> hgetall myhash  //获取全部,以键值队的形式
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1   //删除hash指定的key字段,对应的value值也就没有了
127.0.0.1:6379> hlen myhash    //获取hash的长度
127.0.0.1:6379> hexists myhash field1   //判断hash的指定Key是否存在
127.0.0.1:6379> hkeys myhash  //获取所有的字段
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash  //获取所有的字段对应的值
1) "hello"
2) "world"
//Hash和String的本质差不多---Hash多了一个value
127.0.0.1:6379> hincr myhash field1            //自增+1
127.0.0.1:6379> hdecr myhash field1            //自减-1
127.0.0.1:6379> hincrby myhash field1 10       //自增+10
127.0.0.1:6379> hdecrby myhash field1 10       //自减-10
127.0.0.1:6379> msetnx myhash field1 hello     //原子性一个失败全部失败

hash变更的数据user name age,尤其是是用户信息之类的经常变动的信息,hash 更适合于对象的存储,String更加适合字符串存储。

Zset(有序集合—在set的基础上增加了一个值)
set排序—排行榜,成绩单排序

127.0.0.1:6379> zadd myset 1 one   //Zset添加一个值
127.0.0.1:6379> zadd myset 2 two 3 three  //Zset添加多个值
127.0.0.1:6379> zrange myset 0 -1   //Zset查找集合
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zrem salary zzh   //移除有序集合中的指定元素
127.0.0.1:6379> zcard salary    //获取集合中的个数
127.0.0.1:6379> zcount myset 1  3//获取指定区间的成员数量
//排序
127.0.0.1:6379> zrangebyscore salary -inf +inf  //显示所有的用户---从小到大
127.0.0.1:6379>  zrangebyscore salary -inf +inf withscores //显示所有的用户带有成绩---从小到大
1) "zzh"
2) "2500"
3) "xyf"
4) "5000"
5) "dzzh"
6) "7000"
127.0.0.1:6379> zrevrange salary 0 -1 withscores  //从大到小排序
1) "dzzh"
2) "7000"
3) "xyf"
4) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 6000 withscores//显示小于6000的用户---从小到大
1) "zzh"
2) "2500"
3) "xyf"
4) "5000"

三种特殊数据类型

geospatial(地理位置)

geoadd(添加位置)

//geoadd ---添加指定的位置  两级无法添加
//参数 key  值(经度,纬度,名称)
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 

geopos(定位)

// 定位城市的位置---经纬度
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918"
   2) "39.900000091670925"

geodist(两个位置直线距离)

// 判断两地之间的距离---后面可以跟单位换算
127.0.0.1:6379> geodist china:city beijing chongqi
"1464070.8051"
127.0.0.1:6379> geodist china:city beijing chongqi km
"1464.0708"

georadius(以给定的经纬度为中心,找出某一半径内的元素)好友功能

// 判断半径内的城市---城市必须是添加过的 
//110 30 以这个经纬度为中心  1000  寻找方圆1000 的目标
//withdist距离、withcoord所在位置经纬度和count 筛选指定的结果
127.0.0.1:6379>  georadius china:city 110 30 1000  km withdist withcoord count 1
1) 1) "chongqi"
   2) "341.9374"
   3) 1) "106.49999767541885"
      2) "29.529999579006592"
127.0.0.1:6379> 

georadiusbymember—地图功能

127.0.0.1:6379> georadiusbymember china:city beijing 1000 km

geohash—返回一个或多个位置元素的geohash表示

//将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近
127.0.0.1:6379> geohash china:city beijing chongqi
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

hyperloglogs(允许容错率)

基数:例:B {1,3,5,5,9}  基数是1、3、5、9 ---基数接受误差
//Redis Hyperloglog基数统计的算法!
//网页的UV (一个人访问一个网站多次,但是还是算作一个人! )
127.0.0.1:6379> pfadd mykey a b c d e f   //创建第一组元素
127.0.0.1:6379> pfadd mykey2 e f v b n m  //创建第二组元素
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 //合并两组---并集
127.0.0.1:6379> pfcount mykey3    //统计基数

bitmaps(位存储)

//统计用户信息---活跃、不活跃;登录、未登录;打卡、未打卡
365 天=365 bit 1 字节=8 bit 46个字节左右。

//Bitmaps位图,数据结构,都是操作二进制位来进行记录,就只有0和1两个状态!
//使用bitmap来记录周一到周日的打卡!
127.0.0.1:6379>  setbit sign 0 1
127.0.0.1:6379>  setbit sign 1 1
127.0.0.1:6379>  setbit sign 2 1
127.0.0.1:6379>  setbit sign 3 0
127.0.0.1:6379>  setbit sign 4 0
127.0.0.1:6379>  setbit sign 5 1
127.0.0.1:6379>  setbit sign 6 1
//查看某一天是否有打卡
127.0.0.1:6379> getbit sign 3 
//统计操作---打卡天数
127.0.0.1:6379> bitcount sign

事务

Redis事务的本质
一组命名的集合,一个事务中的所有命令都会被序列化,在事务执行的过程中,会按照顺序执行。

//一致性、顺序性和排他性
//所有命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行
------队列 set set set 队列------

1. Redis单条命令保证原子性,但是事务不保证原子性;
2. Redis没有隔离的概念。

Redis事务

开启事务
127.0.0.1:6379> multi   //开启事务
127.0.0.1:6379> discard //取消事务
命令入队
127.0.0.1:6379> set k1 v1
127.0.0.1:6379> set k2 v2
执行事务
127.0.0.1:6379> exec

1. 编译型异常,事务中所有命令都不会被执行;
2. 运行时异常,事务队列中存在语法问题,执行命名的时候,正常命令是可以执行的,错误命令抛出异常

Redis可以实现乐观锁(Watch)
Redis监视测试:

在这里插入图片描述
在这里插入图片描述
解决方案:退出监视再进入监视

127.0.0.1:6379> unwatch -    //如果事务执行失败,可以先解锁
127.0.0.1:6379> watch money  //获取最新的值,再次监视

Jedis

Jedis是Redis官方推荐的java连接工具,使用JAVA操作Redis中间件。

== 1.连接数据库==

/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/27 10:34
 */
public class TestPing {
    public static void main(String[] args) {
        // 1、new Jedis
        Jedis jedis=new Jedis("127.0.0.1",6379);
        System.out.println(jedis.ping());
    }
}

2.操作命令
3.断开连接

jedis.close();

事务
成功和失败案例:

/**
 * @author zehao
 * @version 1.0
 * @date 2020/10/27 10:34
 */
public class TestPing {
    public static void main(String[] args) {
        // 1、new Jedis
        Jedis jedis=new Jedis("127.0.0.1",6379);
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","zzh");
//        开启事务
        Transaction multi = jedis.multi();
        String s = jsonObject.toJSONString();
       // int i=1/0  ----------------------测试失败而添加的
        try {
            multi.set("user1",s);
            multi.set("user2",s);
            multi.exec();     //提交事务
        } catch (Exception e) {
            e.printStackTrace();
            multi.discard();  //抛异常放弃事务
        }finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();    //结束关闭连接
        }
    }
}

可以加乐观锁—watch

jedis.watch(s);

redis-config详解

配置文件unit单位对大小写不敏感;

在这里插入图片描述

包含

在这里插入图片描述

网络

bind 127.0.0.1     //绑定的ip
protected-mode yes      //保护模式
port 6379         //端口设置

GENERAL

daemonize yes  //以守护进程的方式运行,默认是no,我们需要自己开启为yes !
pidfile/var/run/redis_6379.pid//如果以后台的方式运行,我们就需要指定一个pid文件

#日志
# Specify the server verbosity leve1.
# This can be one of:
# debug (a lot of information, usefu1 for deve lopment/ testing)
# verbose (many rarely useful info,but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably) 生产环境
# warning (only very important / critical messages are logged)
log1eve1 notice
logfile ""    //日志的文件位置名
databases 16 // 数据库的数量,默认是16个数据库
always-show-logo yes  //是否总是显示logo

SNAPSHOTTING(快照) —RDB

//持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb .aof 
//redis是内存数据库,没有持久化会失去数据
save 900 1  //如果900s内,如果至少有一个1 key进行了修改, 我们及进行持久化操作
save 300 10 //如果300s内,如果至少有一个10 key进行了修改, 我们及进行持久化操作
save 60 10000//如果60s内,如果至少有一个10000key进行了修改,我们及进行持久化操作
//可以自己定义持久化规则

stop-writes-on-bgsave-error yes  //如果持久化出差是否继续工作
rdbcompression yes   //是否压缩rdb文件,需要消耗一些cpu
rdbchecksum yes    //保存rdb文件的时候,检查校验
dir ./       //rdb文件保存的目录

REPLICATION(主从复制)

SECURITY(安全)

//给redi设计密码
config set requirepass 密码    
//设置完密码通过 auth 密码  进入

CLIENTS

maxclients 10000            //设置能连接 上redis的最大客户端的数量
maxmemory <bytes>           //redis 配置最大的内存容量
maxmemory-policy noeviction  // 内存到达上限之后的处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU (默认值)
2、allkeys-lru :删除lru算法的key
3、volatile-random: 随机删除即将过期key
4、allkeys-random: 随机删除
5、volatile-ttl :删除即将过期的
6、noeviction :
永不过期, 返回错误

APPEND ONLY MODE —AOF

appendonly no   //默认不开启AOF方式,默认使用的是RDB方式
appendfilename "appendonly.aof"   //持久化的文件名字


# appendfsync always   //每次修改都会sync,消耗性能
appendfsync everysec   //每秒执行一次sync,可能会丢失这1s的数据
# appendfsync no     //不执行sync,操作系统自己同步数据,速度最快


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值