Mongodb副本集集群

一、副本集了解

1、副本集

MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务。 副本集可提供冗余和高可用性,是所有生产部署的基础。也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库挂掉时,在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载。

2、mongodb复制原理

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

MongoDB复制结构图如下所示:

mongodb复制结构图

以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。

3、mongodb的读写分离

1》Primary 机器接收所有的写操作(无法改变的),我们可以配置read preference,使得读操作可以发生在secondary机器上。如果读操作发生在primary机器上,那么数据就是强一致性的;如果读操作发生secondary 就可能数据不一致
对于secondary机器,可以进行如下配置.
a) 禁止某台secondary机器成为primary机器,priority 为0
b) 禁止客户端读取某台机器的数据。隐藏成员。
c) 仅记录历史快照的secondary,延迟成员。比如说延迟一小时。
d) 最常见的secondary机器依然是进行数据一部复制与保持数据的一致性。
e) 副本集最多有50台机器,其中具有投票功能的机器数量最多是7台。

如果进行读写分离,那么要注意到是读会有延迟。
Secondary 机器要通过oplog 异步复制primary机器的数据,因此从整体来看,primary与secondary机器的读速度是大体相当的。
默认情况下都是从primary 机器上面读取的。
2》对于Read preference(读取数据首选项设置):
a) primary(默认值)读操作都从这个地方读取
b) primaryPreferred(大多数情况primary 读取,一旦primary不可用,就从secondary读取)
c) secondary(从secondary读取)
d) secondaryPreferred(优先从secondary读取)
e) nearest(延迟最低机器)

3》关于延迟成员(delayed member)
a) 延迟成员的priority必须为0,表示它无法成为primary
b) 延迟成员也是隐藏成员,应用是无法通过延迟成员查询数据的,
c) 可以对primary的选举进行投票。

请确保副本集中成员的个数为奇数,如果是偶数的话,请添 加一个哨兵成员。
4》关于MongoDB投票与故障恢复
a) MongoDB要求投票时系统中可用的机器数量要是全体副本集成员个数的大多数(一半以上)。
b) 如果副本集中有3(1主 2副)台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以使用吗?(1台)
c) 如果副本集中有4台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以使用吗?(1台)
d) 如果副本集中有5台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以使用吗?(2台)
e) 如果副本集中有6台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以使用吗?(2台)
f) 如果副本集中有7台机器,那么有几台机器宕掉还可以确保MongoDB副本集可以使用吗?(3台)

4、副本集构成

副本集有两种类型,三种角色。

两种类型:

1》主节点(Primary)类型:数据操作的主要连接点,可读写
2》次、辅助、从节点(Secondaries)类型:数据冗余备份节点,可以读(需要设置)或选举

三种角色:

1》主要成员(Primary):主要接收所有写操作。就是主节点。
2》副本成员(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要配置)。是默认的一种从节点类型。
3》仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

5、安装包

打开MongoDB官网 首页,选择头部的Products(产品)中的二级标题Community Edition(社区版)下面的Community Server(社区服务)。
选择合适的Community Server版本下载即可。
MongoDB的版本命名规范如:x.y.z;
y为奇数时表示当前版本为开发版,如:1.5.2、4.1.13;
y为偶数时表示当前版本为稳定版,如:1.6.3、4.0.10;
z是修正版本号,数字越大越好。

二、副本集搭建

1、副本集架构

架构

2、部署主节点

5.0.7 Centos7 tgz 快速下载连接
1》基础环境

cd /usr/local/src/
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.7.tgz
tar -xvf mongodb-linux-x86_64-rhel70-5.0.7.tgz
mv mongodb-linux-x86_64-rhel70-5.0.7 mongodb
cd mongodb/
mkdir {data,log,conf,pid}

2》创建keyfile
keyfile是用于mongodb集群内部成员认证用的。keyfile主要是用于集群内部认证用,唯一的要求是6-1024长度内容,集群内部成员该文件值必须一样才可以。

openssl rand -base64 20 > keyfile
chmod 400 keyfile

3》配置文件(/usr/local/src/mongodb/conf/mongo.conf)

systemLog:
  #MongoDB发送所有日志输出的目标指定为文件  
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径  
  path: "/usr/local/src/mongodb/log/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾  
  logAppend: true
