文章目录

  • 前言
  • 一、基本命令
  • 二、数据类型
    • 1.String
    • 2.List 集合
    • 3.Set 集合
    • 4.Hash集合
    • 5.Zset集合
    • 6.Bitmaps
    • 7.HyperLogLog
    • 8.Geospatial
  • 三、功能实例
    • 1.事务处理
    • 2.测试工具
      • 安装ab
      • 安装Jmeter
    • 3.经典秒杀问题
      • 事务+乐观锁(Watch)
    • 4.备份redis 并恢复(AOP,RDB)
      • RDB
      • AOP
  • 四、Redis进阶
    • 1.主从复制
      • 主服务器
      • 从服务器
    • 2.反客为主
    • 3.哨兵模式(自动替换)
    • 4.集群
      • 配置文件
      • 启动命令
      • 注意
      • 基本命令
    • 常见问题
      • 缓存穿透
    • 缓存击穿
    • 缓存雪崩
    • 分布式锁

前言

本篇文章对Redis的数据类型、基本使用以及常见的错误都有涉猎,是本人学习Redis每一阶段的记录,内容可能有点多。耐心看下去,相信你会有所收获。


一、基本命令

代码如下:

redis-server /etc/redis.conf  //后面是一个修改后的配置文件,支持后台启动ps -ef | grep redis //查看是否启动,命令详解:
ps(Process Status)://进程查看-e 显示所有进程。 -f 全格式。 -h 不显示标题。 -l 长格式。 -w 宽输出。 -a 显示终端上的所有进程,包括其他用户的进程。 -r 只显示正在运行的进程。 -u 以用户为主的格式来显示程序状况。 -x 显示所有程序,不以终端机来区分。
grep //查找命令,支持正则表达式,也可用于文本搜索
| //管道命令,使ps与grep同时执行。
链接服务redis-cli -a 密码select num(0-16)//切换数据库dbsize //数据库的key数量flushdb //清空当前数据库flushall //清空所有keys * //查看所有的key,*用于匹配exists key  //判断key是否存在type key //查看key的类型del key //删除指定keyunlink key 非堵塞删除,之后进行删除操作expire key 10//设置key的过期时间为10秒ttl key //查看还有多长时间过期,-1永不过期,-2已经过期

二、数据类型

1.String

添加/修改
set key valuesetnx key value //只有不存在,才能添加incr key 加一decr key 减一incrby/decrby key value //跨这步子加减mset key1 value1 key2 value2...//同时设置多个msetnx key1 value1 key2 value2...//同时设置多个,key不可存在mget key1 key2 ...//同时获取多个getrange key start end //获取key值范围内的值setrange key start value //会用后面的value替换start开始之后的数据setex key time value //设置键的同时,添加过期时间getset key value //以新换旧,得到值追加
append key value获得长度
strlen key

2.List 集合

 插入
lpush/rpush key value value1 value2 //左边,右边插入值rpoplpush key1 key2 从key1右边取值,存放到key2左边linsert key before/after value newvalue 在 value前面、后面 插入newvaluelrem key n value //从左到右删除n个值为value的数据lset key index value 替换操作获取
lrange key 0 -1 //获取所有lpop/rpop key count //从左边、右边吐出值,值没有后key消失lindex key index //按照索引获取元素(左到右)llen key //获取列表的长度

3.Set 集合

添加
sadd key value value1 value2查询
smembers key 查询键值下所有的数据删除
srem key value(more) 删除key中值为value的数据del key 删除该键sismember key value 判断key值中是否含有valuescard key 返回key下集合的元素个数 spop key 随机吐出一个srandmember key n 随机出来n个值,但是不删除smove source(key) destination(key) value sinter key1 key2 两个集合的交集sunion key1 key2 两个集合的并集sdiff key1 key2 两个集合的差集,包含key1中,不包含key2中

4.Hash集合

 添加
hset key field value hmset key field1 value1 field2 value2hsetnx key field value 仅当不存在field时,才能够正确添加查询
hget key field功能
hexists key field 查看key下field是否存在hkeys key 该key下所有的fieldhvals key 该hash集合所有的valuehincrby/hdecrby  key field num 值的增加删除

5.Zset集合

添加
zadd key score1 value1 score2 value2查询
zrange key start(0) end(-1) (withscores)查询所有(带值)zrangebyscore topno min max (withscores) 查询min-max之间的zrevrangebyscore topno max min   (withscores) 从大到小功能
zincrby key num value 在key下value上增加num,不存在的话就添加zrem key value 删除key下,value的元素zcount key min max 统计之间的个数zrank key value 返回排名,从0开始

6.Bitmaps

添加
setbit key index value获取
getbit key index 返回的是值

7.HyperLogLog

用来统计不同数据的个数

