Redis学习总结

1-NoSQL

Not Only SQL,不仅仅是SQL,泛指非关系型数据库。
为什么需要NoSQL?

  1. 对数据库高并发读写的需求
    对于一个网站来讲,每秒钟上万次的读写请求,对于关系数据库来说实在是无法承受,所以高并发很关键。
  2. 对海量数据的高效率存储和访问的需求
    对于一个大型网站,每天都有海量动态,对于关系数据库来讲,在一个存储着几千万几亿的表中查询,效率极为低下。
  3. 对数据库的高可扩展性和高可用性的需求
    对于24小时在线的网站来说,数据库升级和扩展是很痛苦的事情,所以要用到NoSQL理念
2-NoSQL特点

在大数据存取上具备关系型数据库无法比拟的性能优势,例如:

  1. 易扩展
    NoSQL数据库种类繁多,但是一个共同特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。也无形之间,在架构的层面上带来了可扩展的能力。
  2. 大数据量,高性能
    NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀,这得益于它的无关系性,数据库的结构简单
  3. 灵活的数据模型
    NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。这点在大数据量的Web2.0时代尤其明显。
  4. 高可用
    NoSQL在不太影响性能的情况下,就可以方便的实现高可用的架构。比如Cassandra,HBase模型,通过复制模型也能实现高可用。

综上所述,NoSQL的非关系特性使其成为了后Web2.0时代的宠儿,助力大型Web2.0网站的再次起飞,是一项全新的数据库革命性运动。
很多项目中经常发生变化,加新的业务就要写新的功能,关系型数据库就很难完成。所以新的架构应引用NoSQL理念,关系和非关系配合使用,主要的数据放在关系型数据库中,需要动态增加和扩展的放在Redis里。

NoSQL主流:
键值对、列式存储、文档类型、图形数据库
键值对(Redis来实现)

3-Redis的单进程单线程

采用多路IO复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络的IO时间消耗)

多线程可能涉及到锁
多线程处理会涉及到线程切换而消耗CPU
单线程不存在线程安全问题
缺点是:
无法发挥多核CPU性能,不过可以通过在单机开多个redis来完善

redis默认有16个数据库,可以在config里配置默认多少数据库
统一密码管理,所有库都是同样密码
redis中所有的键都必须是字符串类型,并且索引都是从零开始

4-Redis的基本操作

1、del ‘key’; del可以删除所有数据类型
2、利用config配置文件来启动redis-server
$ ./redis-server /redis.conf
3、切换数据库命令(select + n)
  127.0.1:6379>select 0
4、dbsize 查看当前数据库的key数量
5、flushdb 清空当前库
6、flushall 清空所有库
7、config get dir 获得配置文件地址

5-Redis的数据类型

