# my-redis
**Repository Path**: panleiming/my-redis
## Basic Information
- **Project Name**: my-redis
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-07-07
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# my-redis
官网地址:https://redis.io/topics/introduction
中文网站地址:http://www.redis.cn/
# 目录
1. 概念
1. SQL,NoSQL和NewSQL
2. NoSQL不同的存储类型
3. redis的特性
2. 安装
3. 基本操作
1. 库操作
2. 键操作
3. String类型操作
4. Hash类型操作
5. List类型操作
6. Set类型操作
7. ZSet类型操作
4. 存储原理
5. 问题
1. SDS是什么?
2. 为什么Redis要用SDS实现字符串?
3. embstr和raw的区别?
4. embstr什么时候会转换成raw?会还原吗?
# 概念
## SQL,NoSQL和NewSQL
**关系型数据库的特点:**
* 它以表格的模式,基于行存储数据,是一个二维的模式
* 存储的是结构化的数据,数据存储有固定的模式(schema),数据需要适应表结构
* 表与表之间需要存在关联
* 大部分关系型数据库都支持SQL的操作,支持复杂的关联查询
* 通过支持事务(ACID)来提供严格或者实时的数据一致性
**关系型数据库的一些限制:**
* 要实现扩容的化,只能向上(垂直)扩展,比如磁盘限制了数据的存储,就要扩大磁盘容量,通过堆硬件的方式,不支持动态的扩缩容。水平扩容需要复杂的技术实现,比如分库分表
* 表结构修改困难,因此存储的数据格式也受到限制
* 在高并发高数据量的情况下,关系型数据库通常会把数据持久化到磁盘,基于磁盘的读写压力比较大
**非关系型数据库的特点:**
* 存储非结构化的数据,比如文本,图片,音频,视频
* 表与表之间没有关联,可扩展性强
* 保证数据的最终一致性。遵循BASE理论。Basically Available(基本可用);Soft-state(软状态);Eventually Consistent(最终一致性)
* 支持海量数据的存储和高并发的高效读写
* 支持分布式,能够对数据进行分片存储,扩缩容简单
**NewSQL则结合了SQL和NoSQL的特点**
## NoSQL不同的存储类型
* KV存储,用Key Value的形式来存储数据。比较常见的有Redis和MemcacheDB
* 文档存储,MongoDB
* 列存储,HBase
* 图存储,Neo4j
* 对象存储
* XML存储等等
更多信息可参考该网站:https://hostingdata.co.uk/nosql-database/
## redis的特性
1. 更丰富的数据类型
2. 进程内与跨进称;单机与分布式
3. 功能丰富:持久化机制与过期策略
4. 支持多种编程语言
5. 高可用,集群
# 安装
* [单击安装]()
# 基本操作
## 库操作
默认有16个库(0-15),可以在配置文件中修改,默认使用第一个db0。因为没有完全隔离,不像数据库的database,不适合把不同的库分配给不同的业务。
切换数据库
```java
select 0
```
清空当前数据库
```java
flushdb
```
清空所有数据库
```java
flushall
```
## 键操作
Redis是字典结构的存储方式,采用key-value存储。key和value的最大长度限制在512M。
存值
```java
set age 21
```
取值
```java
get age
```
查看所有键
```java
keys *
```
获取键总数
```java
dbsize
```
查看键是否存在
```java
exists sex
```
删除键
```java
del sex age
```
重命名键
```java
rename sex age
```
查看类型
```java
type sex
```
## String类型操作
可以用来存储字符串,整数,浮点数
设置多个值
```java
mset sex 男 age 21
```
设置值,如果存在key,则不成功。基于此可实现分布式锁,释放时,使用`del key`命令。
这里会有一个问题:如果释放锁失败,那么其他等待线程将永远等待,解决方法是给key加过期时间,命令为`expire key`,但这时两个命令不满足**原子性**。这里有几种方法进行替代:
1. 使用set key value \[expiration EX seconds|PX milliseconds\]\[NX|XX\],示例:`set lock 1 EX 5 NX`
2. 使用redis事务
3. 使用lua脚本
```java
setnx age 28
```
(整数)值递增
```java
incr age
incrby age 10
```
(整数)值递减
```java
decr age
decrby 10
```
(浮点数)值增量
```java
incrbyfloat float 2.0
incrbyfloat float -0.5
```
获取多个值
```java
mget age sex
```
获取值长度
```java
strlen sex
```
字符串追加内容
```java
append age 1
```
获取指定范围的字符串
```java
getrange age 1 2
```
## Hash类型操作
设置hash值
```java
hset map name jack age 28 sex 0
hmset map1 name lili age 21 sex 1
```
获取hash值
```java
hget map name
hmget map name age sex
```
获取指定hash的所有field
```java
hkeys map
```
获取指定hash的所有value
```java
hvals map
```
获取指定hash的所有field-value
```java
hgetall map
```
判断指定hash的field是否存在
```java
hexists map name
```
删除指定hash的field
```java
hdel map name
```
获取指定hash有多少个field
```java
hlen map
```
对指定hash的指定filed的值进行增加或减少
```java
hincrby map age 10
hincrby map age -10
```
## List类型操作
list列表是有序的,左边是列表头,从左到右
向左添加列表元素
```java
lpush list a b c
```
向右添加列表元素
```java
rpush list d e f
```
弹出左边元素
```java
lpop list
```
弹出右边元素
```java
rpop list
```
获取指定索引的元素
```java
lindex list 0
```
获取所有元素
```java
lrange list 0 -1
```
## Set类型操作
添加set元素
```java
sadd set a b c a
```
获取set成员
```java
smembers set
```
获取set的成员数量
```java
scard set
```
随机获取set中的成员
```java
srandmember set 2
```
弹出set中的头部成员
```java
spop set
```
删除set中指定的成员
```java
srem set a
```
判断当前元素是否是set的成员
```java
sismember set c
```
获取多个set集合的差集
```java
sdiff a b
```
获取多个set集合的交集
```java
sinter a b
```
获取多个set集合的并集
```java
sunion a b
```
## ZSet有序集合操作
向zset有序集合中添加元素
```java
zadd myzset 1 a 2 b 3 c
```
根据分数从小到大获取有序集合中的所有元素
```java
zrange myzset 0 -1 withscores
```
根据分数从大到小获取有序集合中的所有元素
```java
zrevrange myzset 0 -1 withscores
```
获取某个分数段内的元素
```java
zrangebyscore myzset 2 4
```
删除指定的元素
```java
zrem myzset a
```
获取元素的数量
```java
zcard myzset
```
新增指定元素的分数
```java
zincrby myzset 5 b
```
获取某个分数段内的元素数量
```java
zcount myzset 2 6
```
返回指定元素排在第几名(按从小到大的顺序)
```java
zrank myzset b
```
返回指定元素的分数
```java
zscore myzset b
```
# 存储原理
# 问题
## SDS是什么?
Redis中字符串的实现。SDS又有多种数据结构(sds.h):sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64,用于存储不同长度的字符串,分别代表2^5=32byte,2^8=256byte,2^16=65536byte=64KB,2^32=4GB
## 为什么Redis要用SDS实现字符串?
C语言本身没有字符串类型(只能用字符数组char[]实现)
1. 使用字符串数组必须先给目标变量分配足够的空间,否则可能会溢出
2. 如果要获取字符串长度,必须遍历字符数组,时间复杂度是O(n)
3. C字符串长度的变更会对字符串组做重新分配
4. 通过从字符串开始到结尾碰到的第一个'\0'来标记字符串的结束,因此不能保存图片,音频,视频,压缩文件等二进制(bytes)保存的内容,二进制不安全
SDS的特点:
## embstr和raw的区别?
## embstr什么时候会转换成raw?会还原吗?