storage:
  #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod
  dbPath: "/usr/local/src/mongodb/data"
  journal:
    #启用或禁用持久性日志以确保数据文件保持有效和可恢复。     
    enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式。  
  fork: true
  #指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
  pidFilePath: "/usr/local/src/mongodb/pid/mongod.pid"
  #从中加载时区数据库的完整路径
#  timeZoneInfo: /usr/share/zoneinfo
net:
  #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
  #bindIpAll: true
  #服务实例绑定的IP,0.0.0.0让所有机器都能连接。
  bindIp: 0.0.0.0
  #绑定的端口  
  port: 27017
# 安全配置  
security:
  # 配置密码文件
  keyFile: /usr/local/src/mongodb/keyfile
replication:
  #副本集的名称  
  replSetName: "myrs"

4》配置环境变量

echo "export PATH=$PATH:/usr/local/src/mongodb/bin" >> /etc/profile
source /etc/profile

5》测试服务

[root@centos7 conf]# mongod -f /usr/local/src/mongodb/conf/mongo.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 10833
child process started successfully, parent exiting

停止服务并删除生成的数据

[root@centos7 conf]# ps -ef |grep mongo
root      10833      1  4 10:51 ?        00:00:02 mongod -f /usr/local/src/mongodb/conf/mongo.conf
root      10965  10356  0 10:52 pts/5    00:00:00 grep --color=auto mongo
[root@centos7 conf]# kill -9 10833
[root@centos7 conf]# rm -rf {data/*,log/*,pid/*}

6》做成系统服务

[root@centos7 conf]# cat /usr/lib/systemd/system/mongod.service
[Unit]
Description=mongodb service
Documentation=https://docs.mongodb.com/manual/
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/src/mongodb/pid/mongod.pid
ExecStart=/usr/local/src/mongodb/bin/mongod -f /usr/local/src/mongodb/conf/mongo.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/usr/local/src/mongodb/bin/mongod --shutdown --config /usr/local/src/mongodb/conf/mongo.conf
PrivateTmp=true
Restart=always
RestartSec=1
[Install]
WantedBy=multi-user.target

3、配置其他两个节点

1》将主节点的文件夹直接复制到其他节点

scp -r mongodb root@192.168.43.103:/usr/local/src/
echo "export PATH=$PATH:/usr/local/src/mongodb/bin" >> /etc/profile
source /etc/profile

4、初始化副本集

1》启动三个节点

mongod -f /usr/local/src/mongodb/conf/mongo.conf

2》登录主节点,初始化副本集

> use admin
switched to db admin
>config={
... _id: "myrs",
... members: [
... { _id: 0, host: "192.168.43.101:27017",priority:2 },
... { _id: 1, host: "192.168.43.102:27017",priority:1 },
... { _id: 2, host: "192.168.43.103:27017",arbiterOnly:true }
... ] }
{
    "_id" : "myrs",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.43.101:27017",
            "priority" : 2
        },
        {
            "_id" : 1,
            "host" : "192.168.43.102:27017",
            "priority" : 1
        },
        {
            "_id" : 2,
            "host" : "192.168.43.103:27017",
            "arbiterOnly" : true
        }
    ]
}
> rs.initiate(config)
{ "ok" : 1 }
myrs:SECONDARY>

查看副本集状态

myrs:SECONDARY> rs.status()

3》新增用户
在这之前我们得建立一个账户,后面配置用户名密码远程连接。在mongodb 中账户和用户都是在admin 这个数据库里面,我们添加一个root 用户。

myrs:PRIMARY> db.createUser({
user:'root',
pwd:'123456',
roles:[{role:'root',db:'admin'}]
 })
