Redis学习之路

次花椒的喵酱 / 2024-03-04 / 原文

Redis

代码成就万世基 积沙镇海 梦想永在凌云意 意气风发

一.是什么,有什么用

用来解决

  1. 数据量太大。

  2. 数据索引太大,内存放不下。

  3. 读写量(读写混合),单独的服务器承受不了。

  4. 减轻服务器压力,使用缓存来保证效率(主要是用来解决读的问题)。Cache有时间局部性和空间局部性

  5. 垂直分离读写,水平扩展集群

本质:解决数据库的读写问题

使用分库分表来解决写的压力

二.NoSQL入门

对于用户的个人信息,社交网络,地理位置等用户不断自己产生的数据,以及用户的日志爆发式增长。

普通的关系型数据库无法实现这么复杂且繁多的数据量。

这个时候就要使用NoSQL数据库,来实现以上的情况。

 

什么是NoSQL

NoSQL = Not Only SQL

不仅仅是SQL(泛指非关系型数据库,不是固定的模式) 关系型数据库RDBMS(用行和列来记录的)

使用键值对Map<String,Object>来控制

特点:

  • 方便扩展,容易扩展

  • 大数据量高性能

  • 数据类型多样,不需要事先设计数据库,随取随用

3V(描述问题):海量Volume,多样Variety,实时Velocity

3高(程序要求):高性能,高可扩,高并发

一个简单的网页,其背后的技术:

1.商品的基本信息
2.商品的描述、评论(文字多)
3.图片、视频
4.商品关键字(搜索引擎solar elasticsearch)
5.商品热门的波段信息(内存数据库)
6.商品的交易,外部的支付接口

 

三.NoSQL的四大分类

1.KV键值对

 

2.文档型数据库(格式和json一样)

MongoDB基于分布式文件存储的数据库,用于处理大量的文档,介于关系型数据库和非关系型数据库中间,是非关系型数据库中功能最丰富的,最像关系型数据库的。

 

3.列存储数据库

 

4.图形关系数据库

 

四.Redis入门

Remote Dictionary Server远程字典服务,是当下NoSQL的技术之一,被人们称为结构化数据库

 

Redis用来解决:

1.内存存储,持久化,rdb持久化和aof持久化是Redis两种持久化的策略

2.效率高,可用于高速缓存

3.发布订阅系统

4.地图信息分析

5.计数器,计时器

特性:

1.多样数据类型

2.持久化

3.集群

4.事务

安装Redis

1.Redis中的内容

 

2.安装gcc环境

sudo yum install gcc-c++

 

make

make install

3.默认安装路径在/usr

 

 

4.用配置文件redis.conf进行启动

redis-server redis-config/redis.conf

5.测试连接,使用Redis客户端进行连接

 

6.使用redis-cli进行连接测试

 

7.查看进程是否开启

 

8.关闭Redis服务

shutdown

exit

测试性能

redis-benchmark是压力测试工具

redis-benchmark 命令参数

 

#测试
redis-benchmark -h localhost -p 6379 -c 100 -n 100000

基本知识说明

Redis默认有16个数据库,默认使用的是第0个数据库

可以使用select来切换数据库

select 3 #切换为第四个数据库

dbsize #查看数据库大小

key * #查看所有的key

set name value #设置KV

get name #获得value

flushdb #清空当前库

flushall #清空全部库

Redis是单线程的

Redis是很快的,它基于内存操作,CPU不是它的性能瓶颈,Redis的瓶颈是机器的内存和网络带宽

为什么单线程还这么快?

答:Redis将所有的数据都放在内存中,所以说使用单线程去操作效率就是最高的;多线程(CPU上下文切换耗费资源),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个CPU上的。

五.进阶

Redis-Key

keys * //显示所有关键字
exists name //该关键字key是否存在
move name 1 //把name的KV移动到1号数据库
expire name 10 //设置可以的存活时间,在10秒后过期
ttl name //显示key的剩余存活时间
del name //移除key
type name //查看key的数据类型