这里所说的数据类型针对键值对中的Value而不是key
各类数据类型常用方法:

  1. 字符串类型
    set key value
    get key
    getrange name n1 n2 (和数组一样取)
    getset key value (设置新值,返回旧值)
    mset key1 key2 ... (multi-批量设置)
    mget key1 key2 ...
    setnx key value (不存在就插入 not exists)
    setrange key index value (从index开始替换)
    incr key (+1递增)
    incrby key n (+n递增)
    incrbyfloat f (+f递增)
    decr key (-1递减)
    decrby key n (-n递减)
    append (延申)
    strlen (长度)
    object encoding key (得到Key类型:int、embstr、raw)
  2. list数据类型(队列)
    lpush list a b c ... (左插入)
    rpush list a b c ... (右插入)
    lrange list n1 n2 (和数组一样取)
    lpop list (弹出队列最左元素)
    rpop list (弹出队列最右元素)
    llen list (输出长度)
    lrem list count value (删除)
      count>0,从左往右删除count个value
      count<0,从右往左删除count个value
      count=0,删除所有value
    lindex list n (显示指定索引的值)
    lset list n value (将索引n的值改为value)
    ltrim list index1 index2 (保留index1到index2的值)
    linsert list before|after value1 value2 (在value1前或后插入value2)
    rpoplpush list1 list2 (将list1中最右元素左插到list2中)
  3. hash数据类型
    hset hash key value (创建或设置)
    hget hash key (获取key的值)
    hmset hash key1 value1 key2 value2 ... (批量设置)
    hmget hash key1 key2 key3 ... (批量获取)
    hgetall hash (获取所有key-value)
    hexists hash key (是否存在)
    hsetnx hash key value (若不存在,则创建;若存在则不动)
    hincrby hash key n (以n递增)
    hdel hash key (删除)
    hkeys hash (所有key)
    hvals hash (所有value)
    hlen hash (长度)
  4. set数据类型 - 无序存储
    sadd key value1 value2 ... (创建一个set)
    smembers key (打印所有数据)
    srem key value1 value2 ... (删除)
    sismember key value (是否存在value)
    scard key (key中value个数)
    sdiff | sinter | sunion (set的:差集 | 交集 | 并集)
    srandmember (随机获取集合中的元素)
    spop (随机弹出元素)
  5. zset(sortset)数据类型 - 有序存储(比较少用)
    zdd zset value key (设置数据,只能设置数字,会自动排序)
    zincrby zset n key (将key以n递增)
    zscore zset key (获取value)
    zrange zset n1 n2 [withscores] ([带value]输出下标n1-n2的数据)
    zrangebyscore zset n1 n2 [withscores] [limit n1 n2] ([带value]输出数值n1-n2的数据,可分页 - 从小到大)
    zrevrangebyscore zset n1 n2 [withscores] ([带value]输出数值n1-n2的数据 - 从大到小)
    zcard zset (输出数量)
    zcount zset n1 n2 (输出n1-n2范围内的key数量)
    zrem zset key1 key2 ... (删除key)
    zremrangebyrank zset n1 n2 (删除下标n1-n2范围内数据)
    zremrangebyscore zset n1 n2 (删除数值n1-n2范围内数据)
    zrank zset key (查看key正序下标)
    zrevrank zset key (查看key逆序下标)

注意:
1、redis中,取值都是左闭右闭,n为-1的意义是指向队列最右元素
2、凡是关于range的方法,0到-1都是取全部,若是0到n则像普通数组取
3、凡是关于range的方法,都是左闭右闭取值
命令的学习网站:redis教程
4、list的push、hash是set能够创建对象,list的set创建不了对象

6-Redis解析配置文件redis.conf

maxmemory-policy策略
noeviction: 不删除策略, 达到最大内存限制时, 如果需要更多内存, 直接返回错误信息。(默认值)
allkeys-lru: 所有key通用; 优先删除最近最少使用(less recently used ,LRU) 的 key。
volatile-lru: 只限于设置了 expire 的部分; 优先删除最近最少使用(less recently used ,LRU) 的 key。
allkeys-random: 所有key通用; 随机删除一部分 key。
volatile-random: 只限于设置了 expire 的部分; 随机删除一部分 key。
volatile-ttl: 只限于设置了 expire 的部分; 优先删除剩余时间(time to live,TTL) 短的key。

redis中并不会准确的删除所有键中最近最少使用的键,而是随机抽取maxmeory-samples个键,删除这三个键中最近最少使用的键。

rdb是一个同步过程,根据配置文件中设置的保存机制来进行同步,同步的是数据,到硬盘中
aof是一种备份机制,将每次执行的命令保存到日志文件中,通过执行所有命令的方式来还原
aof有异步增加原则,准确性高,但是效率低(每秒都写)