Successfully added user: {
    "user" : "root",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

退出当前页面,重新登录客户端,在进行登录验证

myrs:PRIMARY> use admin
switched to db admin
myrs:PRIMARY> db.auth("root","123456")
1
myrs:PRIMARY> show tables
system.keys
system.users
system.version

4》测试副本集
1、主节点新增用户表数据

myrs:PRIMARY> use admin
switched to db admin
myrs:PRIMARY> db.auth("root","123456")
1
myrs:PRIMARY> use test
switched to db test
myrs:PRIMARY> db.createCollection("test")
{
    "ok" : 1,
    "$clusterTime" : {
        "clusterTime" : Timestamp(1693203173, 1),
        "signature" : {
            "hash" : BinData(0,"BOHoJlIVYIfbq1q+q4bu5v1X1sc="),
            "keyId" : NumberLong("7272208560816128004")
        }
    },
    "operationTime" : Timestamp(1693203173, 1)
}
myrs:PRIMARY> db.test.insert({"name":"zhao"})
WriteResult({ "nInserted" : 1 })
myrs:PRIMARY> db.test.find()
{ "_id" : ObjectId("64ec3b633bc7c30a6c051a7f"), "name" : "zhao" }

2、次节点查看数据

myrs:SECONDARY> use admin
switched to db admin
myrs:SECONDARY> db.auth("root","123456")
1
myrs:SECONDARY> use test
switched to db test
myrs:SECONDARY> show tables  #数据库报错从节点没有读权限,设置一下就可以
uncaught exception: Error: listCollections failed: {
    "topologyVersion" : {
        "processId" : ObjectId("64ec0e80558c6973a9dc9fed"),
        "counter" : NumberLong(9)
    },
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotPrimaryNoSecondaryOk",
    "$clusterTime" : {
        "clusterTime" : Timestamp(1693203440, 1),
        "signature" : {
            "hash" : BinData(0,"TP78j5iN5kQGp/sy9VZoj0FEXio="),
            "keyId" : NumberLong("7272208560816128004")
        }
    },
    "operationTime" : Timestamp(1693203440, 1)
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:723:15
DB.prototype.getCollectionInfos@src/mongo/shell/db.js:771:16
shellHelper.show@src/mongo/shell/utils.js:943:9
shellHelper@src/mongo/shell/utils.js:838:15
@(shellhelp2):1:1
myrs:SECONDARY> db.setSlaveOk()  #这个命令太老了,使用db.setSecondaryOk()进行执行
WARNING: setSlaveOk() is deprecated and may be removed in the next major release. Please use setSecondaryOk() instead.
myrs:SECONDARY> db.setSecondaryOk()
myrs:SECONDARY> db.test.find()
{ "_id" : ObjectId("64ec3b633bc7c30a6c051a7f"), "name" : "zhao" }

5、副本集命令

命令

命令

1》rs.status()

myrs:PRIMARY> rs.status()
{
        "set" : "myrs", // 副本集的名字
        "date" : ISODate("2022-04-17T01:45:08.287Z"),
        "myState" : 1, //说明状态正常
        "term" : NumberLong(8),
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "majorityVoteCount" : 2,
        "writeMajorityCount" : 2,
        "votingMembersCount" : 3,
        "writableVotingMembersCount" : 2,
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1650159901, 1),
                        "t" : NumberLong(8)
                },
                "lastCommittedWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1650159901, 1),
                        "t" : NumberLong(8)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1650159901, 1),
                        "t" : NumberLong(8)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1650159901, 1),
                        "t" : NumberLong(8)
                },
                "lastAppliedWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                "lastDurableWallTime" : ISODate("2022-04-17T01:45:01.392Z")
        },
        "lastStableRecoveryTimestamp" : Timestamp(1650159841, 1),
        "electionCandidateMetrics" : {
                "lastElectionReason" : "electionTimeout",
                "lastElectionDate" : ISODate("2022-04-17T01:40:21.198Z"),
                "electionTerm" : NumberLong(8),
                "lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(0, 0),
                        "t" : NumberLong(-1)
                },
                "lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1650116073, 1),
                        "t" : NumberLong(7)
                },
                "numVotesNeeded" : 2,
                "priorityAtElection" : 1,
                "electionTimeoutMillis" : NumberLong(10000),
                "numCatchUpOps" : NumberLong(0),
                "newTermStartDate" : ISODate("2022-04-17T01:40:21.318Z"),
                "wMajorityWriteAvailabilityDate" : ISODate("2022-04-17T01:40:26.886Z")
        },
        "members" : [
                {
                        "_id" : 0,
                        "name" : "192.168.31.128:27017",
                        "health" : 1, // 节点是健康的
                        "state" : 1,
                        "stateStr" : "PRIMARY", // 角色是主节点
                        "uptime" : 304,
                        "optime" : {
                                "ts" : Timestamp(1650159901, 1),
                                "t" : NumberLong(8)
                        },
                        "optimeDate" : ISODate("2022-04-17T01:45:01Z"),
                        "lastAppliedWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                        "lastDurableWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1650159621, 1),
                        "electionDate" : ISODate("2022-04-17T01:40:21Z"),
                        "configVersion" : 1,
                        "configTerm" : 8,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                },
                {
                        "_id" : 1,
                        "name" : "192.168.31.129:27017",
                        "health" : 1,
                        "state" : 7,
                        "stateStr" : "ARBITER", // 仲裁节点
                        "uptime" : 297,
                        "lastHeartbeat" : ISODate("2022-04-17T01:45:06.556Z"),
                        "lastHeartbeatRecv" : ISODate("2022-04-17T01:45:06.574Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "configVersion" : 1,
                        "configTerm" : 8
                },
                {
                        "_id" : 2,
                        "name" : "192.168.31.130:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY", // 次节点
                        "uptime" : 280,
                        "optime" : {
                                "ts" : Timestamp(1650159901, 1),
                                "t" : NumberLong(8)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1650159901, 1),
                                "t" : NumberLong(8)
                        },
                        "optimeDate" : ISODate("2022-04-17T01:45:01Z"),
                        "optimeDurableDate" : ISODate("2022-04-17T01:45:01Z"),
                        "lastAppliedWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                        "lastDurableWallTime" : ISODate("2022-04-17T01:45:01.392Z"),
                        "lastHeartbeat" : ISODate("2022-04-17T01:45:06.798Z"),
                        "lastHeartbeatRecv" : ISODate("2022-04-17T01:45:08.217Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncSourceHost" : "192.168.31.128:27017",
                        "syncSourceId" : 0,
                        "infoMessage" : "",
                        "configVersion" : 1,
                        "configTerm" : 8
                }
        ],
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1650159901, 1),
                "signature" : {
                        "hash" : BinData(0,"rTJm51/Wo0vX7A3Lbgaz9Rthr8c="),
                        "keyId" : NumberLong("7087113268703002629")
                }
        },
        "operationTime" : Timestamp(1650159901, 1)
}

