Redis基础知识(1)

IO多路复用

IO:I/O是Input输入/Output输出的简称,通常指数据在内部存储器(内存)外部存储器(硬盘、优盘)或其他周边设备之间的输入和输出。
  输入/输出是信息处理系统(计算机)与外部世界(人类或另一信息处理系统)之间的通信。

BIO:同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

NIO:异步的IO

Redis基础知识

Redis能干嘛

1.内存存储、持久化,内存中是断电即失的、所以说持久化很重要(rdb、aof)

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

3.发布订阅系统

4.地图信息分析

5.定时器、排行榜、计数器

特性

1.多样的数据类型

2.持久化

3.集群

4.事务

学习中需要用到的东西

中文网:http://www.redis.cn/

基础知识

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

Redis默认有16个数据库,默认选择是第0个,默认端口是6379。

可以使用 select 进行切换数据库

Redis 是单线程的。基于内存操作,官方提供的数据是 10万+ 的QPS,完全不必同样是使用 key-value 的Memecache差。

核心:为什么单线程还这么快?

五大数据类型

String

flushdb    			# 清空数据
keys *				# 读取全部的 key 值
set key				# 设置 key 值
get key				# 读取 key 值
strlen key			# 获取字符串的长度
append key 'hello'	# 追加字符串,如果当前 key 不存在,就相当于 set key
incr key			# i++ ,自增 1
decr key			# i-- , 减 1
incrby key 10		# 可以设置步长,指定增量 10
decrby key 5		# 指定减 5
getrange key 0 3	# 查看字符串范围
getrange key 0 -1	# 获取全部的字符串 跟 get key 是一样的
setrange key 1 xx 	# 替换指定位置开始的字符串 'hxxllo'
ttl key 			# 获取剩余的过期时间

# setex (set with expire)	# 设置过期时间
# setnx (set if not exist)	# 不存在再设置 (在分布式锁中会常常使用!)
setex key 30 "hello"	# 设置 key 的值为 hello 30秒后过期
setnx key "redis"		# 如果 key 不存在,创建 key,返回 1
setnx key "redis"		 # 如果 key 存在,创建失败,返回 0

# 批量设置多个值
mset k1 v1 k2 v2 k3 v3 	# 同时设置多个值 key-value 键值形式
mget k1 k2 k3 			# 同时获取多个值
msetnx k1 v1 k4 v4 		# msetnx 是一个原子性的操作,要么一起成功,要么一起失败

# 对象
set use:1 {name:zhangsan,age:3}  	# 设置一个user:1 对象 ,值为 json 字符来保存一个对象!
# 这是一个巧妙的设计:user:{id}:{filed} ,
mset user:1:name zhangsan user:1:age 2 
get user:1:name user:1:age


# getset  先get然后再set
getset key redis 		# 如果不存在值,则返回 nil,设置值为 redis
getset key mongodb 		# 如果存在值,获取原来的值,并设置新的值 

String 类型的使用场景:value除了是字符串还可以是数字。

  • 计数器
  • 统计多单位的数量 uid:001:focusOn 0 设置为0 一直累加
  • 粉丝数
  • 对象缓存存储

List

基本的数据类型,列表。所有的 list 命令都是 L 开头的.

在 redis 中,我们可以把 list 玩成一个队列、栈、阻塞队列!


# 将一个值或者多个值,插入到列表的头部(左)
lpush list one 	
lpush list two
lpush list three
lrange list 0 -1 		# 获取 list 中全部的值,
lrange list 0 -1 		# 通过区间获取具体的值
rpush list righr		# 将一个值或者多个值,插入到列表的尾部(右)

lpop list				# 移除 list 的第一个元素
rpop list 				# 移除 list 的最后一个元素
lindex list 1			# 通过下标获取 list 中的某一个值
llen list				# 返回 list 的长度
lrem list 1 one 		# 移除 list 中指定个数的 value
ltrim list 1 2 			# 通过下标截取截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素。例如:修建树枝,修建掉的那部分已经被砍掉了,不存在了。

# rpoplpush 移除列表的最后一个元素,将它移动到新的列表中!
rpoplpush list list1   	# list 原来的列表,list1 目标列表