五大数据类型

1.String字符串

append name value //在key后追加value 如果当前key不存在,就相当于set key
strlen name //得到key的长度
incr age //增加1
decr age //减少1
incrby age 10 //自增步长
decrby age 10 //自减步长
getrange key1 1 2 //截取key1的下标从[1,2]
getrange key1 0 -1//取得key1的全部字符串
setrange key1 1 xx//替换指定位置开始的字符串,在下标1进行替换
setex(set with expire) key seconds value //设置过期时间
setnx(set if not exist) key value //不存在再设置(在分布式锁中会经常使用)
mset k1 v1 k2 v2 k3 v3 //连续设置多个值
mget k1 k2 k3 //连续读取多个值
msetnx k1 v1 k4 v4 //设置失败,因为k1 v1 已经存在(原子性操作————一起成功一起失败)

 

对象

set user:1 {name:ren,age:21} //设置一个user:1 对象 值为json字符串,来保存一个对象

mset user:1:name ren user:1:age 21

mget user:1:name user:1:age

  1. "ren"

  2. "21"

 

这里的key是一个巧妙的设计

user:{id}:{field}

 

组合命令

getset //先get再set

getset key value

 

2.List列表

可以把List完成栈、队列、阻塞队列

lpush list one //向List左边插入

lrange list 0 1 //下标[0,1]倒序输出(栈)

lrange list 0 -1 //全部倒序输出

rpush list one //向List右边插入

lpop list //移除头部元素

rpop list //移除尾部元素

lindex list 0 //通过下标获取List中的值

llen list //List的长度

lrem list 1 one //移除一个one

ltrim list 0 1 //截取下标[0,1]的元素(修剪)

rpoplpush list list2 //移除列表的尾部元素,并把他放到list2

lset list 0 value //将List中下标为0的值修改为value

linsert list before/after "value1" "value2" //在value1的前面/后面插入value2

小结:是一个链表,可以在left和right插入元素,如果key不存在,创建新的链表,如果key存在,新增元素,如果移除所有元素,则为空链表,即不存在;在两边插入或者删除,效率最高,在中间进行操作,效率较低。

可以根据需要来进行操作————队列(Lpush,Rpop),栈(Lpush,Lpop)

3.Set集合

set中的值不能重复 无序不重复集合

sadd set name //在集合中添加元素
smembers set //显示集合所有元素
sismeber set name //集合中是否存在name元素
srem set name //移除集合中的name元素
srandmember set //随机选取set中的一个元素
srandmember set 2 //随机选取set中的两个元素
spop set //随机移除元素
move set set1 value//将一个指定的值,从set移动到另外一个集合set1中
sdiff set set1 //差集,set中减去set1中的,所剩的集合
sinter set set1 //交集
sunion set set1 //并集

4.Hash(哈希)

Map集合,key-map,map中的KV键值对

hash更合适于对象的存储,stirng更加适合字符串存储

hset hash key name //set一个具体的KV
hget hash key     //获取一个字段值
hgetall hash //获取hash中所有KV
hdel hash key //删除hash指定的key字段,对于的value也消失了
hlen hash //hash中有多少个KV键值对
hexists hash key //判断hash中的指定key字段是否存在
hkeys hash //获取所有key
hvals hash //获取所有value
hincrby hash age 1 //自增1
hsetnx hash key name //不存在则保存KV
hsetnx hash key age //存在则不保存KV
hset user:1 name ren //存一个user:1对象的name KV
hget user:1 name //得到user:1对象的name value

 

 

5.Zset(有序集合)

在set的基础上,增加了一个值

 

//添加一个值
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 //正序输出
1) "one"
2) "two"
3) "three"

zrevrange salary 0 -1 //逆序输出