Redis的30个关键配置
redis.conf 配置项说明如下:

  1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
    daemonize no

  2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
    pidfile /var/run/redis.pid

  3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
    port 6379

  4. 绑定的主机地址
    bind 127.0.0.1

  5. 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
    timeout 300

  6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
    loglevel verbose

  7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
    logfile stdout

  8. 设置数据库的数量,默认数据库为0,可以使用SELECT命令在连接上指定数据库id
    databases 16

  9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
    save
    Redis默认配置文件中提供了三个条件:
    save 900 1
    save 300 10
    save 60 10000
    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

  10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
    rdbcompression yes

  11. 指定本地数据库文件名,默认值为dump.rdb
    dbfilename dump.rdb

  12. 指定本地数据库存放目录
    dir ./

  13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
    slaveof

  14. 当master服务设置了密码保护时,slav服务连接master的密码
    masterauth

  15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH命令提供密码,默认关闭
    requirepass foobared

  16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
    maxclients 128

  17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
    maxmemory

  18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
    appendonly no

  19. 指定更新日志文件名,默认为appendonly.aof
    appendfilename appendonly.aof

  20. 指定更新日志条件,共有3个可选值:
    no:表示等操作系统进行数据缓存同步到磁盘(快)
    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
    everysec:表示每秒同步一次(折衷,默认值)
    appendfsync everysec

  21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
    vm-enabled no

  22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
    vm-swap-file /tmp/redis.swap

  23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
    vm-max-memory 0

  24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不确定,就使用默认值
    vm-page-size 32

  25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,在磁盘上每8个pages将消耗1byte的内存。
    vm-pages 134217728

  26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
    vm-max-threads 4

  27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
    glueoutputbuf yes

  28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
    hash-max-zipmap-entries 64
    hash-max-zipmap-value 512

  29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
    activerehashing yes

  30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
    include /path/to/local.conf

7-Redis数据持久化

Redis RDB和AOF的区别
RDB和AOF的配置方式:
1、RDB配置方式
默认情况下,是快照rdb的持久化方式,将内存中的数据以快照的方式写入二进制文件中,默认的文件名是dump.rdb
配置方式: redis.conf中找到并修改
save 900 1 save 300 10 save 60 10000

2、AOF 配置方式
使用aof做持久化,每一个写命令都通过write函数追加到appendonly.aof中
配置方式:启动aof持久化的方式
appendonly yes

8-Redis事务

Redis事务主要有以下5个命令:
事务相关指令
事务执行情况1 - 正常执行
正常执行
事务执行情况2 - 放弃事务
放弃事务
事务执行情况3 - 一错全错
一错全错
事务执行情况4 - 谁错谁当
谁错谁当
使用Watch对Key进行监控时:
事务执行情况5 - 被监控值不变,则执行成功
在这里插入图片描述
事务执行情况6 - 被监控值改变,则执行失败
在这里插入图片描述
  一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。
  故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。
总结:
  watch指令类似于乐观锁,在事务提交时,如果watch监控的多个KEY中任何KEY的值已经被其他客户端更改,则使用EXEC执行事务时,事务队列将不会被执行,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。

9-Redis的复制

利用主从复制原理实现读写并发分离操作,解决高可用
也就是说,我们开启多个客户端,并设置一个为主机,其他的为主机的从机。主机(Master)负责写,从机(Slave)负责读
优点:1、读写分离 2、容灾恢复

配置操作:
   1、 拷贝多个redis.conf文件
   2、 开启deamonize yes
   3、 Pid文件名字
   4、 指定端口
   5、 Log文件名字
   6、 Dump.rdb名字
配置命令
   1、 SLAVEOF 主库IP 主库端 (从机用该命令)
   2、 INFO replication (查看主从信息)
   3、一般是一主二仆,一个主机两个从机
一主二仆觉见问题
   1、 切入点问题?slave1、slave2是从头开始复制还是从切入点开始复制?
     从头复制,也就是说数据齐全
   2、 从机是否可以写?set可否?
     从机是只读的
   3、 主机shutdown后情况如何?从机是上位还是原地待命
     从机原地待命
   4、 主机又回来了后,主机新增记录,从机还能否顺利复制?
     可以
   5、 其中一台从机down后情况如何?依照原有它能跟上大部队吗?
     可以

Redis复制有以下情况:
1、薪火相传
   上一个Slave可以是下一个Salve的Master,也就是继承关系,可以有效减轻原有Master的压力
   中途改变主从关系会清除之前的数据,重新拷贝最新数据
   Slaveof 新主库IP 新主库端口
2、反客为主
   SLAVEOF no one
   使当前数据库停止与其他数据库的同步,转成主数据库,但是必须手动,而且要实时监控才可以

复制原理
Slave启动成功连接到master后会发送一个sync命令
Master接到命令启动后台的存盘进程, 同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后, master将传送整个数据文件到slave,以完成一次完全同步
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步,但是只要是重新连接master, 一次完全同步(全量复制)将被自动执行