# lset 将列表中指定下标的值替换为另外一个值,更新操作
exists list 			# 先判断这个列表是否存在
lset list 0 item 		# 如果不存在列表 我们去更新就会报错
lset list 0 item 		# 如果存在 更新当前下标的值
lset list 1 item2		# 如果不存在 就会报错,例如:我们的下标越界

# 将某个具体的值 插入到列表中某个值的前面或者后面
linsert list before "hello" "word"
linsert list after "hello" "mr.wang" 
 

小结

  • 他实际上是一个链表,before Node after ,left right 都可以插入值
  • 如果key不窜在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在
  • 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点

消息排队、消息队列(Lpush Rpop)、栈(Lpush Lpop)。

Set

set 无序不重复集合,抽随机!

sadd key "hello"			# set 集合中添加元素
smembers key				# 查看指定 set 的所有值
sismember key hello			# 判断某一个值是否存在 set 中
scard key 					# 获取 set 集合中的元素个数
srem key hello				# 移除某一个元素
srandmember key 			# 随机抽选出一个元素
srandmember key 			# 随机抽选出指定个数的元素

# 删除指定的key,随机删除key
spop key					# 随机删除 set 集合中的元素

smove key key2 "hello"		# 将一个指定的值,移动到另一个set 集合

# 数字集合类
- 差集 sdiff key1 key2
- 交集 sinter key1 key2 	# 共同好友就是这样实现的
- 并集 sunion key1 key2

Hash

map集合,key-map集合。本质和string类型没有太大区别,还是一个简单的key-value

hset key k1 v1				# set 一个具体的 key-value
hget key k1 				# 获取一个字段值
hmset key k1 v1 k2 v2		# set 多个 key-value
hmget key k1 k2				# 获取多个字段值
hgetall key					# 获取全部的数据
hdel key k1					# 删除 hash 指定的 key 字段,对应的value值也就消失了
hlen key					# 获取 hash 的字段数量
hexists key K1 				# 判断 hash 中指定字段是否存在
hkeys key					# 获取所有key 
hvals key					# 获取所有value

hincr key			# i++ ,自增 1
hdecr key			# i-- , 减 1
hincrby key 10		# 可以设置步长,指定增量 10
hdecrby key 5		# 指定减 5
 

hash 更适合对象的存储,尤其是用户信息之类的,经常变动的信息!string 更加适合字符串。

Zset

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

zadd key 1 one				# 添加一个值
zadd key 2 two 3 three 		# 添加多个值
zrange key 0 -1 			# 获取全部值

# 排序
zrangebyscore key -inf +inf	# 显示全部数据,从小到大。负无穷到正无穷
zrevrange key 0 -1			# 从大到小 排序
zrangebyscore key -inf +inf withscores 	# 显示全部的用户并且附带成绩
zrangebyscore key -inf 2500 withscores	# 显示小于2500的数据,什序排列
# 移除
zrem key k1 				# 移除有序集合中的指定元素

zcard key					# 获取有序中的个数
zcount key 1 2				# 获取指定区间的元素数量

三种特殊数据类型

geospatial 地理位置

朋友的定位,附近的人,打车距离计算?

redis 的 Geo 在Redis3.2 版本就推出了! 这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人!

# 规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入
# 参数 key   值(精度 维度 名称)
geoadd china:city 116.40 39.90 beijing		# 添加指定城市的经度纬度

# geopos 获取当前定位:一定是一个坐标值
geopos china:city beijing			# 获取指定城市的经度纬度

# geodist 返回两个给定位置之间的距离
# 单位 m km mi:英里 ft:英尺
geodist china:city beijing shanghai		# 查看北京到上海的直线距离

# georadius 以给定的经纬度为中心,找出某一半径内的元素 
# 附近的人?(获得所有附近的人的地址,定位!通过半径来查询)
georadius china:city 110 30 1000 km 					# 以指定经纬度寻找1000km内的城市,所有数据应该录入 china:city ,才会让结果更加精确
georadius china:city 110 30 1000 km withcoord			# 显示1000km内他人的定位信息
georadius china:city 110 30 1000 km withdist			# 显示到中间距离的位置
georadius china:city 110 30 1000 km withdist count 3	# 筛选出指定个数的结果

# 找出位于指定元素周围的其他元素
georadiusbymember china:city beijing 1000 km


# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近
geohash china:city beijng chongqing		# 返回一个或多个位置元素的经纬度的字符串

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