添加
pfadd key value功能
pfcount key 统计key中的数量pfmerge newkey key1 key2 将key1与key2中的数据结合保存到newkey

8.Geospatial

添加
geoadd key 经度 维度 地区名(geoadd china:city 121.47 31.23 shanghai) 可添加多个获取
geopos key 地区名(geopos china:city shanghai) 获得经纬度geodist key 地区1 地区2 单位(geodist china:city shanghai beijing km)地区1与2之间的距离georadius key 经度 维度 范围 单位(georadius china:city 110 30 1000 km) 以这个经纬度为中心,方圆1000km包含的城市

三、功能实例

1.事务处理

开启事务队列
multi + 之后进行的操作 执行队列中的任务
exec 终止组队
discard

2.测试工具

以下两种测试工具任选一个使用就行,ab是linux系统下的,Jmeter是Windows下的,个人感觉还是ab好用。

安装ab

yum install httpd-toolsab -n 1000 -c 100 -p ~/postfile -T application/x-www-form-urlencoded http://192.168.133.235:8080/redis
~/postfile根目录下的postfile文件(pid=0101&),也就是保存该接口需要的返回数据(POST类型)。1000个线程,100个并发。

安装Jmeter

这里是详细的安装步骤和使用方法,实测有效。

3.经典秒杀问题

不加处理的基础逻辑会产生超卖超时问题,以下是解决方式:
事务+乐观锁(Watch)可以解决超卖超时问题,但是还会有库存遗留和连接超时问题
连接超时可以通过连接池解决
库存遗留可以通过LUA解决

事务+乐观锁(Watch)