//排序集合
127.0.0.1:6379> zadd salary 2500 ren
(integer) 1
127.0.0.1:6379> zadd salary 500 zi
(integer) 1
127.0.0.1:6379> zadd salary 5000 shuo
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf //正序输出,正无穷到负无穷
1) "zi"
2) "ren"
3) "shuo"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores //附带数值
1) "zi"
2) "500"
3) "ren"
4) "2500"
5) "shuo"
6) "5000"
127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf //逆序输出,负无穷到正无穷
1) "shuo"
2) "ren"
3) "zi"
//移除set中的元素
127.0.0.1:6379> zrem salary ren
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zi"
2) "shuo"
//获取有序集合中的个数
127.0.0.1:6379> ZCARD salary
(integer) 3
//获取区间内的元素数量
127.0.0.1:6379> zcount salary 0 5000
(integer) 3

应用范围:

1.set排序,存储班级成绩表,工资表

2.普通消息和重要消息的带权重判断

3.排行榜实现

 

三种特殊数据类型

1.geospatial地理位置

附近的人,打车距离

只有六个命令

image-20240302171513244

一//geoadd添加地理位置 南极北极无法直接添加,一般直接通过Java程序导入
127.0.0.1:6379> geoadd china:city 113.6401 34.72468 zhengzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 115.45 38.87 baoding
(integer) 1
二//geopos通过城市查询地理位置
127.0.0.1:6379> geopos china:city zhengzhou
1) 1) "113.64010244607925415"
  2) "34.72467993544626808"
127.0.0.1:6379> geopos china:city baoding
1) 1) "115.44999808073043823"
  2) "38.8700009402465767"
三//geodist两个城市之间的距离 mi英里ft英尺
127.0.0.1:6379> geodist china:city zhengzhou baoding
"488403.9370"
四//georadius以给定的经纬度为中心,找出某一半径内的元素
georadius china:city 110 35 1000 km //找出在半径1000km内的城市
georadius china:city 110 35 1000 km withdist //显示直线距离
georadius china:city 110 35 1000 km withcoord //显示经纬度
georadius china:city 110 35 1000 km withcoord count 1 //只显示1个
五//georadiusbymember通过一个城市元素来查询某半径范围的所有城市
georadiusbymember china:city zhengzhou 1000 km
六//geohash返回一个或多个位置元素的Geohash,该命令将返回11个字符的Geohash字符串
geohash china:city zhengzhou baoding
将二维的经纬度转换成一维的字符串
如果两个字符串越接近,则距离越近

Geo底层的实现原理就是Zset,我们可以使用Zset命令来操作Geo

zrange china:city 0 -1 //查看地图中全部元素
zrem china:city beijing //删除地图中指定元素

2.hyperloglog

基数,指一个集合中不重复的元素,是一个集合中不重复的,不是两个集合做对比

网页的UV,一个人多次访问网站,但只算作一个人

用于进行基数统计,占用的内存是固定的12KB,从内存角度来比较,其性能首选

127.0.0.1:6379> pfadd key a b c d e //输入key的元素
(integer) 1
127.0.0.1:6379> pfcount key //显示key的元素个数
(integer) 5
127.0.0.1:6379> pfadd keyTwo a b c d e f g //输入keyTwo的元素
(integer) 1
127.0.0.1:6379> pfcount keyTwo //显示keyTwo的元素个数
(integer) 7
127.0.0.1:6379> pfmerge key3 key keyTwo //合并key和keyTwo的元素
OK
127.0.0.1:6379> pfcount key3
(integer) 7

如果允许容错,可以使用hyperloglog

3.bitmap位图

位存储

统计用户信息,通过操作二进制位来进行记录,只有0和1两个状态

//使用bitmap记录周一到周四的打卡
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 1
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
//查看某一天是否打卡
127.0.0.1:6379> getbit sign 0
(integer) 1
127.0.0.1:6379> getbit sign 1
(integer) 0
//统计打卡的天数
127.0.0.1:6379> bitcount sign
(integer) 3