zrange china:city 0 -1 			# 查看地图中的全部元素
zrem China:city beijng			# 移除指定元素

hyperloglog

简介

Redis 2.8.9 版本就更新了 Hyperloglog 数据结构!

Redis Hyperloglog 基数统计的算法!

优点:占用的内存是固定的,2^64 不同的元素的技术,只需要废 12 KB内存!如果要从内存角度来比较的话 Hyperloglog 首选。

网页的 UV (一个人访问一个网站多次,但是还是算作一个人)

0.81% 错误率!统计 UV ,可以忽略不计

pfadd key a b c d e f g				# 创建第一组元素
pfcount key 						# 统计 key 元素的基数数量
pfadd key2 h i j k l m 				# 创建第二组元素
pfmerge key3 key key2 				# 合并两组元素 并集

如果允许容错,那么一定可以使用 Hyoerloglog!

如果不允许容错,就使用set或者自己的数据类型即可!

bitmaps

位存储

统计用户信息,活跃,不活跃!登录,未登录!打卡,365打卡!两个状态的,都可以使用Bitmaps!

Bitmaps 位图,数据结构!凑是操作二进制位来进行记录,就只有0 和 1 两个状态!

365天 = 365 bit 1字节 = 8bit 46个字节左右!

# 使用bitmap 来记录 周一到周日的打卡 
setbit key 0 0
setbit key 1 1
setbit key 2 0
setbit key 3 0
setbit key 4 1
setbit key 5 1
setbit key 6 0

# 查看某一天是否打卡
getbit key 3

# 统计这周的打卡记录,就可以看到是否有全勤
bitcount key

事务

Redis单条命令是保证原子性的,但是事务不保证原子性!

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会被执行!Exec

一次性、顺序性、排他性!执行一系列的命令

正常执行事务

multi 					# 开启事务
set k1 v1
set k2 v2 
get k1
exec					# 执行事务
discard					# 取消事务 事务队列中的命令都不会被执行

编译时异常,代码有问题,命令错误,事务中所有的命令都不会被执行!
运行时异常,如果事务队列中存在语法性错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常!
监控!Watch

悲观锁:

  • 很悲观,什么时候都会出问题,无论做什么都会加锁!

乐观锁

  • 很乐观,认为什么时候都不会出现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据

Redis.conf详解

启动的时候就通过配置文件来启动

单位

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

包含

包含,多个配置文件,就好比 Improt ,Include

网络

bind 127.0.0.1			# 绑定的IP	
protected-mode yes 		# 是否受保护模式
port 6379 				# 端口设置

通用 GENERAL

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

# 日志
loglevel notice
logfile "" 	# 日志的文件位置
database 16 # 默认数据库的数量
always-show-logo yes	# 是否显示logo

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件 .rdb .aof

redis 是内存数据库,如果没有持久化,那么数据断电即失!

# 900s内,如果至少有1个key进行了修改,就进行持久化操作,依次类推
save 900 1
save 300 10
save 60 10000

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

REPLICATION 复制,我们后面讲解主从复制的时候讲解

SECURITY 安全

config get requirepass		# 获取redis的密码
config set requirepass "123456"		# 设置redis的密码
auth 123456		# 使用密码登录

限制 CLIENTS

maxclients 1000 	# 设置能连接上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 模式 aof模式

appendonly no 	# 默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分所有的情况下,rdb完全够用
appendfilename "appendonly.aof"		# 持久化的文件的名字

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

数据淘汰策略

maxmemory

使用maxmemory配置是为了将Redis配置为对数据集使用指定的内存量

# 查看当前配置的最大结果
config get maxmemoy 

# 可以修改redis.conf文件(建议)
maxmemoy 100mb

# 也可以连接redis执行
config set maxmemoy 100mb

设置maxmemoy为0将导致没有内存限制

image

redis数据淘汰策略

image

高频面试题

redis用了半年多,发现内存占用很大。然后批量删除了一些没用的key,发现内存并没有释放。

碎片管理:重启redis,如果内存比较小,可以直接修改配置文件,代表我们可用内存的百分比剩下多少的时候,帮我们去碎片整理。如果碎片整理过于频繁会降低redis的性能。

posted @ 2023-03-15 21:39  shenghuotaiai  阅读(43)  评论(0编辑  收藏  举报