public static boolean doSecKill(String uid,String pid){if (pid==null||uid==null){return false;}
//        链接Jedis
//        Jedis jedis=new Jedis("192.168.180.98",6379);
//        使用连接池,解决连接超时问题JedisPool poolInstance = JedisPoolUtil.getJedisPoolInstance("192.168.133.98", 6379, 60000,"112233");Jedis jedis = poolInstance.getResource();String kcKey="sk:"+pid+":qt";String userKey="sk:"+pid+":user";//        监视库存,乐观锁jedis.watch(kcKey);String kc = jedis.get(kcKey);if (kc==null){System.out.println("还没有开始");jedis.close();return false;}if (jedis.sismember(userKey, uid)){System.out.println("已经成功,不能再次");jedis.close();return false;}if (Integer.parseInt(kc)<=0){System.out.println("秒杀结束");jedis.close();return false;}
//        使用事务,原子性Transaction multi=jedis.multi();
//        组队multi.decr(kcKey);multi.sadd(userKey,uid);
//        执行List<Object> results = multi.exec();if (results==null||results.size()==0){System.out.println("秒杀失败");jedis.close();return false;}System.out.println("秒杀成功");jedis.close();return true;}public static String geyUid(){Random random=new Random();StringBuilder sb=new StringBuilder();for (int i=0;i<4;i++){sb.append(random.nextInt(10));}return sb.toString();}
自己写了一个常用的连接池,如果感觉不错的话,可以直接拿去使用:
public class JedisPoolUtil {//双重检验private static volatile JedisPool jedisPool=null;private static volatile JedisSentinelPool jedisSentinelPool=null;private JedisPoolUtil() {}public static JedisPool getJedisPoolInstance(String url,int port,int timeout,String password){if (null==jedisPool){synchronized (JedisPoolUtil.class){if (null==jedisPool){jedisPool=new JedisPool(getJedisPoolConfig(),url,port,timeout,password);}}}return jedisPool;}//哨兵模式public static JedisPool getJedisPoolInstance1(Set<String> set,String password){if (null==jedisSentinelPool){synchronized (JedisPoolUtil.class){if (null==jedisSentinelPool){jedisSentinelPool=new JedisSentinelPool("mymaster",set,getJedisPoolConfig(),password);}}}return jedisPool;}//    集群public JedisCluster getJedisCluster(String url,int port){Set<HostAndPort> set=new HashSet<>();set.add(new HostAndPort(url,port));return new JedisCluster(set);}private static JedisPoolConfig getJedisPoolConfig(){JedisPoolConfig poolConfig=new JedisPoolConfig();poolConfig.setMaxTotal(200);//最大可用连接数poolConfig.setMaxIdle(32);//最大闲置连接数poolConfig.setMinIdle(32);//最小闲置连接数poolConfig.setMaxWaitMillis(100*1000);//等待时间poolConfig.setBlockWhenExhausted(true);//时间耗尽是否等待poolConfig.setTestOnBorrow(true);//取连接的时候ping一下return poolConfig;}public static void release(JedisPool jedisPool, Jedis jedis){if(null!=jedis){jedisPool.returnResource(jedis);}}
}

LUA解决库存遗留问题

static String secKellScript = "local userid=KEYS[1];\n" +"local prodid=KEYS[2];\n" +"local qtkey=\"sk:\"..prodid..\":qt\";\n" +"local userkey=\"sk:\"..prodid..\":usr\";\n" +"local userExists=redis.call(\"sismember\",userkey,userid);\n" +"if tonumber(userExists)==1 then\n" +"return 2;\n" +"end\n" +"local num=redis.call(\"get\",qtkey);\n" +"if tonumber(num)<=0 then \n" +"return 0;\n" +"else\n" +"redis.call(\"decr\",qtkey);\n" +"redis.call(\"sadd\",userkey,userid);\n" +"end \n" +"return 1;";public static  boolean doDecKill(String userid,String pid){JedisPool poolInstance = JedisPoolUtil.getJedisPoolInstance("192.168.133.98", 6379, 60000,"lgy112233");Jedis jedis = poolInstance.getResource();String sha1=jedis.scriptLoad(secKellScript);Object result = jedis.evalsha(sha1, 2, userid, pid);String re = String.valueOf(result);if ("0".equals(re)){System.err.println("已经抢空");}else if ("1".equals(re)){System.err.println("抢购成功");}else if ("2".equals(re)){System.err.println("已经抢过");}else {System.err.println("抢购繁忙");}jedis.close();return  true;}

4.备份redis 并恢复(AOP,RDB)

以下两种测试工具任选一个使用就行,ab是linux系统下的,Jmeter是Windows下的,个人感觉还是ab好用。

RDB

手动备份命令:
save 和 bgsave
推荐使用后者,因为此时服务器还可以提供服务。save 300 10   //表示如果距离上一次创建RDB文件已经过去了300秒,并且服务器的所有数据库总共已经发生了不少于10次修改,那么自动执行BGSAVE命令

流程
1.cp 要备份的文件 备份的文件名
2.rm -rf 要备份的文件
3.mv 备份的文件 要备份的文件名,说白了就是替换掉原文件

AOP

appendonly yes
appendfilename "appendonly.aof"
sudo /etc/init.d/redis-server restart 重启服务redis-check-aof --fix appendonly.aof (文件名字)  修复AOP文件重写触发命令BGREWRITEAOF

四、Redis进阶

1.主从复制

复制原来的配置文件到一个新的位置,同时新建几个配置文件作为从服务器的配置文件,其中只能有一个主服务器,其他的均为从服务器。例如:

主服务器

include redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb

从服务器

include redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
slaveof 127.0.0.1 6379
masterauth 112233

连接服务器:redis-cli -p 6380(端口) -a 密码

查看状态:info replication

2.反客为主

在从服务器端输入 slaveof no one,当主服务器死亡后,此从服务器会成为主服务器。

3.哨兵模式(自动替换)

新建一个sentinel.conf文件

sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster lgy112233

在命令行启动:redis-sentinel sentinel.conf

4.集群

配置文件

1.主配置文件不变,复制过来一份

2.各端口配置文件,不同的地方就是端口号

include redis.conf
pidfile "/var/run/redis_6379.pid"
port 6379
dbfilename "dump6379.rdb"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
masterauth "112233"

启动命令

来到redis安装包中的src中,打开命令行

redis-cli -a lgy112233  --cluster create --cluster-replicas 1 192.168.184.98:6379 192.168.184.98:6380 192.168.184.98:6381 192.168.184.98:6389 192.168.184.98:6390 192.168.184.98:6391

注意

启动端口前把所有的缓存文件删除,保证每个端口的keys * 都是空的。不然会报错误:

Node 192.168.184.98:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

基本命令

多个:mset name{user} lucy age{user} 20 adress{user} china

查询某个键插槽值:cluster keyslot 值

查询任一插槽中值得数量:cluster countkeysinslot 插槽值

查询插槽中值:cluster getkeysinslot 插槽值 num

查看状态:cluster nodes

配置某段插槽宕机后,整个系统的状态:

redis.conf中的

cluster-require-full-coverage yes 整个集群挂掉 no 其他插槽依旧可以

常见问题

缓存穿透

redis中没有,命中率低,大量请求到数据库。

缓存击穿

redis中某个key过期,突然这个key的访问量突然加大,数据库访问量突然加大。

缓存雪崩

在极少的时间段,大量key集中过期的情况。

解决方式:随机缓存时间。

分布式锁

setnx key value 上锁

del key

expire key time 设置过期时间

set key value nx ex 12 同时设置锁和过期时间

Redis保姆级学习教程相关推荐

  1. Docker保姆级学习教程

    文章目录 1.什么是Docker 1.1.容器技术 1.2.容器与虚拟机比较 1.3.Docker特点 1.更高效的利用系统资源 2.更快速的启动时间 3.一致的运行环境 4.持续支付和部署 5.更轻 ...

  2. 保姆级黑苹果教程:让你的Ryzen+A卡用上最新版本的MacOS

    保姆级黑苹果教程:让你的Ryzen+A卡用上最新版本的MacOS 0x00:前言 教程那么多了,为什么要还要写?(博主的废话,可跳过) 几个月前,博主(学生狗一枚)在用GoodNotes(一个很有名的 ...

  3. [黑群晖]DSM7.1 ds3617xs 志强e3 1265lv3 b85保姆级安装教程

    [黑群晖]DSM7.1 ds3617xs 志强e3 1265lv3 b85保姆级安装教程 鉴于网上几乎没有志强cpu安装的教程,我走了相当多的弯路,不一定适合你的cpu,但是有一些小问题的解决办法,可 ...

  4. yolov5 6.1官方模板TensorRT加速保姆级图文教程

    加速的基础流程今年春季已经写好了,可以完美复现加速. 需要补充的是运行export.py的报错,加一句: pip install onnx 这会写教程的时候,电脑是昨天新做的系统,没有python以及 ...

  5. PID 控制保姆级培训教程下-全国大学生电子设计大赛赛前必备

    紧接上回<PID 控制保姆级培训教程上-全国大学生电子设计大赛赛前必备> http://t.csdn.cn/TY4eB 上回介绍到 书接上回,实操设计,干货满满.... 3 数字控制器的模 ...

  6. matlab按图像边缘抠图_不会抠图?保姆级抠图教程!手把手教你抠图(一)

    本篇教程由浅入深的了解ps当中的每一个抠图工具以及原理,帮助大家提升工作效率的同时,还能打破很多同学对抠图的一些刻板印象. 抠图是我们几乎每一天都能接触到的工作,说到最好用的抠图工具,有的同学觉得是魔 ...

  7. Promox VE安装黑群晖保姆级图文教程

    本教程是PVE家用All in one一体机方案的保姆级攻略之一,将详细介绍在PVE虚拟环境用xpenology大神Jun的引导镜像引导安装黑群晖的详细过步骤. PVE虚拟环境的构建请移步:Proxm ...

  8. Alexa对接开发java版(保姆级图文教程)

    文章目录 前言 一.准备工作? 二.使用步骤 1.登陆科技账号创建函数 2.登陆开发在账号创建技能 3.测试 总结 前言 提示:真正的保姆级图文教程,因本人java开发,准备写篇java+node版本 ...

  9. Typora 保姆级安装教程

    Typora 保姆级安装教程 文章目录 Typora 保姆级安装教程 下载 安装 配置 更改配置文件 base.user.css github.css 更改设置 设置图床 用法 下载 https:// ...

最新文章

  1. linux shell数据重定向(输入重定向与输出重定向)详细分析
  2. .Net程序员学用Oracle系列(10):系统函数(中)
  3. oracle cube排序,Oracle rollup cube 用法
  4. 南宁师范大学计算机与信息工程学院研究生,南宁师范大学计算机与信息工程学院(专业学位)职业技术教育保研...
  5. 1063 Set Similarity
  6. java启动100线程_Java启动新线程的几种方式(Runnable、Callable、CompletableFuture)
  7. Mysql-innoDB存储引擎(事务,锁,MVCC)
  8. JavaScript点击事件-一个按钮触发另一个按钮
  9. Doc2Vec,Word2Vec文本相似度 初体验。
  10. C#编译器优化那点事
  11. poj Muddy Fields
  12. 【华为大咖分享】9.2018加速度,洞悉DevOps高效能组织的秘密(后附PPT下载地址)
  13. HDU1229 还是A+B【水题】
  14. chrome 离线安装包下载
  15. C语言代码实现最小二乘法线性拟合直线
  16. 【Web前端】儿童摄影网——网页制作代码
  17. 训练好caffemodel后,提取人脸图片的特征向量
  18. html:制作简易京东导航栏
  19. HTML+css制作简单游戏界面
  20. 学生成绩管理系统 ssm layui

热门文章

  1. LOONGSON派二代 PMON编译
  2. 全国运营商DNS服务器IPv4IPv6地址记录
  3. 红米K20PRO解锁Bootloader权限并刷入recovery
  4. html css 八卦图,CSS动画-八卦图
  5. 基于php+mysql购物商城 校园二手商品 图书鲜花商城 毕业设计(2)分类
  6. linux音频驱动修复工具,Linux声卡驱动(4)——音频驱动实战
  7. 安装labelimg及出现的问题
  8. 初级模拟电路:3-11 BJT实现电流源
  9. 停车场停车系统软件测试报告,智慧停车场系统各大功能系统的详解
  10. c语言停车场管理系统答辩ppt,停车场管理系统C语言实现,全动画模拟