Redis哨兵模式
1、哨兵模式简介
   反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
2、哨兵模式
   调整结构,6379带着80、81
   自定义的/redis目录下新建sentinel.conf文件, 名字绝不能错
   配置哨兵,填写内容
   sentinel monitor被监控主机名字(自己起名字) 127.0.0.1 6379 1
   如sentinel monitor hos6379 127.0.0.1 6379 1
   上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得到对应票数后成为主机
   启动哨兵:./redis-sentinel /自定义目录/sentinel.conf
   如果原来master挂了之后重启回来,就变小弟了
   哨兵能同时监控多个Master
   从机多了哨兵模式效率就低了

10-Redis高可用高并发集群配置

提高Redis效率的方式有普通的一主二仆还有哨兵模式,而这这两种方式都有一定的缺陷,哨兵模式强于一主二仆,而哨兵模式在Slave数量多的时候同步更新效率极低,所以要实现高可用和高并发,那么就要用到去中心化的思想

中心化:奴隶制度,参考一主二仆和哨兵模式
去中心化:人民当家作主,平起平坐

Redis集群执行流程
Redis 集群中内置了16384个哈希槽,当需要在 Redis 集群中放置一个key-value时,Redis先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
如下面这张图,当我们执行set name rose写入操作时,Redis会使用crc16算法对name进行计算,然后将结果对16384取余数,假设我们计算完之后,余数为2500,那么这个key-value就会被分配到Redis:2(哈希槽为5000-10000之间)。
集群流程
当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。你可以理解成表的分区,使用单节点时的Redis时只有一个表,所有的key都放在这个表里。当改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,每个分区里可以存在多个key。

Redis集群详细配置
关于Redis的集群配置,比较繁琐,我当时也配了好久,也遇到过很多错误的情况,所以我特意写了一篇文章:Redis集群搭建 秒会

11-Redis客户端的使用

很简单,直接下载一个Redis可视化工具连接Redis即可
我用的是Redis-Desktop-Manager,但是这个软件,有比较多的问题,以后换一个

12-Jedis的使用

首先,Eclipse创建一个Maven项目,然后修改porm.xml中的内容,添加如下代码(版本自选):

<dependencies>
  	<dependency>
  		<groupId>redis.clients</groupId>
  		<artifactId>jedis</artifactId>
  		<version>3.2.0</version>
  	</dependency>
  </dependencies>

其次,在src/main/java中创建class,其中jedsi对象的方法和redis中的命令几乎一模一样,所以使用起来也不会特别复杂。可以自行查询命令以及pool配置

import java.util.Set;
import redis.clients.jedis.Jedis;
public class JedisDemo {
	public static void main(String[] args) {
		Jedis jedis = new Jedis("192.168.1.104", 6379);
		//jedis.auth("密码");
		jedis.set("test", "hello jedis");
		jedis.expire("k3", 10);
		//keys命令
		Set<String> keys = jedis.keys("*");
		for (String string : keys) {
			System.out.println(string);
		}
		//list
		jedis.lpush("list", "a","b","c","d");
		List<String> lrange = jedis.lrange("list", 0, -1);
		System.out.println(lrange);
	}
}

JedisPool的使用,与JDBCPool差不多:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolUtils {
	private static volatile JedisPool pool = null;
	private JedisPoolUtils(){}
	public static JedisPool getJedisInstance(){
		if(null == pool){
			synchronized (JedisPoolUtils.class){
				if(null == pool){
					JedisPoolConfig config = new JedisPoolConfig();
					config.setMaxTotal(1000);//最大连接数
					config.setMaxIdle(32);//活动连接个数
					config.setMaxWaitMillis(100 * 1000);//最大等待时间
					config.setTestOnBorrow(true);//借之前,检查是否可用
					pool = new JedisPool(config, "192.168.1.104", 6379);
				}
			}
		}
		return pool;
	}
	public static void release(JedisPool pool,Jedis jedis){
		if(jedis!=null){
			jedis.close();
		}
	}
}
13-至此,结束

如果有帮助的话,点个赞、收个藏、加个关注我都会很感谢!
如果有什么问题,请在评论区评论,我会及时查看!♥♥♥

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hillain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值