关于数据一致性的思考

写代码会碰到数据一致性的问题。为了保证数据的一致性用到了事务,为了简化代码的编写,用到了AOP的思想进行面向切面编程。

作者:徐立

开始的时候所有的业务逻辑都放在action里,由于主业务相关逻辑没有放在同一个事务中就导致了数据有可能出现不一致,有的时候用户操作失败却入库成功,这个时候把所有的业务放在一个事务中,这样可以保证数据一致,但是会引来另一个问题,增值业务报错会响应到主业务逻辑,为了不让增值业务影响主业务,这个时候我想有4种办法解决这种问题。

  1. 增值业务在action中调用service的另一个方法(缺点是:编译器可能对代码重排序导致一些数据没有初始化,先执行了增值业务)
  2. 在同一个service方法中另外调用一个方法,在该方法上加上事务注解(一般是当前事务挂起,新开启另一个事务)。(缺点是只适用cglib代理,不适用JDK动态代理。JDK动态代理的是接口,方法内调用其他方法不会在执行切面方法,cglib是生成子类代理的方法,可以对方法内部调用其他公有方法进行拦截,但是不会拦截私有方法和final修锁的方法)
  3. 增值业务放在另一个线程中这样和原业务就没有任何关系,并且提高了业务执行速度,但是新的线程会消耗系统资源,可以利用线程池进行线程复用,降低资源消耗
  4. 所有的增值业务都放在action中,但是如果增值业务过多会导致代码理解难度提高,从而提高成本。
    还有一种代理是javaassit,可以直接操作字节码文件但是使用比较复杂。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个多线程TCP通信的例子,其中接收到的数据类型为自定义类型MyData,收到的数据存储在QMap<QString, QVector<MyData>>中,主线程进行数据分类和一致性比较。发送的数据通过QVector<MyData>发送给子线程。 在头文件中定义以下内容: ```cpp #ifndef TCPCOMMUNICATION_H #define TCPCOMMUNICATION_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> #include <QThread> #include <QVector> #include <QMap> struct MyData { QString name; int value; }; class TcpCommunication : public QObject { Q_OBJECT public: explicit TcpCommunication(QObject *parent = nullptr); void start(); signals: void newDataReceived(const QString& name, const QVector<MyData>& data); public slots: void newConnection(); void readData(); void sendData(const QVector<MyData>& data); private: QTcpServer *m_server; QTcpSocket *m_socket; QMap<QString, QVector<MyData>> m_dataReceived; }; #endif // TCPCOMMUNICATION_H ``` 在源文件中实现以下内容: ```cpp #include "tcpcommunication.h" TcpCommunication::TcpCommunication(QObject *parent) : QObject(parent) { m_server = new QTcpServer(this); m_socket = new QTcpSocket(this); connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); connect(m_socket, SIGNAL(disconnected()), m_socket, SLOT(deleteLater())); } void TcpCommunication::start() { if (m_server->listen(QHostAddress::Any, 1234)) { qDebug() << "Server started"; } else { qDebug() << "Server failed to start"; } } void TcpCommunication::newConnection() { m_socket = m_server->nextPendingConnection(); } void TcpCommunication::readData() { QByteArray data = m_socket->readAll(); QDataStream stream(&data, QIODevice::ReadOnly); QVector<MyData> newDataVector; while (!stream.atEnd()) { MyData newData; stream >> newData.name >> newData.value; newDataVector.append(newData); } emit newDataReceived(newDataVector); } void TcpCommunication::sendData(const QVector<MyData>& data) { QByteArray dataToSend; QDataStream stream(&dataToSend, QIODevice::WriteOnly); for (const auto& newData : data) { stream << newData.name << newData.value; } m_socket->write(dataToSend); } ``` 在主函数中创建一个TcpCommunication对象,使用QThread将其移动到子线程中运行,并且将接收到的数据放入QMap<QString, QVector<MyData>>中: ```cpp #include <QCoreApplication> #include <QThread> #include "tcpcommunication.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMap<QString, QVector<MyData>> dataMap; TcpCommunication tcpCommunication; QThread thread; tcpCommunication.moveToThread(&thread); QObject::connect(&thread, SIGNAL(started()), &tcpCommunication, SLOT(start())); QObject::connect(&tcpCommunication, &TcpCommunication::newDataReceived, [&](const QString& name, const QVector<MyData>& data){ dataMap[name] = data; }); QObject::connect(&tcpCommunication, SIGNAL(finished()), &thread, SLOT(quit())); QObject::connect(&tcpCommunication, SIGNAL(finished()), &tcpCommunication, SLOT(deleteLater())); QObject::connect(&thread, SIGNAL(finished()), &thread, SLOT(deleteLater())); thread.start(); return a.exec(); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值