2》rs.conf()

myrs:PRIMARY> rs.conf()
{
        "_id" : "myrs", // 副本集的配置数据存储的主键值,默认就是副本集的名字
        "version" : 1,
        "term" : 8,
        "members" : [ // 副本集成员数组
                {
                        "_id" : 0,
                        "host" : "192.168.31.128:27017",
                        "arbiterOnly" : false, // 是否是仲裁节点
                        "buildIndexes" : true,
                        "hidden" : false, // 是否是隐藏节点
                        "priority" : 1, // 优先级(权重值)
                        "tags" : {
                                
                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 1,
                        "host" : "192.168.31.129:27017",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {
                                
                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "192.168.31.130:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                                
                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                }
        ],
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "settings" : {  // 副本集的参数配置。
                "chainingAllowed" : true,
                "heartbeatIntervalMillis" : 2000,
                "heartbeatTimeoutSecs" : 10,
                "electionTimeoutMillis" : 10000,
                "catchUpTimeoutMillis" : -1,
                "catchUpTakeoverDelayMillis" : 30000,
                "getLastErrorModes" : {
                        
                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                },
                "replicaSetId" : ObjectId("625a7bee81773d2b614e1610")
        }
}

3》修改优先级
1、先将配置导入cfg变量

myrs:PRIMARY> cfg=rs.conf()

2、然后修改值(ID号默认从0开始)

myrs:PRIMARY> cfg.members[2].priority=2
2

3、重新加载配置

myrs:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1650162053, 1),
                "signature" : {
                        "hash" : BinData(0,"Wap6hq5wxmpqQkQ/vHrl1v8/bAY="),
                        "keyId" : NumberLong("7087113268703002629")
                }
        },
        "operationTime" : Timestamp(1650162053, 1)
}

稍等片刻会重新开始选举。
4》spring boot 集成副本集
1、pom.xml中引入依赖

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2、在application.yml中配置副本集

spring:
  data:
    mongodb:
      uri: mongodb://zs:123456@192.168.43.101:27017,192.168.43.102:27017,192.168.43.103:27017/db1?replicaSet=myrs&readPreference=secondaryPreferred&connectTimeoutMS=300000&slaveOk=true

3、mongodb客户端连接语法

mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

mongodb:// 这是固定的格式,必须要指定。
username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登录这个数据库
host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。
portX 可选的指定端口,如果不填,默认为27017
/database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开test 数据库。
?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开


参数
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容