标签:写文件 const 发包 sorted 存在 硬盘 write nal 方案
[TOC]
? NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL” ? 是一项全新的数据库理念,泛指非关系型的数据库。
web程序不再仅仅专注在功能上,同时也在追求性能
High performance --- 对数据库高并发读写的需求
现在数据库并发负载非常高,往往要达到每秒上万次读写请求
关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了
Huge Storage --- 对海量数据的高效率存储和访问的需求
对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的
High Scalability && High Availability --- 对数据库的高可扩展性和高可用性的需求
对于很多需要提供24小时不间断服务的网站来说,
对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库
官方提供测试数据
50个并发执行100000个请求
读的速度是110000次/s
写的速度是81000次/s
redis的应用场景
缓存(数据查询、短连接、新闻内容、商品内容等等)
聊天室的在线好友列表
任务队列。(秒杀、抢购、12306等等)
应用排行榜
网站访问统计
数据过期处理(可以精确到毫秒
分布式集群架构中的session分离
业务流程
获取数据的时候先从redis中获取, 如果获取到数据则直接返回, 就不用访问数据库了
如果获取不到数据, 可以从数据库中查询, 查询到后放入redis中一份, 下回就可以直接从redis中查询到
这样大大降低了数据库的高并发访问压力。
持久化方案
RDB(默认) 分时持久化
可以在配置文件中设定, 多长时间持久化一次, 持久化次数少也就是操作硬盘的次数少,
速度快. 但是如果在没有完成持久化前, 如果服务器断电, 则内存中没有持久化的数据会丢失.
AOF 实时持久化
每次向redis中做增删改操作, 都会将数据持久化到硬盘上, 数据可靠性高, 不会丢失,
但是速度慢
?
将redis在Linux的安装包上传到/usr/local当中
cd /usr/local
解压
tar -zxvf redis-4.0.9.tar.gz
rm -rf redis-4.0.9.tar.gz
编译安装
进入到redis目录
cd /usr/local/redis-4.0.9/
make
make install PREFIX=‘/usr/local/redis-4.0.9/6379‘
启动
cd /usr/local/redis-4.0.9/6379/bin
./redis-server
修改配置文件
cd /usr/local/redis-4.0.9/
把/usr/local/redis-4.0.9/目录下的配置文件复制一份到6379目录下
cp redis.conf /usr/local/redis-4.0.9/6379/bin/
修改配置文件
cd /usr/local/redis-4.0.9/6379/bin/
#bind 127.0.0.1 # 将这行代码注释,监听所有的ip地址,外网可以访问
protected-mode no # 把yes改成no,允许外网访问
daemonize yes # 把no改成yes,后台运行
重新启动
./redis-server redis.conf
ps -ef|grep redis
set key value
set name gaowei
get key
获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,
get name
del key
del name
删除后,返回整数1,表示删除成功
?
?
hset key field value
为指定的key设定field/value对(键值对)
hset myhash username gaowei
存入hash类型值 myhast存的值为username:gaowei
hget key field
返回指定的key中的field的值
hset myhash username
返回值为gaowei
hdel key field [field … ]
可以删除一个或多个字段,返回值是被删除的字段个数
hdel myhash username
hdel myhash password
hgetall key
可以获取该键的所有数据
hgetall myhash
lpush key values[value1 value2…]
在指定的key所关联的list的头部插入所有的values,
如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。
插入成功,返回元素的个数
lpush mylist a b c
lpop key
返回并弹出指定的key关联的链表中的第一个元素,即头部元素
如果该key不存在,返回nil;
若key存在,则返回链表的头部元素。
lpop mylist
c
lpop mylist
b
rpop key
从尾部弹出元素。
lpush mylist a b c
rpop mylist
a
lrange key
遍历该键的所有数据
lrange key 0 2
返回0 1 2
lrange key 0 -1
返回所有
sadd key values[value1、value2…]
向set中添加数据,如果该key的值已有则不会重复添加
sadd myset a b c
smembers key
获取set中所有的成员
smembers myset
srem key members[member1、member2…]
删除set中指定的成员
srem myset a b
zadd key values[value1、value2…]
zadd mysort 5 zs 10 lisi 7 wc 8 xk
zrange key 索引 索引
zrange mysort 0 -1
zrem key value
zrem mysort lisi
keys pattern
获取所有与pattern匹配的key,返回所有与该key匹配的keys。
*表示任意一个或多个字符,?表示任意一个字符
keys *
del key1 key2…
删除指定的key
del myset
exists key
判断该key是否存在,1代表存在,0代表不存在
exists mysort
type key
获取指定key的类型。该命令将以字符串的格式返回
返回的字符串为string、list、set、hash,如果key不存在返回none
type mysort
?
RDB持久化(默认支持,无需配置)
该机制是指在 指定的时间间隔 内将内存中的数据集快照写入磁盘。
AOF持久化
该机制将以日志的形式记录服务器所处理的每一个写操作
在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。
无持久化
我们可以通过配置的方式禁用Redis服务器的持久化功能
这样我们就可以将Redis视为一个功能加强版的memcached了
redis可以同时使用RDB和AOF
?
RDB持久化机制优点
一旦采用该方式,那么你的整个Redis数据库将只包含一个文件
这对于文件备份而言是非常完美的
RDB持久化机制缺点
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
快照触发条件
客户端执行命令save和bgsave会生成快照;
根据配置文件save m n规则进行自动快照;
主从复制时,从库全量复制同步主库数据,此时主库会执行bgsave命令进行快照;
客户端执行数据库清空命令FLUSHALL时候,触发快照;
客户端执行shutdown关闭redis时,触发快照;
RDB持久化机制的配置
save m n
配置快照(rdb)促发规则,格式:save <seconds> <changes>
save 900 1 900秒内至少有1个key被改变则做一次快照
save 300 10 300秒内至少有10个key被改变则做一次快照
save 60 10000 60秒内至少有10000个key被改变则做一次快照
#关闭该规则使用save “ ”
dbfilename dump.rdb
rdb持久化存储数据库文件名,默认为dump.rdb
stop-write-on-bgsave-error yes
yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。
rdbchecksum yes
在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
dir "./"
数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限
rdbcompression yes
是否开启RDB文件压缩,该功能可以节约磁盘空间
/usr/local/redis-4.0.9/6379/bin
./redis-cli
config get appendonly
查询配置状态
config set appendonly yes
修改配置
config rewrite
写入到redis.conf中,使配置生效
开启后,在/usr/local/redis-4.0.9/6379/bin目录下,会生成appendonly.aof文件
在redis.conf配置文件中修改
appendfsync
always
每执行一次更新命令,持久化一次
appendfsync
everysec
每秒钟持久化一次
appendfsync
no
不持久化
?
cd /usr/local/redis-4.0.9/6379/bin
./redis-cli
查看密码
config get requirepass
初始化Redis密码:
requirepass这个就是配置redis文件访问密码的参数
vi /usr/local/redis-4.0.9/6379/bin/redis.conf
修改对应参数
requirepass 123456
需重启Redis才能生效
不重启Redis设置密码
config set requirepass 123456
config rewrite
验证
auth 123456
?
commons-pool2-2.3.jar
jedis-2.7.0.jar
new Jedis(host, port)
创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口
set(key,value)
设置字符串类型的数据
get(key)
获得字符串类型的数据
hset(key,field,value)
设置哈希类型的数据
hget(key,field)
获得哈希类型的数据
lpush(key,values)
设置列表类型的数据
lpop(key)
列表左面弹栈
rpop(key)
列表右面弹栈
del(key)
删除指定的key
public void testJedis(){
//1 设置ip地址和端口
Jedis jedis = new Jedis("localhost", 6379);
//2 设置数据
jedis.set("name", "fmjava");
//3 获得数据
String name = jedis.get("name");
System.out.println(name);
//4 释放资源
jedis.close();
}
public void testJedisPool(){
//1 获得连接池配置对象,设置配置项
JedisPoolConfig config = new JedisPoolConfig();
// 1.1 最大连接数
config.setMaxTotal(30);
// 1.2 最大空闲连接数
config.setMaxIdle(10);
//2 获得连接池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
//3 获得核心对象
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4 设置数据
jedis.set("name", "fmjava");
//5 获得数据
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
// 虚拟机关闭时,释放pool资源
if(jedisPool != null){
jedisPool.close();
}
}
}
? 1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类 ? 2.针对jedis客户端中大量api进行了归类封装 ? SetOperations:set类型数据操作 ? ZSetOperations:zset类型数据操作 ? HashOperations:针对map类型的数据操作 ? ListOperations:针对list类型的数据操作 ? ValueOperations:简单K-V操作
? 1.构建Maven工程 SpringDataRedisDemo jar工程 ? 2.引入Spring/Jedis和SpringDataRedis依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
</dependencies>
? 4.在src/main/resources建立redis-config.properties
redis.host=192.168.1.88
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
? 5.在src/main/resources创建applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:*.properties" />
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>
? 6.建立TestString测试字符串操作方法 ?
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSet() {
redisTemplate.boundValueOps("name").set("myxq");
}
@Test
public void testGet() {
String name = (String) redisTemplate.boundValueOps("name").get();
System.out.println("name=" + name);
}
@Test
public void testDelete() {
redisTemplate.delete("name");
}
}
? 7.建立TestList测试List操作方法
?
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestList {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testLpush() {
redisTemplate.boundListOps("myListKey").leftPush("001");
redisTemplate.boundListOps("myListKey").leftPush("002");
redisTemplate.boundListOps("myListKey").leftPush("003");
redisTemplate.boundListOps("myListKey").leftPush("004");
}
@Test
public void testRpush() {
redisTemplate.boundListOps("myListKey").rightPush("001");
redisTemplate.boundListOps("myListKey").rightPush("002");
redisTemplate.boundListOps("myListKey").rightPush("003");
redisTemplate.boundListOps("myListKey").rightPush("004");
}
@Test
public void testRange() {
List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
for (String s : myListKey) {
System.out.println("value=" + s);
}
}
@Test
public void testDelete() {
redisTemplate.delete("myListKey");
}
}
? 8.建立TestHash测试hash
? 示例代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestHash {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testPut() {
redisTemplate.boundHashOps("keyname1").put("name", "zs");
redisTemplate.boundHashOps("keyname1").put("age", "20");
redisTemplate.boundHashOps("keyname1").put("phone", "121");
redisTemplate.boundHashOps("keyname1").put("email", "1@qq.com");
}
@Test
public void testGetOne() {
String name = (String)redisTemplate.boundHashOps("keyname1").get("name");
System.out.println("name =" + name);
}
@Test
public void testGetAll() {
//获取所有的entries
Map<String, String> testHash = (Map<String, String>)redisTemplate.boundHashOps("keyname1").entries();
Set<Map.Entry<String, String>> entries = testHash.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key=" + entry.getKey());
System.out.println("value=" + entry.getValue());
}
}
@Test
public void testDeleteOne() {
redisTemplate.boundHashOps("keyname1").delete("name");
}
@Test
public void testDeleteAll() {
redisTemplate.delete("keyname1");
}
}
<!-- Jackson Json处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
redis.host=192.168.1.88
redis.port=6379
redis.pass=123456
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:/properties/*.properties" />
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>
public class Constants {
public static final String CONTENT_LIST_REDIS = "content";
}
?
?
@Override
public List<Content> findByCategoryIdFromRedis(Long categoryId) {
//1. 首先根据分类id到redis中获取数据
List<Content> contentList = (List<Content>)redisTemplate
.boundHashOps(Constants.CONTENT_LIST_REDIS)
.get(categoryId);
//2. 如果redis中没有数据则到数据库中获取数据
if (contentList == null) {
//3. 如果数据库中获取到数据, 则放入redis中一份
contentList = findByCategoryId(categoryId);
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).put(categoryId, contentList);
}
return contentList;
}
?
?
@Override
public void add(Content content) {
//1. 将新广告添加到数据库中
contentDao.insertSelective(content);
//2. 根据分类id, 到redis中删除对应分类的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
}
?
@Override
public void delete(Long[] ids) {
if (ids != null) {
for (Long id : ids) {
//1. 根据广告id, 到数据库中查询广告对象
Content content = contentDao.selectByPrimaryKey(id);
//2. 根据广告对象中的分类id, 删除redis中对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
//3. 根据广告id删除数据库中的广告数据
contentDao.deleteByPrimaryKey(id);
}
}
}
?
@Override
public void update(Content content) {
//1. 根据广告id, 到数据库中查询原来的广告对象
Content oldContent = contentDao.selectByPrimaryKey(content.getId());
//2. 根据原来的广告对象中的分类id, 到redis中删除对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(oldContent.getCategoryId());
//3. 根据传入的最新的广告对象中的分类id, 删除redis中对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
//4. 将新的广告对象更新到数据库中
contentDao.updateByPrimaryKeySelective(content);
}
标签:写文件 const 发包 sorted 存在 硬盘 write nal 方案
原文地址:https://www.cnblogs.com/mumuyinxin/p/11706759.html